diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java index 156995e26d..4e19b05334 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java @@ -67,8 +67,7 @@ public class AppLinkActivity extends FragmentActivity mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner(); mAfterDirectoryInitializationRunner.run(this, true, () -> tryPlay(playAction)); - IntentFilter gameFileCacheIntentFilter = new IntentFilter( - GameFileCacheService.BROADCAST_ACTION); + IntentFilter gameFileCacheIntentFilter = new IntentFilter(GameFileCacheService.DONE_LOADING); BroadcastReceiver gameFileCacheReceiver = new BroadcastReceiver() { @@ -109,7 +108,7 @@ public class AppLinkActivity extends FragmentActivity // If game == null and the load isn't done, wait for the next GameFileCacheService broadcast. // If game == null and the load is done, call play with a null game, making us exit in failure. - if (game != null || GameFileCacheService.hasLoadedCache()) + if (game != null || !GameFileCacheService.isLoading()) { play(action, game); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/PlatformPagerAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/PlatformPagerAdapter.java index f18c7e5438..eef3c5b77d 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/PlatformPagerAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/PlatformPagerAdapter.java @@ -10,6 +10,7 @@ import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.ui.platform.Platform; @@ -18,6 +19,7 @@ import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesFragment; public class PlatformPagerAdapter extends FragmentPagerAdapter { private Context mContext; + private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener; private final static int[] TAB_ICONS = { @@ -26,17 +28,19 @@ public class PlatformPagerAdapter extends FragmentPagerAdapter R.drawable.ic_folder }; - public PlatformPagerAdapter(FragmentManager fm, Context context) + public PlatformPagerAdapter(FragmentManager fm, Context context, + SwipeRefreshLayout.OnRefreshListener onRefreshListener) { super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); mContext = context; + mOnRefreshListener = onRefreshListener; } @NonNull @Override public Fragment getItem(int position) { - return PlatformGamesFragment.newInstance(Platform.fromPosition(position)); + return PlatformGamesFragment.newInstance(Platform.fromPosition(position), mOnRefreshListener); } @Override diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java index a15e734d0b..e359d701bc 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java @@ -116,6 +116,8 @@ public class GameFileCache return cacheChanged; } + public native int getSize(); + public native GameFile[] getAllGames(); public native GameFile addOrGet(String gamePath); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java index ab295c5550..34bf1afa0a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java @@ -15,7 +15,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; /** @@ -23,7 +23,17 @@ import java.util.concurrent.atomic.AtomicReference; */ public final class GameFileCacheService extends IntentService { - public static final String BROADCAST_ACTION = "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_UPDATED"; + /** + * This is broadcast when the contents of the cache change. + */ + public static final String CACHE_UPDATED = "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_UPDATED"; + + /** + * This is broadcast when the service is done with all requested work, regardless of whether + * the contents of the cache actually changed. (Maybe the cache was already up to date.) + */ + public static final String DONE_LOADING = + "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_DONE_LOADING"; private static final String ACTION_LOAD = "org.dolphinemu.dolphinemu.LOAD_GAME_FILE_CACHE"; private static final String ACTION_RESCAN = "org.dolphinemu.dolphinemu.RESCAN_GAME_FILE_CACHE"; @@ -31,8 +41,7 @@ public final class GameFileCacheService extends IntentService private static GameFileCache gameFileCache = null; private static final AtomicReference gameFiles = new AtomicReference<>(new GameFile[]{}); - private static final AtomicBoolean hasLoadedCache = new AtomicBoolean(false); - private static final AtomicBoolean hasScannedLibrary = new AtomicBoolean(false); + private static final AtomicInteger unhandledIntents = new AtomicInteger(0); public GameFileCacheService() { @@ -96,14 +105,9 @@ public final class GameFileCacheService extends IntentService return new String[]{gameFile.getPath(), secondFile.getPath()}; } - public static boolean hasLoadedCache() + public static boolean isLoading() { - return hasLoadedCache.get(); - } - - public static boolean hasScannedLibrary() - { - return hasScannedLibrary.get(); + return unhandledIntents.get() != 0; } private static void startService(Context context, String action) @@ -119,6 +123,8 @@ public final class GameFileCacheService extends IntentService */ public static void startLoad(Context context) { + unhandledIntents.getAndIncrement(); + new AfterDirectoryInitializationRunner().run(context, false, () -> startService(context, ACTION_LOAD)); } @@ -130,6 +136,8 @@ public final class GameFileCacheService extends IntentService */ public static void startRescan(Context context) { + unhandledIntents.getAndIncrement(); + new AfterDirectoryInitializationRunner().run(context, false, () -> startService(context, ACTION_RESCAN)); } @@ -156,9 +164,11 @@ public final class GameFileCacheService extends IntentService { gameFileCache = temp; gameFileCache.load(); - updateGameFileArray(); - hasLoadedCache.set(true); - sendBroadcast(); + if (gameFileCache.getSize() != 0) + { + updateGameFileArray(); + sendBroadcast(CACHE_UPDATED); + } } } @@ -169,11 +179,18 @@ public final class GameFileCacheService extends IntentService { boolean changed = gameFileCache.scanLibrary(); if (changed) + { updateGameFileArray(); - hasScannedLibrary.set(true); - sendBroadcast(); + sendBroadcast(CACHE_UPDATED); + } } } + + int intentsLeft = unhandledIntents.decrementAndGet(); + if (intentsLeft == 0) + { + sendBroadcast(DONE_LOADING); + } } private void updateGameFileArray() @@ -183,8 +200,8 @@ public final class GameFileCacheService extends IntentService gameFiles.set(gameFilesTemp); } - private void sendBroadcast() + private void sendBroadcast(String action) { - LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_ACTION)); + LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(action)); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java index 2beb2112f2..8849494d26 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java @@ -13,6 +13,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.viewpager.widget.ViewPager; import com.google.android.material.floatingactionbutton.FloatingActionButton; @@ -28,6 +29,7 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; import org.dolphinemu.dolphinemu.services.GameFileCacheService; import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView; +import org.dolphinemu.dolphinemu.utils.Action1; import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.FileBrowserHelper; @@ -38,7 +40,8 @@ import org.dolphinemu.dolphinemu.utils.StartupHandler; * The main Activity of the Lollipop style UI. Manages several PlatformGamesFragments, which * individually display a grid of available games for each Fragment, in a tabbed layout. */ -public final class MainActivity extends AppCompatActivity implements MainView +public final class MainActivity extends AppCompatActivity + implements MainView, SwipeRefreshLayout.OnRefreshListener { private ViewPager mViewPager; private Toolbar mToolbar; @@ -79,6 +82,8 @@ public final class MainActivity extends AppCompatActivity implements MainView { super.onResume(); + boolean cacheAlreadyLoading = GameFileCacheService.isLoading(); + if (DirectoryInitialization.shouldStart(this)) { DirectoryInitialization.start(this); @@ -90,16 +95,18 @@ public final class MainActivity extends AppCompatActivity implements MainView // In case the user changed a setting that affects how games are displayed, // such as system language, cover downloading... - refetchMetadata(); + forEachPlatformGamesView(PlatformGamesView::refetchMetadata); - if (sShouldRescanLibrary) + if (sShouldRescanLibrary && !cacheAlreadyLoading) { - GameFileCacheService.startRescan(this); - } - else - { - sShouldRescanLibrary = true; + new AfterDirectoryInitializationRunner().run(this, false, () -> + { + setRefreshing(true); + GameFileCacheService.startRescan(this); + }); } + + sShouldRescanLibrary = true; } @Override @@ -266,26 +273,42 @@ public final class MainActivity extends AppCompatActivity implements MainView return mPresenter.handleOptionSelection(item.getItemId(), this); } - public void showGames() + /** + * Called when the user requests a refresh by swiping down. + */ + @Override + public void onRefresh() { - for (Platform platform : Platform.values()) - { - PlatformGamesView fragment = getPlatformGamesView(platform); - if (fragment != null) - { - fragment.showGames(); - } - } + setRefreshing(true); + GameFileCacheService.startRescan(this); } - private void refetchMetadata() + /** + * Shows or hides the loading indicator. + */ + @Override + public void setRefreshing(boolean refreshing) + { + forEachPlatformGamesView(view -> view.setRefreshing(refreshing)); + } + + /** + * To be called when the game file cache is updated. + */ + @Override + public void showGames() + { + forEachPlatformGamesView(PlatformGamesView::showGames); + } + + private void forEachPlatformGamesView(Action1 action) { for (Platform platform : Platform.values()) { PlatformGamesView fragment = getPlatformGamesView(platform); if (fragment != null) { - fragment.refetchMetadata(); + action.call(fragment); } } } @@ -302,7 +325,7 @@ public final class MainActivity extends AppCompatActivity implements MainView private void setPlatformTabsAndStartGameFileCacheService() { PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter( - getSupportFragmentManager(), this); + getSupportFragmentManager(), this, this); mViewPager.setAdapter(platformPagerAdapter); mViewPager.setOffscreenPageLimit(platformPagerAdapter.getCount()); mTabLayout.setupWithViewPager(mViewPager); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java index ebd43513ab..803994a67f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java @@ -53,13 +53,22 @@ public final class MainPresenter mView.setVersionString(versionName); IntentFilter filter = new IntentFilter(); - filter.addAction(GameFileCacheService.BROADCAST_ACTION); + filter.addAction(GameFileCacheService.CACHE_UPDATED); + filter.addAction(GameFileCacheService.DONE_LOADING); mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - mView.showGames(); + switch (intent.getAction()) + { + case GameFileCacheService.CACHE_UPDATED: + mView.showGames(); + break; + case GameFileCacheService.DONE_LOADING: + mView.setRefreshing(false); + break; + } } }; LocalBroadcastManager.getInstance(mContext).registerReceiver(mBroadcastReceiver, filter); @@ -87,6 +96,7 @@ public final class MainPresenter return true; case R.id.menu_refresh: + mView.setRefreshing(true); GameFileCacheService.startRescan(context); return true; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.java index b2e6b74495..8428104240 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.java @@ -23,6 +23,11 @@ public interface MainView void launchOpenFileActivity(int requestCode); + /** + * Shows or hides the loading indicator. + */ + void setRefreshing(boolean refreshing); + /** * To be called when the game file cache is updated. */ diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java index d34c3d8518..4df042df82 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java @@ -4,6 +4,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; +import android.util.TypedValue; import android.widget.Toast; import androidx.annotation.NonNull; @@ -15,6 +16,7 @@ import androidx.leanback.widget.ArrayObjectAdapter; import androidx.leanback.widget.HeaderItem; import androidx.leanback.widget.ListRow; import androidx.leanback.widget.ListRowPresenter; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; @@ -26,6 +28,7 @@ import org.dolphinemu.dolphinemu.model.GameFile; import org.dolphinemu.dolphinemu.model.TvSettingsItem; import org.dolphinemu.dolphinemu.services.GameFileCacheService; import org.dolphinemu.dolphinemu.ui.platform.Platform; +import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.FileBrowserHelper; import org.dolphinemu.dolphinemu.utils.PermissionsHandler; @@ -36,12 +39,15 @@ import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; import java.util.ArrayList; import java.util.Collection; -public final class TvMainActivity extends FragmentActivity implements MainView +public final class TvMainActivity extends FragmentActivity + implements MainView, SwipeRefreshLayout.OnRefreshListener { private static boolean sShouldRescanLibrary = true; private final MainPresenter mPresenter = new MainPresenter(this, this); + private SwipeRefreshLayout mSwipeRefresh; + private BrowseSupportFragment mBrowseFragment; private final ArrayList mGameRows = new ArrayList<>(); @@ -68,6 +74,8 @@ public final class TvMainActivity extends FragmentActivity implements MainView { super.onResume(); + boolean cacheAlreadyLoading = GameFileCacheService.isLoading(); + if (DirectoryInitialization.shouldStart(this)) { DirectoryInitialization.start(this); @@ -80,14 +88,16 @@ public final class TvMainActivity extends FragmentActivity implements MainView // such as system language, cover downloading... refetchMetadata(); - if (sShouldRescanLibrary) + if (sShouldRescanLibrary && !cacheAlreadyLoading) { - GameFileCacheService.startRescan(this); - } - else - { - sShouldRescanLibrary = true; + new AfterDirectoryInitializationRunner().run(this, false, () -> + { + setRefreshing(true); + GameFileCacheService.startRescan(this); + }); } + + sShouldRescanLibrary = true; } @Override @@ -117,6 +127,16 @@ public final class TvMainActivity extends FragmentActivity implements MainView void setupUI() { + mSwipeRefresh = findViewById(R.id.swipe_refresh); + + TypedValue typedValue = new TypedValue(); + getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true); + mSwipeRefresh.setColorSchemeColors(typedValue.data); + + mSwipeRefresh.setOnRefreshListener(this); + + setRefreshing(GameFileCacheService.isLoading()); + final FragmentManager fragmentManager = getSupportFragmentManager(); mBrowseFragment = new BrowseSupportFragment(); fragmentManager @@ -188,6 +208,15 @@ public final class TvMainActivity extends FragmentActivity implements MainView startActivityForResult(intent, requestCode); } + /** + * Shows or hides the loading indicator. + */ + @Override + public void setRefreshing(boolean refreshing) + { + mSwipeRefresh.setRefreshing(refreshing); + } + @Override public void showGames() { @@ -277,6 +306,16 @@ public final class TvMainActivity extends FragmentActivity implements MainView } } + /** + * Called when the user requests a refresh by swiping down. + */ + @Override + public void onRefresh() + { + setRefreshing(true); + GameFileCacheService.startRescan(this); + } + private void buildRowsAdapter() { ArrayObjectAdapter rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java index 50d2499705..a3f67613c0 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesFragment.java @@ -1,14 +1,17 @@ package org.dolphinemu.dolphinemu.ui.platform; import android.os.Bundle; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.adapters.GameAdapter; @@ -20,10 +23,13 @@ public final class PlatformGamesFragment extends Fragment implements PlatformGam private GameAdapter mAdapter; private RecyclerView mRecyclerView; + private SwipeRefreshLayout mSwipeRefresh; + private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener; - public static PlatformGamesFragment newInstance(Platform platform) + public static PlatformGamesFragment newInstance(Platform platform, + SwipeRefreshLayout.OnRefreshListener onRefreshListener) { - PlatformGamesFragment fragment = new PlatformGamesFragment(); + PlatformGamesFragment fragment = new PlatformGamesFragment(onRefreshListener); Bundle args = new Bundle(); args.putSerializable(ARG_PLATFORM, platform); @@ -32,6 +38,11 @@ public final class PlatformGamesFragment extends Fragment implements PlatformGam return fragment; } + public PlatformGamesFragment(SwipeRefreshLayout.OnRefreshListener onRefreshListener) + { + mOnRefreshListener = onRefreshListener; + } + @Override public void onCreate(Bundle savedInstanceState) { @@ -55,11 +66,19 @@ public final class PlatformGamesFragment extends Fragment implements PlatformGam RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), columns); mAdapter = new GameAdapter(); + TypedValue typedValue = new TypedValue(); + requireActivity().getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true); + mSwipeRefresh.setColorSchemeColors(typedValue.data); + + mSwipeRefresh.setOnRefreshListener(mOnRefreshListener); + mRecyclerView.setLayoutManager(layoutManager); mRecyclerView.setAdapter(mAdapter); mRecyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8)); + setRefreshing(GameFileCacheService.isLoading()); + showGames(); } @@ -91,8 +110,14 @@ public final class PlatformGamesFragment extends Fragment implements PlatformGam mAdapter.refetchMetadata(); } + public void setRefreshing(boolean refreshing) + { + mSwipeRefresh.setRefreshing(refreshing); + } + private void findViews(View root) { + mSwipeRefresh = root.findViewById(R.id.swipe_refresh); mRecyclerView = root.findViewById(R.id.grid_games); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesView.java index 918f40c6e0..b4ee22f985 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/platform/PlatformGamesView.java @@ -1,5 +1,8 @@ package org.dolphinemu.dolphinemu.ui.platform; +import androidx.annotation.Nullable; +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + /** * Abstraction for a screen representing a single platform's games. */ @@ -21,6 +24,11 @@ public interface PlatformGamesView */ void onItemClick(String gameId); + /** + * Shows or hides the loading indicator. + */ + void setRefreshing(boolean refreshing); + /** * To be called when the game file cache is updated. */ diff --git a/Source/Android/app/src/main/res/layout/activity_tv_main.xml b/Source/Android/app/src/main/res/layout/activity_tv_main.xml index b14f5c56d0..91f86a66ea 100644 --- a/Source/Android/app/src/main/res/layout/activity_tv_main.xml +++ b/Source/Android/app/src/main/res/layout/activity_tv_main.xml @@ -1,7 +1,20 @@ - - \ No newline at end of file + + + + + + + + + diff --git a/Source/Android/app/src/main/res/layout/fragment_grid.xml b/Source/Android/app/src/main/res/layout/fragment_grid.xml index 97faa0ac8d..adedbed4c0 100644 --- a/Source/Android/app/src/main/res/layout/fragment_grid.xml +++ b/Source/Android/app/src/main/res/layout/fragment_grid.xml @@ -4,12 +4,19 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + android:layout_marginRight="@dimen/activity_horizontal_margin"> + + + + diff --git a/Source/Android/jni/GameList/GameFileCache.cpp b/Source/Android/jni/GameList/GameFileCache.cpp index d5fce915b8..9a3bb49556 100644 --- a/Source/Android/jni/GameList/GameFileCache.cpp +++ b/Source/Android/jni/GameList/GameFileCache.cpp @@ -39,6 +39,12 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_finali delete GetPointer(env, obj); } +JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_getSize(JNIEnv* env, + jobject obj) +{ + return static_cast(GetPointer(env, obj)->GetSize()); +} + JNIEXPORT jobjectArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_getAllGames(JNIEnv* env, jobject obj) {