Android: Optional AfterDirectoryInitializationRunner failure message

This centralizes the code for showing the write_permission_needed
and external_storage_not_mounted toasts.
This commit is contained in:
JosJuice 2020-09-05 19:43:36 +02:00
parent db067104ed
commit 2959e76f4a
11 changed files with 147 additions and 210 deletions

View File

@ -11,15 +11,13 @@ import androidx.fragment.app.FragmentActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.util.Log; import android.util.Log;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.GameFile; import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.services.GameFileCacheService; import org.dolphinemu.dolphinemu.services.GameFileCacheService;
import org.dolphinemu.dolphinemu.ui.main.TvMainActivity; import org.dolphinemu.dolphinemu.ui.main.TvMainActivity;
import org.dolphinemu.dolphinemu.utils.AppLinkHelper; import org.dolphinemu.dolphinemu.utils.AppLinkHelper;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
/** /**
* Linker between leanback homescreen and app * Linker between leanback homescreen and app
@ -29,7 +27,7 @@ public class AppLinkActivity extends FragmentActivity
private static final String TAG = "AppLinkActivity"; private static final String TAG = "AppLinkActivity";
private AppLinkHelper.PlayAction playAction; private AppLinkHelper.PlayAction playAction;
private DirectoryStateReceiver directoryStateReceiver; private AfterDirectoryInitializationRunner mAfterDirectoryInitializationRunner;
@Override @Override
protected void onCreate(Bundle savedInstanceState) protected void onCreate(Bundle savedInstanceState)
@ -67,34 +65,12 @@ public class AppLinkActivity extends FragmentActivity
*/ */
private void initResources() private void initResources()
{ {
IntentFilter directoryStateIntentFilter = new IntentFilter( mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner();
DirectoryInitialization.BROADCAST_ACTION); mAfterDirectoryInitializationRunner.run(this, true, () -> tryPlay(playAction));
IntentFilter gameFileCacheIntentFilter = new IntentFilter( IntentFilter gameFileCacheIntentFilter = new IntentFilter(
GameFileCacheService.BROADCAST_ACTION); 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() BroadcastReceiver gameFileCacheReceiver = new BroadcastReceiver()
{ {
@Override @Override
@ -108,7 +84,6 @@ public class AppLinkActivity extends FragmentActivity
}; };
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this); LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
broadcastManager.registerReceiver(directoryStateReceiver, directoryStateIntentFilter);
broadcastManager.registerReceiver(gameFileCacheReceiver, gameFileCacheIntentFilter); broadcastManager.registerReceiver(gameFileCacheReceiver, gameFileCacheIntentFilter);
DirectoryInitialization.start(this); DirectoryInitialization.start(this);
@ -160,10 +135,10 @@ public class AppLinkActivity extends FragmentActivity
private void startGame(GameFile game) private void startGame(GameFile game)
{ {
if (directoryStateReceiver != null) if (mAfterDirectoryInitializationRunner != null)
{ {
LocalBroadcastManager.getInstance(this).unregisterReceiver(directoryStateReceiver); mAfterDirectoryInitializationRunner.cancel();
directoryStateReceiver = null; mAfterDirectoryInitializationRunner = null;
} }
EmulationActivity.launch(this, game); EmulationActivity.launch(this, game);
} }

View File

@ -3,7 +3,6 @@ package org.dolphinemu.dolphinemu.features.settings.ui;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
@ -11,7 +10,6 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import android.view.Menu; import android.view.Menu;
@ -22,8 +20,6 @@ import android.widget.Toast;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.ui.main.MainActivity; import org.dolphinemu.dolphinemu.ui.main.MainActivity;
import org.dolphinemu.dolphinemu.ui.main.TvMainActivity; 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.FileBrowserHelper;
import org.dolphinemu.dolphinemu.utils.TvUtil; import org.dolphinemu.dolphinemu.utils.TvUtil;
@ -150,22 +146,6 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
return duration != 0 && transition != 0; 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 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent result) protected void onActivityResult(int requestCode, int resultCode, Intent result)
{ {
@ -212,20 +192,6 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
dialog.dismiss(); 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 @Override
public void showGameIniJunkDeletionQuestion() public void showGameIniJunkDeletionQuestion()
{ {

View File

@ -1,15 +1,13 @@
package org.dolphinemu.dolphinemu.features.settings.ui; package org.dolphinemu.dolphinemu.features.settings.ui;
import android.content.Context; import android.content.Context;
import android.content.IntentFilter;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.Settings; 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;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
import java.util.HashSet; import java.util.HashSet;
@ -25,7 +23,7 @@ public final class SettingsActivityPresenter
private boolean mShouldSave; private boolean mShouldSave;
private DirectoryStateReceiver directoryStateReceiver; private AfterDirectoryInitializationRunner mAfterDirectoryInitializationRunner;
private MenuTag menuTag; private MenuTag menuTag;
private String gameId; private String gameId;
@ -85,33 +83,10 @@ public final class SettingsActivityPresenter
else else
{ {
mView.showLoading(); mView.showLoading();
IntentFilter statusIntentFilter = new IntentFilter(
DirectoryInitialization.BROADCAST_ACTION);
directoryStateReceiver = mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner();
new DirectoryStateReceiver(directoryInitializationState -> mAfterDirectoryInitializationRunner.setFinishedCallback(mView::hideLoading);
{ mAfterDirectoryInitializationRunner.run(context, true, this::loadSettingsUI);
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);
} }
} }
@ -128,10 +103,10 @@ public final class SettingsActivityPresenter
public void onStop(boolean finishing) public void onStop(boolean finishing)
{ {
if (directoryStateReceiver != null) if (mAfterDirectoryInitializationRunner != null)
{ {
mView.stopListeningToDirectoryInitializationService(directoryStateReceiver); mAfterDirectoryInitializationRunner.cancel();
directoryStateReceiver = null; mAfterDirectoryInitializationRunner = null;
} }
if (mSettings != null && finishing && mShouldSave) if (mSettings != null && finishing && mShouldSave)

View File

@ -1,10 +1,8 @@
package org.dolphinemu.dolphinemu.features.settings.ui; package org.dolphinemu.dolphinemu.features.settings.ui;
import android.content.IntentFilter;
import android.os.Bundle; import android.os.Bundle;
import org.dolphinemu.dolphinemu.features.settings.model.Settings; import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
/** /**
* Abstraction for the Activity that manages SettingsFragments. * Abstraction for the Activity that manages SettingsFragments.
@ -97,33 +95,8 @@ public interface SettingsActivityView
*/ */
void hideLoading(); 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. * Tell the user that there is junk in the game INI and ask if they want to delete the whole file.
*/ */
void showGameIniJunkDeletionQuestion(); 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);
} }

View File

@ -1,14 +1,12 @@
package org.dolphinemu.dolphinemu.fragments; package org.dolphinemu.dolphinemu.fragments;
import android.content.Context; import android.content.Context;
import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Surface; import android.view.Surface;
@ -17,15 +15,12 @@ import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.overlay.InputOverlay; import org.dolphinemu.dolphinemu.overlay.InputOverlay;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
import java.io.File; import java.io.File;
@ -40,7 +35,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
private EmulationState mEmulationState; private EmulationState mEmulationState;
private DirectoryStateReceiver directoryStateReceiver; private AfterDirectoryInitializationRunner mAfterDirectoryInitializationRunner;
private EmulationActivity activity; private EmulationActivity activity;
@ -115,23 +110,19 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
public void onResume() public void onResume()
{ {
super.onResume(); super.onResume();
if (DirectoryInitialization.areDolphinDirectoriesReady())
{ mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner();
mEmulationState.run(activity.isActivityRecreated()); mAfterDirectoryInitializationRunner.run(requireContext(), true,
} () -> mEmulationState.run(activity.isActivityRecreated()));
else
{
setupDolphinDirectoriesThenStartEmulation();
}
} }
@Override @Override
public void onPause() public void onPause()
{ {
if (directoryStateReceiver != null) if (mAfterDirectoryInitializationRunner != null)
{ {
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(directoryStateReceiver); mAfterDirectoryInitializationRunner.cancel();
directoryStateReceiver = null; mAfterDirectoryInitializationRunner = null;
} }
if (mEmulationState.isRunning()) if (mEmulationState.isRunning())
@ -146,41 +137,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
super.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() public void toggleInputOverlayVisibility()
{ {
SharedPreferences.Editor editor = mPreferences.edit(); SharedPreferences.Editor editor = mPreferences.edit();

View File

@ -109,7 +109,7 @@ public final class GameFileCacheService extends IntentService
*/ */
public static void startLoad(Context context) public static void startLoad(Context context)
{ {
new AfterDirectoryInitializationRunner().run(context, new AfterDirectoryInitializationRunner().run(context, false,
() -> startService(context, ACTION_LOAD)); () -> startService(context, ACTION_LOAD));
} }
@ -120,7 +120,7 @@ public final class GameFileCacheService extends IntentService
*/ */
public static void startRescan(Context context) public static void startRescan(Context context)
{ {
new AfterDirectoryInitializationRunner().run(context, new AfterDirectoryInitializationRunner().run(context, false,
() -> startService(context, ACTION_RESCAN)); () -> startService(context, ACTION_RESCAN));
} }

View File

@ -72,7 +72,7 @@ public final class MainActivity extends AppCompatActivity implements MainView
if (PermissionsHandler.hasWriteAccess(this)) if (PermissionsHandler.hasWriteAccess(this))
{ {
new AfterDirectoryInitializationRunner() new AfterDirectoryInitializationRunner()
.run(this, this::setPlatformTabsAndStartGameFileCacheService); .run(this, false, this::setPlatformTabsAndStartGameFileCacheService);
} }
} }
@ -213,7 +213,7 @@ public final class MainActivity extends AppCompatActivity implements MainView
{ {
DirectoryInitialization.start(this); DirectoryInitialization.start(this);
new AfterDirectoryInitializationRunner() new AfterDirectoryInitializationRunner()
.run(this, this::setPlatformTabsAndStartGameFileCacheService); .run(this, false, this::setPlatformTabsAndStartGameFileCacheService);
} }
else else
{ {

View File

@ -2,12 +2,38 @@ package org.dolphinemu.dolphinemu.utils;
import android.content.Context; import android.content.Context;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.widget.Toast;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
public class AfterDirectoryInitializationRunner 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. * Executes a Runnable after directory initialization has finished.
@ -19,33 +45,84 @@ public class AfterDirectoryInitializationRunner
* in case directory initialization doesn't finish successfully. * in case directory initialization doesn't finish successfully.
* *
* Calling this function multiple times per object is not supported. * 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()) if (DirectoryInitialization.areDolphinDirectoriesReady())
{ {
// Wait for directories to get initialized runFinishedCallback();
IntentFilter statusIntentFilter = new IntentFilter( runnable.run();
DirectoryInitialization.BROADCAST_ACTION); }
else if (abortOnFailure &&
directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> showErrorMessage(context, DirectoryInitialization.getDolphinDirectoriesState(context)))
{ {
if (directoryInitializationState == runFinishedCallback();
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);
} }
else else
{ {
runnable.run(); runAfterInitialization(context, abortOnFailure, runnable);
}
}
private void runAfterInitialization(Context context, boolean abortOnFailure, Runnable runnable)
{
mDirectoryStateReceiver = new DirectoryStateReceiver(state ->
{
boolean done = state == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
if (!done && abortOnFailure)
{
done = showErrorMessage(context, state);
}
if (done)
{
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;
}
}
private static boolean showErrorMessage(Context context, DirectoryInitializationState state)
{
switch (state)
{
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;
} }
} }
} }

View File

@ -32,7 +32,7 @@ public class Analytics
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (!preferences.getBoolean(analyticsAsked, false)) if (!preferences.getBoolean(analyticsAsked, false))
{ {
new AfterDirectoryInitializationRunner().run(context, new AfterDirectoryInitializationRunner().run(context, false,
() -> showMessage(context, preferences)); () -> showMessage(context, preferences));
} }
} }

View File

@ -37,13 +37,15 @@ public final class DirectoryInitialization
public static final String EXTRA_STATE = "directoryState"; public static final String EXTRA_STATE = "directoryState";
private static final int WiimoteNewVersion = 5; // Last changed in PR 8907 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 userPath;
private static String internalPath; private static String internalPath;
private static AtomicBoolean isDolphinDirectoryInitializationRunning = new AtomicBoolean(false); private static AtomicBoolean isDolphinDirectoryInitializationRunning = new AtomicBoolean(false);
public enum DirectoryInitializationState public enum DirectoryInitializationState
{ {
NOT_YET_INITIALIZED,
DOLPHIN_DIRECTORIES_INITIALIZED, DOLPHIN_DIRECTORIES_INITIALIZED,
EXTERNAL_STORAGE_PERMISSION_NEEDED, EXTERNAL_STORAGE_PERMISSION_NEEDED,
CANT_FIND_EXTERNAL_STORAGE CANT_FIND_EXTERNAL_STORAGE
@ -199,9 +201,22 @@ public final class DirectoryInitialization
return directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; 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() public static String getUserDirectory()
{ {
if (directoryState == null) if (directoryState == DirectoryInitializationState.NOT_YET_INITIALIZED)
{ {
throw new IllegalStateException("DirectoryInitialization has to run at least once!"); throw new IllegalStateException("DirectoryInitialization has to run at least once!");
} }
@ -216,7 +231,7 @@ public final class DirectoryInitialization
public static String getDolphinInternalDirectory() public static String getDolphinInternalDirectory()
{ {
if (directoryState == null) if (directoryState == DirectoryInitializationState.NOT_YET_INITIALIZED)
{ {
throw new IllegalStateException("DirectoryInitialization has to run at least once!"); throw new IllegalStateException("DirectoryInitialization has to run at least once!");
} }

View File

@ -76,7 +76,7 @@ public final class StartupHandler
long lastOpen = preferences.getLong(LAST_CLOSED, 0); long lastOpen = preferences.getLong(LAST_CLOSED, 0);
if (currentTime > (lastOpen + SESSION_TIMEOUT)) if (currentTime > (lastOpen + SESSION_TIMEOUT))
{ {
new AfterDirectoryInitializationRunner().run(context, new AfterDirectoryInitializationRunner().run(context, false,
NativeLibrary::ReportStartToAnalytics); NativeLibrary::ReportStartToAnalytics);
} }
} }