From 2959e76f4a3a6c40e03db1b08549677cad19aad8 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 5 Sep 2020 19:43:36 +0200 Subject: [PATCH] Android: Optional AfterDirectoryInitializationRunner failure message This centralizes the code for showing the write_permission_needed and external_storage_not_mounted toasts. --- .../activities/AppLinkActivity.java | 39 ++---- .../settings/ui/SettingsActivity.java | 34 ----- .../ui/SettingsActivityPresenter.java | 43 ++----- .../settings/ui/SettingsActivityView.java | 27 ---- .../fragments/EmulationFragment.java | 62 ++------- .../services/GameFileCacheService.java | 4 +- .../dolphinemu/ui/main/MainActivity.java | 4 +- .../AfterDirectoryInitializationRunner.java | 119 ++++++++++++++---- .../dolphinemu/utils/Analytics.java | 2 +- .../utils/DirectoryInitialization.java | 21 +++- .../dolphinemu/utils/StartupHandler.java | 2 +- 11 files changed, 147 insertions(+), 210 deletions(-) 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 582296c89b68..a97b7fcf395f 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 @@ -11,15 +11,13 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.util.Log; -import android.widget.Toast; -import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.model.GameFile; +import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.services.GameFileCacheService; import org.dolphinemu.dolphinemu.ui.main.TvMainActivity; import org.dolphinemu.dolphinemu.utils.AppLinkHelper; -import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; /** * Linker between leanback homescreen and app @@ -29,7 +27,7 @@ public class AppLinkActivity extends FragmentActivity private static final String TAG = "AppLinkActivity"; private AppLinkHelper.PlayAction playAction; - private DirectoryStateReceiver directoryStateReceiver; + private AfterDirectoryInitializationRunner mAfterDirectoryInitializationRunner; @Override protected void onCreate(Bundle savedInstanceState) @@ -67,34 +65,12 @@ protected void onCreate(Bundle savedInstanceState) */ private void initResources() { - IntentFilter directoryStateIntentFilter = new IntentFilter( - DirectoryInitialization.BROADCAST_ACTION); + mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner(); + mAfterDirectoryInitializationRunner.run(this, true, () -> tryPlay(playAction)); IntentFilter gameFileCacheIntentFilter = new IntentFilter( GameFileCacheService.BROADCAST_ACTION); - directoryStateReceiver = - new DirectoryStateReceiver(directoryInitializationState -> - { - if (directoryInitializationState == - DirectoryInitialization.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) - { - tryPlay(playAction); - } - else if (directoryInitializationState == - DirectoryInitialization.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) - { - Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT) - .show(); - } - else if (directoryInitializationState == - DirectoryInitialization.DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE) - { - Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT) - .show(); - } - }); - BroadcastReceiver gameFileCacheReceiver = new BroadcastReceiver() { @Override @@ -108,7 +84,6 @@ public void onReceive(Context context, Intent intent) }; LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this); - broadcastManager.registerReceiver(directoryStateReceiver, directoryStateIntentFilter); broadcastManager.registerReceiver(gameFileCacheReceiver, gameFileCacheIntentFilter); DirectoryInitialization.start(this); @@ -160,10 +135,10 @@ private void play(AppLinkHelper.PlayAction action, GameFile game) private void startGame(GameFile game) { - if (directoryStateReceiver != null) + if (mAfterDirectoryInitializationRunner != null) { - LocalBroadcastManager.getInstance(this).unregisterReceiver(directoryStateReceiver); - directoryStateReceiver = null; + mAfterDirectoryInitializationRunner.cancel(); + mAfterDirectoryInitializationRunner = null; } EmulationActivity.launch(this, game); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java index 837024c2ab0a..6518fdfe9565 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java @@ -3,7 +3,6 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.os.Bundle; import android.provider.Settings; @@ -11,7 +10,6 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.ViewModelProvider; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.appcompat.app.AppCompatActivity; import android.view.Menu; @@ -22,8 +20,6 @@ import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.ui.main.MainActivity; import org.dolphinemu.dolphinemu.ui.main.TvMainActivity; -import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; -import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.FileBrowserHelper; import org.dolphinemu.dolphinemu.utils.TvUtil; @@ -150,22 +146,6 @@ private boolean areSystemAnimationsEnabled() return duration != 0 && transition != 0; } - @Override - public void startDirectoryInitializationService(DirectoryStateReceiver receiver, - IntentFilter filter) - { - LocalBroadcastManager.getInstance(this).registerReceiver( - receiver, - filter); - DirectoryInitialization.start(this); - } - - @Override - public void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver) - { - LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); - } - @Override protected void onActivityResult(int requestCode, int resultCode, Intent result) { @@ -212,20 +192,6 @@ public void hideLoading() dialog.dismiss(); } - @Override - public void showPermissionNeededHint() - { - Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT) - .show(); - } - - @Override - public void showExternalStorageNotMountedHint() - { - Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT) - .show(); - } - @Override public void showGameIniJunkDeletionQuestion() { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java index 71eb9fd02a9d..710510c40c3f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java @@ -1,15 +1,13 @@ package org.dolphinemu.dolphinemu.features.settings.ui; import android.content.Context; -import android.content.IntentFilter; import android.os.Bundle; import android.text.TextUtils; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.features.settings.model.Settings; +import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; -import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState; -import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.Log; import java.util.HashSet; @@ -25,7 +23,7 @@ public final class SettingsActivityPresenter private boolean mShouldSave; - private DirectoryStateReceiver directoryStateReceiver; + private AfterDirectoryInitializationRunner mAfterDirectoryInitializationRunner; private MenuTag menuTag; private String gameId; @@ -85,33 +83,10 @@ private void prepareDolphinDirectoriesIfNeeded() else { mView.showLoading(); - IntentFilter statusIntentFilter = new IntentFilter( - DirectoryInitialization.BROADCAST_ACTION); - - directoryStateReceiver = - new DirectoryStateReceiver(directoryInitializationState -> - { - if (directoryInitializationState == - DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) - { - mView.hideLoading(); - loadSettingsUI(); - } - else if (directoryInitializationState == - DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) - { - mView.showPermissionNeededHint(); - mView.hideLoading(); - } - else if (directoryInitializationState == - DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE) - { - mView.showExternalStorageNotMountedHint(); - mView.hideLoading(); - } - }); - - mView.startDirectoryInitializationService(directoryStateReceiver, statusIntentFilter); + + mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner(); + mAfterDirectoryInitializationRunner.setFinishedCallback(mView::hideLoading); + mAfterDirectoryInitializationRunner.run(context, true, this::loadSettingsUI); } } @@ -128,10 +103,10 @@ public void clearSettings() public void onStop(boolean finishing) { - if (directoryStateReceiver != null) + if (mAfterDirectoryInitializationRunner != null) { - mView.stopListeningToDirectoryInitializationService(directoryStateReceiver); - directoryStateReceiver = null; + mAfterDirectoryInitializationRunner.cancel(); + mAfterDirectoryInitializationRunner = null; } if (mSettings != null && finishing && mShouldSave) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java index 1507706e0f66..f22261d36d4c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java @@ -1,10 +1,8 @@ package org.dolphinemu.dolphinemu.features.settings.ui; -import android.content.IntentFilter; import android.os.Bundle; import org.dolphinemu.dolphinemu.features.settings.model.Settings; -import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; /** * Abstraction for the Activity that manages SettingsFragments. @@ -97,33 +95,8 @@ public interface SettingsActivityView */ void hideLoading(); - /** - * Show a hint to the user that the app needs write to external storage access - */ - void showPermissionNeededHint(); - - /** - * Show a hint to the user that the app needs the external storage to be mounted - */ - void showExternalStorageNotMountedHint(); - /** * Tell the user that there is junk in the game INI and ask if they want to delete the whole file. */ void showGameIniJunkDeletionQuestion(); - - /** - * Start the DirectoryInitialization and listen for the result. - * - * @param receiver the broadcast receiver for the DirectoryInitialization - * @param filter the Intent broadcasts to be received. - */ - void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter); - - /** - * Stop listening to the DirectoryInitialization. - * - * @param receiver The broadcast receiver to unregister. - */ - void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index 174a7e0bc6bf..0e99eaed351f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -1,14 +1,12 @@ package org.dolphinemu.dolphinemu.fragments; import android.content.Context; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; -import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.view.LayoutInflater; import android.view.Surface; @@ -17,15 +15,12 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.Toast; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.overlay.InputOverlay; -import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; -import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState; -import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; +import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner; import org.dolphinemu.dolphinemu.utils.Log; import java.io.File; @@ -40,7 +35,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private EmulationState mEmulationState; - private DirectoryStateReceiver directoryStateReceiver; + private AfterDirectoryInitializationRunner mAfterDirectoryInitializationRunner; private EmulationActivity activity; @@ -115,23 +110,19 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa public void onResume() { super.onResume(); - if (DirectoryInitialization.areDolphinDirectoriesReady()) - { - mEmulationState.run(activity.isActivityRecreated()); - } - else - { - setupDolphinDirectoriesThenStartEmulation(); - } + + mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner(); + mAfterDirectoryInitializationRunner.run(requireContext(), true, + () -> mEmulationState.run(activity.isActivityRecreated())); } @Override public void onPause() { - if (directoryStateReceiver != null) + if (mAfterDirectoryInitializationRunner != null) { - LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(directoryStateReceiver); - directoryStateReceiver = null; + mAfterDirectoryInitializationRunner.cancel(); + mAfterDirectoryInitializationRunner = null; } if (mEmulationState.isRunning()) @@ -146,41 +137,6 @@ public void onDetach() super.onDetach(); } - private void setupDolphinDirectoriesThenStartEmulation() - { - IntentFilter statusIntentFilter = new IntentFilter( - DirectoryInitialization.BROADCAST_ACTION); - - directoryStateReceiver = - new DirectoryStateReceiver(directoryInitializationState -> - { - if (directoryInitializationState == - DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) - { - mEmulationState.run(activity.isActivityRecreated()); - } - else if (directoryInitializationState == - DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) - { - Toast.makeText(getContext(), R.string.write_permission_needed, Toast.LENGTH_SHORT) - .show(); - } - else if (directoryInitializationState == - DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE) - { - Toast.makeText(getContext(), R.string.external_storage_not_mounted, - Toast.LENGTH_SHORT) - .show(); - } - }); - - // Registers the DirectoryStateReceiver and its intent filters - LocalBroadcastManager.getInstance(getActivity()).registerReceiver( - directoryStateReceiver, - statusIntentFilter); - DirectoryInitialization.start(getActivity()); - } - public void toggleInputOverlayVisibility() { SharedPreferences.Editor editor = mPreferences.edit(); 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 fa6f039d84eb..61f3efa75565 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 @@ -109,7 +109,7 @@ private static void startService(Context context, String action) */ public static void startLoad(Context context) { - new AfterDirectoryInitializationRunner().run(context, + new AfterDirectoryInitializationRunner().run(context, false, () -> startService(context, ACTION_LOAD)); } @@ -120,7 +120,7 @@ public static void startLoad(Context context) */ public static void startRescan(Context context) { - new AfterDirectoryInitializationRunner().run(context, + new AfterDirectoryInitializationRunner().run(context, false, () -> startService(context, ACTION_RESCAN)); } 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 5081e58cb193..a53356f8a266 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 @@ -72,7 +72,7 @@ protected void onCreate(Bundle savedInstanceState) if (PermissionsHandler.hasWriteAccess(this)) { new AfterDirectoryInitializationRunner() - .run(this, this::setPlatformTabsAndStartGameFileCacheService); + .run(this, false, this::setPlatformTabsAndStartGameFileCacheService); } } @@ -213,7 +213,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis { DirectoryInitialization.start(this); new AfterDirectoryInitializationRunner() - .run(this, this::setPlatformTabsAndStartGameFileCacheService); + .run(this, false, this::setPlatformTabsAndStartGameFileCacheService); } else { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AfterDirectoryInitializationRunner.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AfterDirectoryInitializationRunner.java index 1ff86d8656b2..4f8a5fc49cff 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AfterDirectoryInitializationRunner.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AfterDirectoryInitializationRunner.java @@ -2,12 +2,38 @@ import android.content.Context; import android.content.IntentFilter; +import android.widget.Toast; import androidx.localbroadcastmanager.content.LocalBroadcastManager; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState; + public class AfterDirectoryInitializationRunner { - private DirectoryStateReceiver directoryStateReceiver; + private DirectoryStateReceiver mDirectoryStateReceiver; + private LocalBroadcastManager mLocalBroadcastManager; + + private Runnable mUnregisterCallback; + + /** + * Sets a Runnable which will be called when: + * + * 1. The Runnable supplied to {@link #run} is just about to run, or + * 2. {@link #run} was called with abortOnFailure == true and there is a failure + */ + public void setFinishedCallback(Runnable runnable) + { + mUnregisterCallback = runnable; + } + + private void runFinishedCallback() + { + if (mUnregisterCallback != null) + { + mUnregisterCallback.run(); + } + } /** * Executes a Runnable after directory initialization has finished. @@ -19,33 +45,84 @@ public class AfterDirectoryInitializationRunner * in case directory initialization doesn't finish successfully. * * Calling this function multiple times per object is not supported. + * + * If abortOnFailure is true and the user has not granted the required + * permission or the external storage was not found, a message will be + * shown to the user and the Runnable will not run. If it is false, the + * attempt to run the Runnable will never be aborted, and the Runnable + * is guaranteed to run if directory initialization ever finishes. */ - public void run(Context context, Runnable runnable) + public void run(Context context, boolean abortOnFailure, Runnable runnable) + { + if (DirectoryInitialization.areDolphinDirectoriesReady()) + { + runFinishedCallback(); + runnable.run(); + } + else if (abortOnFailure && + showErrorMessage(context, DirectoryInitialization.getDolphinDirectoriesState(context))) + { + runFinishedCallback(); + } + else + { + runAfterInitialization(context, abortOnFailure, runnable); + } + } + + private void runAfterInitialization(Context context, boolean abortOnFailure, Runnable runnable) { - if (!DirectoryInitialization.areDolphinDirectoriesReady()) + mDirectoryStateReceiver = new DirectoryStateReceiver(state -> { - // Wait for directories to get initialized - IntentFilter statusIntentFilter = new IntentFilter( - DirectoryInitialization.BROADCAST_ACTION); + boolean done = state == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; + + if (!done && abortOnFailure) + { + done = showErrorMessage(context, state); + } - directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> + if (done) { - if (directoryInitializationState == - DirectoryInitialization.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) - { - LocalBroadcastManager.getInstance(context).unregisterReceiver(directoryStateReceiver); - directoryStateReceiver = null; - runnable.run(); - } - }); - // Registers the DirectoryStateReceiver and its intent filters - LocalBroadcastManager.getInstance(context).registerReceiver( - directoryStateReceiver, - statusIntentFilter); + cancel(); + runFinishedCallback(); + } + + if (state == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) + { + runnable.run(); + } + }); + + mLocalBroadcastManager = LocalBroadcastManager.getInstance(context); + + IntentFilter statusIntentFilter = new IntentFilter(DirectoryInitialization.BROADCAST_ACTION); + mLocalBroadcastManager.registerReceiver(mDirectoryStateReceiver, statusIntentFilter); + } + + public void cancel() + { + if (mDirectoryStateReceiver != null) + { + mLocalBroadcastManager.unregisterReceiver(mDirectoryStateReceiver); + mDirectoryStateReceiver = null; + mLocalBroadcastManager = null; } - else + } + + private static boolean showErrorMessage(Context context, DirectoryInitializationState state) + { + switch (state) { - runnable.run(); + case EXTERNAL_STORAGE_PERMISSION_NEEDED: + Toast.makeText(context, R.string.write_permission_needed, Toast.LENGTH_SHORT).show(); + return true; + + case CANT_FIND_EXTERNAL_STORAGE: + Toast.makeText(context, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT).show(); + return true; + + default: + return false; } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java index 9907769146b6..f9ff6e535bbf 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java @@ -32,7 +32,7 @@ public static void checkAnalyticsInit(Context context) SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); if (!preferences.getBoolean(analyticsAsked, false)) { - new AfterDirectoryInitializationRunner().run(context, + new AfterDirectoryInitializationRunner().run(context, false, () -> showMessage(context, preferences)); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java index 946071193b00..a15757647d13 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java @@ -37,13 +37,15 @@ public final class DirectoryInitialization public static final String EXTRA_STATE = "directoryState"; private static final int WiimoteNewVersion = 5; // Last changed in PR 8907 - private static volatile DirectoryInitializationState directoryState = null; + private static volatile DirectoryInitializationState directoryState = + DirectoryInitializationState.NOT_YET_INITIALIZED; private static String userPath; private static String internalPath; private static AtomicBoolean isDolphinDirectoryInitializationRunning = new AtomicBoolean(false); public enum DirectoryInitializationState { + NOT_YET_INITIALIZED, DOLPHIN_DIRECTORIES_INITIALIZED, EXTERNAL_STORAGE_PERMISSION_NEEDED, CANT_FIND_EXTERNAL_STORAGE @@ -199,9 +201,22 @@ public static boolean areDolphinDirectoriesReady() return directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; } + public static DirectoryInitializationState getDolphinDirectoriesState(Context context) + { + if (directoryState == DirectoryInitializationState.NOT_YET_INITIALIZED && + !PermissionsHandler.hasWriteAccess(context)) + { + return DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED; + } + else + { + return directoryState; + } + } + public static String getUserDirectory() { - if (directoryState == null) + if (directoryState == DirectoryInitializationState.NOT_YET_INITIALIZED) { throw new IllegalStateException("DirectoryInitialization has to run at least once!"); } @@ -216,7 +231,7 @@ else if (isDolphinDirectoryInitializationRunning.get()) public static String getDolphinInternalDirectory() { - if (directoryState == null) + if (directoryState == DirectoryInitializationState.NOT_YET_INITIALIZED) { throw new IllegalStateException("DirectoryInitialization has to run at least once!"); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java index e09a20098500..9bf68368bf12 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/StartupHandler.java @@ -76,7 +76,7 @@ public static void checkSessionReset(Context context) long lastOpen = preferences.getLong(LAST_CLOSED, 0); if (currentTime > (lastOpen + SESSION_TIMEOUT)) { - new AfterDirectoryInitializationRunner().run(context, + new AfterDirectoryInitializationRunner().run(context, false, NativeLibrary::ReportStartToAnalytics); } }