Android: Make DirectoryInitialization use LiveData

Gets rid of all remaining uses of the deprecated LocalBroadcastManager.
This commit is contained in:
JosJuice 2021-11-18 22:12:55 +01:00
parent 8b57aad8ed
commit bb475391d2
12 changed files with 109 additions and 129 deletions

View file

@ -63,7 +63,7 @@ public class AppLinkActivity extends FragmentActivity
private void initResources() private void initResources()
{ {
mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner(); mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner();
mAfterDirectoryInitializationRunner.run(this, true, () -> tryPlay(playAction)); mAfterDirectoryInitializationRunner.runWithLifecycle(this, true, () -> tryPlay(playAction));
GameFileCacheManager.isLoading().observe(this, (isLoading) -> GameFileCacheManager.isLoading().observe(this, (isLoading) ->
{ {
@ -122,11 +122,7 @@ public class AppLinkActivity extends FragmentActivity
private void startGame(GameFile game) private void startGame(GameFile game)
{ {
if (mAfterDirectoryInitializationRunner != null) mAfterDirectoryInitializationRunner.cancel();
{
mAfterDirectoryInitializationRunner.cancel();
mAfterDirectoryInitializationRunner = null;
}
EmulationActivity.launch(this, GameFileCacheManager.findSecondDiscAndGetPaths(game), false); EmulationActivity.launch(this, GameFileCacheManager.findSecondDiscAndGetPaths(game), false);
} }
} }

View file

@ -176,7 +176,7 @@ public final class EmulationActivity extends AppCompatActivity
if (sIgnoreLaunchRequests) if (sIgnoreLaunchRequests)
return; return;
new AfterDirectoryInitializationRunner().run(activity, true, () -> new AfterDirectoryInitializationRunner().runWithLifecycle(activity, true, () ->
{ {
if (FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_DEFAULT_ISO) && if (FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_DEFAULT_ISO) &&
FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_FS_PATH) && FileBrowserHelper.isPathEmptyOrValid(StringSetting.MAIN_FS_PATH) &&

View file

@ -74,8 +74,7 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
MenuTag menuTag = (MenuTag) launcher.getSerializableExtra(ARG_MENU_TAG); MenuTag menuTag = (MenuTag) launcher.getSerializableExtra(ARG_MENU_TAG);
mPresenter = new SettingsActivityPresenter(this, getSettings()); mPresenter = new SettingsActivityPresenter(this, getSettings());
mPresenter.onCreate(savedInstanceState, menuTag, gameID, revision, isWii, mPresenter.onCreate(savedInstanceState, menuTag, gameID, revision, isWii, this);
getApplicationContext());
} }
@Override @Override

View file

@ -2,10 +2,11 @@
package org.dolphinemu.dolphinemu.features.settings.ui; package org.dolphinemu.dolphinemu.features.settings.ui;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.core.app.ComponentActivity;
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.AfterDirectoryInitializationRunner;
@ -22,13 +23,11 @@ public final class SettingsActivityPresenter
private boolean mShouldSave; private boolean mShouldSave;
private AfterDirectoryInitializationRunner mAfterDirectoryInitializationRunner;
private MenuTag mMenuTag; private MenuTag mMenuTag;
private String mGameId; private String mGameId;
private int mRevision; private int mRevision;
private boolean mIsWii; private boolean mIsWii;
private Context mContext; private ComponentActivity mActivity;
SettingsActivityPresenter(SettingsActivityView view, Settings settings) SettingsActivityPresenter(SettingsActivityView view, Settings settings)
{ {
@ -37,13 +36,13 @@ public final class SettingsActivityPresenter
} }
public void onCreate(Bundle savedInstanceState, MenuTag menuTag, String gameId, int revision, public void onCreate(Bundle savedInstanceState, MenuTag menuTag, String gameId, int revision,
boolean isWii, Context context) boolean isWii, ComponentActivity activity)
{ {
this.mMenuTag = menuTag; this.mMenuTag = menuTag;
this.mGameId = gameId; this.mGameId = gameId;
this.mRevision = revision; this.mRevision = revision;
this.mIsWii = isWii; this.mIsWii = isWii;
this.mContext = context; this.mActivity = activity;
mShouldSave = savedInstanceState != null && savedInstanceState.getBoolean(KEY_SHOULD_SAVE); mShouldSave = savedInstanceState != null && savedInstanceState.getBoolean(KEY_SHOULD_SAVE);
} }
@ -95,9 +94,9 @@ public final class SettingsActivityPresenter
{ {
mView.showLoading(); mView.showLoading();
mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner(); new AfterDirectoryInitializationRunner()
mAfterDirectoryInitializationRunner.setFinishedCallback(mView::hideLoading); .setFinishedCallback(mView::hideLoading)
mAfterDirectoryInitializationRunner.run(mContext, true, this::loadSettingsUI); .runWithLifecycle(mActivity, true, this::loadSettingsUI);
} }
} }
@ -114,16 +113,10 @@ public final class SettingsActivityPresenter
public void onStop(boolean finishing) public void onStop(boolean finishing)
{ {
if (mAfterDirectoryInitializationRunner != null)
{
mAfterDirectoryInitializationRunner.cancel();
mAfterDirectoryInitializationRunner = null;
}
if (mSettings != null && finishing && mShouldSave) if (mSettings != null && finishing && mShouldSave)
{ {
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI..."); Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
mSettings.saveSettings(mView, mContext); mSettings.saveSettings(mView, mActivity);
} }
} }
@ -172,7 +165,7 @@ public final class SettingsActivityPresenter
break; break;
case 2: case 2:
mView.showToastMessage(mContext.getString(R.string.make_sure_continuous_scan_enabled)); mView.showToastMessage(mActivity.getString(R.string.make_sure_continuous_scan_enabled));
break; break;
} }
} }

