Android: Don't hard code the user dircetory path to /sdcard/dolphin-emu

Android is allowed to pick any path for the external storage media and
that's why we should always use Environment.getExternalStorageDirectory()
to get the external storage path
This commit is contained in:
mahdihijazi 2018-01-08 18:06:10 +01:00
parent 9a166dca57
commit ae8b469b80
8 changed files with 110 additions and 27 deletions

View File

@ -15,8 +15,6 @@ public class DolphinApplication extends Application
{
super.onCreate();
NativeLibrary.SetUserDirectory(""); // Empty string means use the default path
if (PermissionsHandler.hasWriteAccess(getApplicationContext()))
DirectoryInitializationService.startService(getApplicationContext());

View File

@ -158,13 +158,22 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
DirectoryInitializationService.BROADCAST_ACTION);
directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState -> {
if (directoryInitializationState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) {
new DirectoryStateReceiver(directoryInitializationState ->
{
if (directoryInitializationState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{
mEmulationState.run(activity.isActivityRecreated());
} else if (directoryInitializationState == DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) {
}
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

View File

@ -10,6 +10,7 @@ import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
@ -22,6 +23,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
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
@ -32,12 +35,15 @@ public final class DirectoryInitializationService extends IntentService
public static final String BROADCAST_ACTION = "org.dolphinemu.dolphinemu.BROADCAST";
public static final String EXTRA_STATE = "directoryState";
private static DirectoryInitializationState directoryState = null;
private static volatile DirectoryInitializationState directoryState = null;
private static String userPath;
private static AtomicBoolean isDolphinDirectoryInitializationRunning = new AtomicBoolean(false);
public enum DirectoryInitializationState
{
DOLPHIN_DIRECTORIES_INITIALIZED,
EXTERNAL_STORAGE_PERMISSION_NEEDED
EXTERNAL_STORAGE_PERMISSION_NEEDED,
CANT_FIND_EXTERNAL_STORAGE
}
public DirectoryInitializationService()
@ -55,21 +61,50 @@ public final class DirectoryInitializationService extends IntentService
@Override
protected void onHandleIntent(Intent intent)
{
if (directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
isDolphinDirectoryInitializationRunning.set(true);
if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{
sendBroadcastState(DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED);
if (PermissionsHandler.hasWriteAccess(this))
{
if (setDolphinUserDirectory())
{
initializeInternalStorage();
initializeExternalStorage();
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
}
else
{
directoryState = DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE;
}
}
else
{
directoryState = DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED;
}
}
else if (PermissionsHandler.hasWriteAccess(this))
isDolphinDirectoryInitializationRunning.set(false);
sendBroadcastState(directoryState);
}
private boolean setDolphinUserDirectory()
{
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
initializeInternalStorage();
initializeExternalStorage();
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
sendBroadcastState(directoryState);
}
else
{
sendBroadcastState(DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED);
File externalPath = Environment.getExternalStorageDirectory();
if (externalPath != null)
{
userPath = externalPath.getAbsolutePath() + "/dolphin-emu";
Log.debug("[DirectoryInitializationService] User Dir: " + userPath);
NativeLibrary.SetUserDirectory(userPath);
return true;
}
}
return false;
}
private void initializeInternalStorage()
@ -128,6 +163,20 @@ public final class DirectoryInitializationService extends IntentService
return directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
}
public static String getUserDirectory()
{
if (directoryState == null)
{
throw new IllegalStateException("DirectoryInitializationService has to run at least once!");
}
else if (isDolphinDirectoryInitializationRunning.get())
{
throw new IllegalStateException("DirectoryInitializationService has to finish running first!");
}
return userPath;
}
private void sendBroadcastState(DirectoryInitializationState state)
{
Intent localIntent =

View File

@ -161,6 +161,13 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
.show();
}
@Override
public void showExternalStorageNotMountedHint()
{
Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
.show();
}
@Override
public HashMap<String, SettingSection> getSettings(int file)
{

View File

@ -6,6 +6,7 @@ import android.os.Bundle;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.settings.SettingSection;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
import org.dolphinemu.dolphinemu.utils.Log;
import org.dolphinemu.dolphinemu.utils.SettingsFile;
@ -40,9 +41,6 @@ public final class SettingsActivityPresenter
{
if (savedInstanceState == null)
{
mSettings.add(SettingsFile.SETTINGS_DOLPHIN, SettingsFile.readFile(SettingsFile.FILE_NAME_DOLPHIN, mView));
mSettings.add(SettingsFile.SETTINGS_GFX, SettingsFile.readFile(SettingsFile.FILE_NAME_GFX, mView));
mSettings.add(SettingsFile.SETTINGS_WIIMOTE, SettingsFile.readFile(SettingsFile.FILE_NAME_WIIMOTE, mView));
this.menuTag = menuTag;
}
else
@ -58,6 +56,13 @@ public final class SettingsActivityPresenter
void loadSettingsUI()
{
if (mSettings.isEmpty())
{
mSettings.add(SettingsFile.SETTINGS_DOLPHIN, SettingsFile.readFile(SettingsFile.FILE_NAME_DOLPHIN, mView));
mSettings.add(SettingsFile.SETTINGS_GFX, SettingsFile.readFile(SettingsFile.FILE_NAME_GFX, mView));
mSettings.add(SettingsFile.SETTINGS_WIIMOTE, SettingsFile.readFile(SettingsFile.FILE_NAME_WIIMOTE, mView));
}
mView.showSettingsFragment(menuTag, false);
mView.onSettingsFileLoaded(mSettings);
}
@ -72,14 +77,23 @@ public final class SettingsActivityPresenter
DirectoryInitializationService.BROADCAST_ACTION);
directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState -> {
if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) {
new DirectoryStateReceiver(directoryInitializationState ->
{
if (directoryInitializationState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{
mView.hideLoading();
loadSettingsUI();
} else if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) {
}
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);

View File

@ -118,6 +118,11 @@ public interface SettingsActivityView
*/
void showPermissionNeededHint();
/**
* Show a hint to the user that the app needs the external storage to be mounted
*/
void showExternalStorageNotMountedHint();
/**
* Start the DirectoryInitializationService and listen for the result.
*

View File

@ -1,6 +1,5 @@
package org.dolphinemu.dolphinemu.utils;
import android.os.Environment;
import android.support.annotation.NonNull;
import org.dolphinemu.dolphinemu.model.settings.BooleanSetting;
@ -9,6 +8,7 @@ import org.dolphinemu.dolphinemu.model.settings.IntSetting;
import org.dolphinemu.dolphinemu.model.settings.Setting;
import org.dolphinemu.dolphinemu.model.settings.SettingSection;
import org.dolphinemu.dolphinemu.model.settings.StringSetting;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivityView;
import java.io.BufferedReader;
@ -393,8 +393,7 @@ public final class SettingsFile
@NonNull
private static File getSettingsFile(String fileName)
{
String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
return new File(storagePath + "/dolphin-emu/Config/" + fileName + ".ini");
return new File(DirectoryInitializationService.getUserDirectory() + "/Config/" + fileName + ".ini");
}
private static SettingSection sectionFromLine(String line)

View File

@ -251,4 +251,6 @@
<string name="load_settings">Loading Settings...</string>
<string name="emulation_change_disc">Change Disc</string>
<string name="external_storage_not_mounted">The external storage needs to be available in order to use Dolphin</string>
</resources>