View file

@ -127,7 +127,7 @@ public final class GameFileCacheManager
if (!loadInProgress.getValue()) if (!loadInProgress.getValue())
{ {
loadInProgress.setValue(true); loadInProgress.setValue(true);
new AfterDirectoryInitializationRunner().run(context, false, new AfterDirectoryInitializationRunner().runWithoutLifecycle(context, false,
() -> executor.execute(GameFileCacheManager::load)); () -> executor.execute(GameFileCacheManager::load));
} }
} }
@ -142,7 +142,7 @@ public final class GameFileCacheManager
if (!rescanInProgress.getValue()) if (!rescanInProgress.getValue())
{ {
rescanInProgress.setValue(true); rescanInProgress.setValue(true);
new AfterDirectoryInitializationRunner().run(context, false, new AfterDirectoryInitializationRunner().runWithoutLifecycle(context, false,
() -> executor.execute(GameFileCacheManager::rescan)); () -> executor.execute(GameFileCacheManager::rescan));
} }
} }

View file

@ -73,7 +73,7 @@ public final class MainActivity extends AppCompatActivity
if (!DirectoryInitialization.isWaitingForWriteAccess(this)) if (!DirectoryInitialization.isWaitingForWriteAccess(this))
{ {
new AfterDirectoryInitializationRunner() new AfterDirectoryInitializationRunner()
.run(this, false, this::setPlatformTabsAndStartGameFileCacheService); .runWithLifecycle(this, false, this::setPlatformTabsAndStartGameFileCacheService);
} }
} }
@ -86,7 +86,7 @@ public final class MainActivity extends AppCompatActivity
{ {
DirectoryInitialization.start(this); DirectoryInitialization.start(this);
new AfterDirectoryInitializationRunner() new AfterDirectoryInitializationRunner()
.run(this, false, this::setPlatformTabsAndStartGameFileCacheService); .runWithLifecycle(this, false, this::setPlatformTabsAndStartGameFileCacheService);
} }
mPresenter.onResume(); mPresenter.onResume();
@ -254,7 +254,7 @@ public final class MainActivity extends AppCompatActivity
DirectoryInitialization.start(this); DirectoryInitialization.start(this);
new AfterDirectoryInitializationRunner() new AfterDirectoryInitializationRunner()
.run(this, false, this::setPlatformTabsAndStartGameFileCacheService); .runWithLifecycle(this, false, this::setPlatformTabsAndStartGameFileCacheService);
} }
} }

View file

@ -73,7 +73,7 @@ public final class MainPresenter
mView.launchFileListActivity(); mView.launchFileListActivity();
} }
public boolean handleOptionSelection(int itemId, Context context) public boolean handleOptionSelection(int itemId, ComponentActivity activity)
{ {
switch (itemId) switch (itemId)
{ {
@ -83,7 +83,7 @@ public final class MainPresenter
case R.id.menu_refresh: case R.id.menu_refresh:
mView.setRefreshing(true); mView.setRefreshing(true);
GameFileCacheManager.startRescan(context); GameFileCacheManager.startRescan(activity);
return true; return true;
case R.id.button_add_directory: case R.id.button_add_directory:
@ -95,17 +95,17 @@ public final class MainPresenter
return true; return true;
case R.id.menu_install_wad: case R.id.menu_install_wad:
new AfterDirectoryInitializationRunner().run(context, true, new AfterDirectoryInitializationRunner().runWithLifecycle(activity, true,
() -> mView.launchOpenFileActivity(REQUEST_WAD_FILE)); () -> mView.launchOpenFileActivity(REQUEST_WAD_FILE));
return true; return true;
case R.id.menu_import_wii_save: case R.id.menu_import_wii_save:
new AfterDirectoryInitializationRunner().run(context, true, new AfterDirectoryInitializationRunner().runWithLifecycle(activity, true,
() -> mView.launchOpenFileActivity(REQUEST_WII_SAVE_FILE)); () -> mView.launchOpenFileActivity(REQUEST_WII_SAVE_FILE));
return true; return true;
case R.id.menu_import_nand_backup: case R.id.menu_import_nand_backup:
new AfterDirectoryInitializationRunner().run(context, true, new AfterDirectoryInitializationRunner().runWithLifecycle(activity, true,
() -> mView.launchOpenFileActivity(REQUEST_NAND_BIN_FILE)); () -> mView.launchOpenFileActivity(REQUEST_NAND_BIN_FILE));
return true; return true;
} }
@ -121,12 +121,9 @@ public final class MainPresenter
mDirToAdd = null; mDirToAdd = null;
} }
if (sShouldRescanLibrary && !GameFileCacheManager.isRescanning().getValue()) if (sShouldRescanLibrary)
{ {
new AfterDirectoryInitializationRunner().run(mActivity, false, () -> GameFileCacheManager.startRescan(mActivity);
{
GameFileCacheManager.startRescan(mActivity);
});
} }
sShouldRescanLibrary = true; sShouldRescanLibrary = true;

View file

@ -3,30 +3,33 @@
package org.dolphinemu.dolphinemu.utils; package org.dolphinemu.dolphinemu.utils;
import android.content.Context; import android.content.Context;
import android.content.IntentFilter;
import android.widget.Toast; import android.widget.Toast;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.core.app.ComponentActivity;
import androidx.lifecycle.Observer;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
public class AfterDirectoryInitializationRunner public class AfterDirectoryInitializationRunner
{ {
private DirectoryStateReceiver mDirectoryStateReceiver; private Observer<DirectoryInitializationState> mObserver;
private LocalBroadcastManager mLocalBroadcastManager;
private Runnable mUnregisterCallback; private Runnable mUnregisterCallback;
/** /**
* Sets a Runnable which will be called when: * Sets a Runnable which will be called when:
* *
* 1. The Runnable supplied to {@link #run} is just about to run, or * 1. The Runnable supplied to {@link #runWithLifecycle}/{@link #runWithoutLifecycle}
* 2. {@link #run} was called with abortOnFailure == true and there is a failure * is just about to run, or
* 2. {@link #runWithLifecycle}/{@link #runWithoutLifecycle} was called with
* abortOnFailure == true and there is a failure
*
* @return this
*/ */
public void setFinishedCallback(Runnable runnable) public AfterDirectoryInitializationRunner setFinishedCallback(Runnable runnable)
{ {
mUnregisterCallback = runnable; mUnregisterCallback = runnable;
return this;
} }
private void runFinishedCallback() private void runFinishedCallback()
@ -48,13 +51,16 @@ public class AfterDirectoryInitializationRunner
* *
* 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 * If abortOnFailure is true and external storage was not found, a message
* permission or the external storage was not found, a message will be * will be shown to the user and the Runnable will not run. If it is false,
* shown to the user and the Runnable will not run. If it is false, the * the attempt to run the Runnable will never be aborted, and the Runnable
* attempt to run the Runnable will never be aborted, and the Runnable
* is guaranteed to run if directory initialization ever finishes. * is guaranteed to run if directory initialization ever finishes.
*
* If the passed-in activity gets destroyed before this operation finishes,
* it will be automatically canceled.
*/ */
public void run(Context context, boolean abortOnFailure, Runnable runnable) public void runWithLifecycle(ComponentActivity activity, boolean abortOnFailure,
Runnable runnable)
{ {
if (DirectoryInitialization.areDolphinDirectoriesReady()) if (DirectoryInitialization.areDolphinDirectoriesReady())
{ {
@ -62,19 +68,58 @@ public class AfterDirectoryInitializationRunner
runnable.run(); runnable.run();
} }
else if (abortOnFailure && else if (abortOnFailure &&
showErrorMessage(context, DirectoryInitialization.getDolphinDirectoriesState())) showErrorMessage(activity,
DirectoryInitialization.getDolphinDirectoriesState().getValue()))
{ {
runFinishedCallback(); runFinishedCallback();
} }
else else
{ {
runAfterInitialization(context, abortOnFailure, runnable); mObserver = createObserver(activity, abortOnFailure, runnable);
DirectoryInitialization.getDolphinDirectoriesState().observe(activity, mObserver);
} }
} }
private void runAfterInitialization(Context context, boolean abortOnFailure, Runnable runnable) /**
* Executes a Runnable after directory initialization has finished.
*
* If this is called when directory initialization already is done,
* the Runnable will be executed immediately. If this is called before
* directory initialization is done, the Runnable will be executed
* after directory initialization finishes successfully, or never
* in case directory initialization doesn't finish successfully.
*
* Calling this function multiple times per object is not supported.
*
* If abortOnFailure is true and 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 runWithoutLifecycle(Context context, boolean abortOnFailure, Runnable runnable)
{ {
mDirectoryStateReceiver = new DirectoryStateReceiver(state -> if (DirectoryInitialization.areDolphinDirectoriesReady())
{
runFinishedCallback();
runnable.run();
}
else if (abortOnFailure &&
showErrorMessage(context,
DirectoryInitialization.getDolphinDirectoriesState().getValue()))
{
runFinishedCallback();
}
else
{
mObserver = createObserver(context, abortOnFailure, runnable);
DirectoryInitialization.getDolphinDirectoriesState().observeForever(mObserver);
}
}
private Observer<DirectoryInitializationState> createObserver(Context context,
boolean abortOnFailure, Runnable runnable)
{
return (state) ->
{ {
boolean done = state == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; boolean done = state == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
@ -93,22 +138,12 @@ public class AfterDirectoryInitializationRunner
{ {
runnable.run(); runnable.run();
} }
}); };
mLocalBroadcastManager = LocalBroadcastManager.getInstance(context);
IntentFilter statusIntentFilter = new IntentFilter(DirectoryInitialization.BROADCAST_ACTION);
mLocalBroadcastManager.registerReceiver(mDirectoryStateReceiver, statusIntentFilter);
} }
public void cancel() public void cancel()
{ {
if (mDirectoryStateReceiver != null) DirectoryInitialization.getDolphinDirectoriesState().removeObserver(mObserver);
{
mLocalBroadcastManager.unregisterReceiver(mDirectoryStateReceiver);
mDirectoryStateReceiver = null;
mLocalBroadcastManager = null;
}
} }
private static boolean showErrorMessage(Context context, DirectoryInitializationState state) private static boolean showErrorMessage(Context context, DirectoryInitializationState state)

View file

@ -25,7 +25,7 @@ public class Analytics
public static void checkAnalyticsInit(Context context) public static void checkAnalyticsInit(Context context)
{ {
new AfterDirectoryInitializationRunner().run(context, false, () -> new AfterDirectoryInitializationRunner().runWithoutLifecycle(context, false, () ->
{ {
if (!BooleanSetting.MAIN_ANALYTICS_PERMISSION_ASKED.getBooleanGlobal()) if (!BooleanSetting.MAIN_ANALYTICS_PERMISSION_ASKED.getBooleanGlobal())
{ {

View file

@ -6,7 +6,6 @@
package org.dolphinemu.dolphinemu.utils; package org.dolphinemu.dolphinemu.utils;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
@ -14,18 +13,17 @@ import android.preference.PreferenceManager;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* A service that spawns its own thread in order to copy several binary and shader files * A service that spawns its own thread in order to copy several binary and shader files
@ -33,30 +31,29 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/ */
public final class DirectoryInitialization public final class DirectoryInitialization
{ {
public static final String BROADCAST_ACTION =
"org.dolphinemu.dolphinemu.DIRECTORY_INITIALIZATION";
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 = private static final MutableLiveData<DirectoryInitializationState> directoryState =
DirectoryInitializationState.NOT_YET_INITIALIZED; new MutableLiveData<>(DirectoryInitializationState.NOT_YET_INITIALIZED);
private static volatile boolean areDirectoriesAvailable = false; private static volatile boolean areDirectoriesAvailable = false;
private static String userPath; private static String userPath;
private static AtomicBoolean isDolphinDirectoryInitializationRunning = new AtomicBoolean(false);
private static boolean isUsingLegacyUserDirectory = false; private static boolean isUsingLegacyUserDirectory = false;
public enum DirectoryInitializationState public enum DirectoryInitializationState
{ {
NOT_YET_INITIALIZED, NOT_YET_INITIALIZED,
INITIALIZING,
DOLPHIN_DIRECTORIES_INITIALIZED, DOLPHIN_DIRECTORIES_INITIALIZED,
CANT_FIND_EXTERNAL_STORAGE CANT_FIND_EXTERNAL_STORAGE
} }
public static void start(Context context) public static void start(Context context)
{ {
if (!isDolphinDirectoryInitializationRunning.compareAndSet(false, true)) if (directoryState.getValue() == DirectoryInitializationState.INITIALIZING)
return; return;
directoryState.setValue(DirectoryInitializationState.INITIALIZING);
// Can take a few seconds to run, so don't block UI thread. // Can take a few seconds to run, so don't block UI thread.
//noinspection TrivialFunctionalExpressionUsage //noinspection TrivialFunctionalExpressionUsage
((Runnable) () -> init(context)).run(); ((Runnable) () -> init(context)).run();
@ -64,7 +61,7 @@ public final class DirectoryInitialization
private static void init(Context context) private static void init(Context context)
{ {
if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) if (directoryState.getValue() != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{ {
if (setDolphinUserDirectory(context)) if (setDolphinUserDirectory(context))
{ {
@ -82,16 +79,13 @@ public final class DirectoryInitialization
EmulationActivity.updateWiimoteNewIniPreferences(context); EmulationActivity.updateWiimoteNewIniPreferences(context);
} }
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; directoryState.postValue(DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED);
} }
else else
{ {
directoryState = DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE; directoryState.postValue(DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE);
} }
} }
isDolphinDirectoryInitializationRunning.set(false);
sendBroadcastState(directoryState, context);
} }
@Nullable @Nullable
@ -216,17 +210,18 @@ public final class DirectoryInitialization
public static boolean shouldStart(Context context) public static boolean shouldStart(Context context)
{ {
return !isDolphinDirectoryInitializationRunning.get() && return getDolphinDirectoriesState().getValue() ==
getDolphinDirectoriesState() == DirectoryInitializationState.NOT_YET_INITIALIZED && DirectoryInitializationState.NOT_YET_INITIALIZED &&
!isWaitingForWriteAccess(context); !isWaitingForWriteAccess(context);
} }
public static boolean areDolphinDirectoriesReady() public static boolean areDolphinDirectoriesReady()
{ {
return directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; return directoryState.getValue() ==
DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
} }
public static DirectoryInitializationState getDolphinDirectoriesState() public static LiveData<DirectoryInitializationState> getDolphinDirectoriesState()
{ {
return directoryState; return directoryState;
} }
@ -241,14 +236,6 @@ public final class DirectoryInitialization
return userPath; return userPath;
} }
private static void sendBroadcastState(DirectoryInitializationState state, Context context)
{
Intent localIntent =
new Intent(BROADCAST_ACTION)
.putExtra(EXTRA_STATE, state);
LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent);
}
private static boolean copyAsset(String asset, File output, Boolean overwrite, Context context) private static boolean copyAsset(String asset, File output, Boolean overwrite, Context context)
{ {
Log.verbose("[DirectoryInitialization] Copying File " + asset + " to " + output); Log.verbose("[DirectoryInitialization] Copying File " + asset + " to " + output);
@ -400,7 +387,7 @@ public final class DirectoryInitialization
public static boolean isWaitingForWriteAccess(Context context) public static boolean isWaitingForWriteAccess(Context context)
{ {
// This first check is only for performance, not correctness // This first check is only for performance, not correctness
if (getDolphinDirectoriesState() != DirectoryInitializationState.NOT_YET_INITIALIZED) if (directoryState.getValue() != DirectoryInitializationState.NOT_YET_INITIALIZED)
return false; return false;
return preferLegacyUserDirectory(context) && !PermissionsHandler.hasWriteAccess(context); return preferLegacyUserDirectory(context) && !PermissionsHandler.hasWriteAccess(context);

View file

@ -1,27 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.utils;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
public class DirectoryStateReceiver extends BroadcastReceiver
{
Action1<DirectoryInitializationState> callback;
public DirectoryStateReceiver(Action1<DirectoryInitializationState> callback)
{
this.callback = callback;
}
@Override
public void onReceive(Context context, Intent intent)
{
DirectoryInitializationState state = (DirectoryInitializationState) intent
.getSerializableExtra(DirectoryInitialization.EXTRA_STATE);
callback.call(state);
}
}

View file

@ -79,7 +79,7 @@ public final class StartupHandler
final Instant lastOpened = Instant.ofEpochMilli(lastOpen); final Instant lastOpened = Instant.ofEpochMilli(lastOpen);
if (current.isAfter(lastOpened.plus(6, ChronoUnit.HOURS))) if (current.isAfter(lastOpened.plus(6, ChronoUnit.HOURS)))
{ {
new AfterDirectoryInitializationRunner().run(context, false, new AfterDirectoryInitializationRunner().runWithoutLifecycle(context, false,
NativeLibrary::ReportStartToAnalytics); NativeLibrary::ReportStartToAnalytics);
} }
} }