Merge pull request #6258 from mahdihijazi/extract_service
[Android] Refactor AssetCopyService and the way we extract resources …
This commit is contained in:
commit
bfa7c14fef
|
@ -65,7 +65,7 @@
|
|||
android:theme="@style/DolphinEmulationGamecube"/>
|
||||
|
||||
|
||||
<service android:name=".services.AssetCopyService"/>
|
||||
<service android:name=".services.DirectoryInitializationService"/>
|
||||
|
||||
<provider
|
||||
android:name=".model.GameProvider"
|
||||
|
|
|
@ -1,10 +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 android.support.v4.app.Fragment;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
|
@ -12,13 +14,19 @@ import android.view.SurfaceView;
|
|||
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.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState;
|
||||
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
|
||||
import rx.functions.Action1;
|
||||
|
||||
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback
|
||||
{
|
||||
private static final String KEY_GAMEPATH = "gamepath";
|
||||
|
@ -29,6 +37,8 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
|
||||
private EmulationState mEmulationState;
|
||||
|
||||
private DirectoryStateReceiver directoryStateReceiver;
|
||||
|
||||
public static EmulationFragment newInstance(String gamePath)
|
||||
{
|
||||
|
||||
|
@ -108,12 +118,25 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
mEmulationState.run();
|
||||
if (DirectoryInitializationService.areDolphinDirectoriesReady())
|
||||
{
|
||||
mEmulationState.run();
|
||||
}
|
||||
else
|
||||
{
|
||||
setupDolphinDirectoriesThenStartEmulation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
if (directoryStateReceiver != null)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
|
||||
mEmulationState.pause();
|
||||
super.onPause();
|
||||
}
|
||||
|
@ -125,6 +148,27 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
|||
super.onDetach();
|
||||
}
|
||||
|
||||
private void setupDolphinDirectoriesThenStartEmulation() {
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
|
||||
directoryStateReceiver =
|
||||
new DirectoryStateReceiver(directoryInitializationState -> {
|
||||
if (directoryInitializationState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) {
|
||||
mEmulationState.run();
|
||||
} else if (directoryInitializationState == DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) {
|
||||
Toast.makeText(getContext(), R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
// Registers the DirectoryStateReceiver and its intent filters
|
||||
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
|
||||
directoryStateReceiver,
|
||||
statusIntentFilter);
|
||||
DirectoryInitializationService.startService(getActivity());
|
||||
}
|
||||
|
||||
public void toggleInputOverlayVisibility()
|
||||
{
|
||||
SharedPreferences.Editor editor = mPreferences.edit();
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
/**
|
||||
* Copyright 2014 Dolphin Emulator Project
|
||||
* Licensed under GPLv2+
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu.services;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A service that spawns its own thread in order to copy several binary and shader files
|
||||
* from the Dolphin APK to the external file system.
|
||||
*/
|
||||
public final class AssetCopyService extends IntentService
|
||||
{
|
||||
public AssetCopyService()
|
||||
{
|
||||
// Superclass constructor is called to name the thread on which this service executes.
|
||||
super("AssetCopyService");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent)
|
||||
{
|
||||
String BaseDir = NativeLibrary.GetUserDirectory();
|
||||
String ConfigDir = BaseDir + File.separator + "Config";
|
||||
|
||||
// Copy assets if needed
|
||||
NativeLibrary.CreateUserFolders();
|
||||
copyAssetFolder("GC", BaseDir + File.separator + "GC", false);
|
||||
copyAssetFolder("Shaders", BaseDir + File.separator + "Shaders", false);
|
||||
copyAssetFolder("Wii", BaseDir + File.separator + "Wii", false);
|
||||
|
||||
// Always copy over the GCPad config in case of change or corruption.
|
||||
// Not a user configurable file.
|
||||
copyAsset("GCPadNew.ini", ConfigDir + File.separator + "GCPadNew.ini", true);
|
||||
copyAsset("WiimoteNew.ini", ConfigDir + File.separator + "WiimoteNew.ini", true);
|
||||
|
||||
// Record the fact that we've done this before, so we don't do it on every launch.
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
editor.putBoolean("assetsCopied", true);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
private void copyAsset(String asset, String output, Boolean overwrite)
|
||||
{
|
||||
Log.verbose("[AssetCopyService] Copying File " + asset + " to " + output);
|
||||
InputStream in;
|
||||
OutputStream out;
|
||||
|
||||
try
|
||||
{
|
||||
File file = new File(output);
|
||||
if(!file.exists() || overwrite)
|
||||
{
|
||||
in = getAssets().open(asset);
|
||||
out = new FileOutputStream(output);
|
||||
copyFile(in, out);
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.error("[AssetCopyService] Failed to copy asset file: " + asset + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void copyAssetFolder(String assetFolder, String outputFolder, Boolean overwrite)
|
||||
{
|
||||
Log.verbose("[AssetCopyService] Copying Folder " + assetFolder + " to " + outputFolder);
|
||||
|
||||
try
|
||||
{
|
||||
for (String file : getAssets().list(assetFolder))
|
||||
{
|
||||
copyAssetFolder(assetFolder + File.separator + file, outputFolder + File.separator + file, overwrite);
|
||||
copyAsset(assetFolder + File.separator + file, outputFolder + File.separator + file, overwrite);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.error("[AssetCopyService] Failed to copy asset folder: " + assetFolder + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void copyFile(InputStream in, OutputStream out) throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
|
||||
while ((read = in.read(buffer)) != -1)
|
||||
{
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/**
|
||||
* Copyright 2014 Dolphin Emulator Project
|
||||
* Licensed under GPLv2+
|
||||
* Refer to the license.txt file included.
|
||||
*/
|
||||
|
||||
package org.dolphinemu.dolphinemu.services;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A service that spawns its own thread in order to copy several binary and shader files
|
||||
* from the Dolphin APK to the external file system.
|
||||
*/
|
||||
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;
|
||||
|
||||
public enum DirectoryInitializationState
|
||||
{
|
||||
DOLPHIN_DIRECTORIES_INITIALIZED,
|
||||
EXTERNAL_STORAGE_PERMISSION_NEEDED
|
||||
}
|
||||
|
||||
public DirectoryInitializationService()
|
||||
{
|
||||
// Superclass constructor is called to name the thread on which this service executes.
|
||||
super("DirectoryInitializationService");
|
||||
}
|
||||
|
||||
public static void startService(Context context)
|
||||
{
|
||||
Intent intent = new Intent(context, DirectoryInitializationService.class);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent)
|
||||
{
|
||||
if (directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
sendBroadcastState(DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED);
|
||||
}
|
||||
else if (PermissionsHandler.hasWriteAccess(this))
|
||||
{
|
||||
initDolphinDirectories();
|
||||
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
|
||||
sendBroadcastState(directoryState);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendBroadcastState(DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED);
|
||||
}
|
||||
}
|
||||
|
||||
private void initDolphinDirectories()
|
||||
{
|
||||
String BaseDir = NativeLibrary.GetUserDirectory();
|
||||
String ConfigDir = BaseDir + File.separator + "Config";
|
||||
|
||||
// Copy assets if needed
|
||||
NativeLibrary.CreateUserFolders();
|
||||
copyAssetFolder("GC", BaseDir + File.separator + "GC", false);
|
||||
copyAssetFolder("Shaders", BaseDir + File.separator + "Shaders", false);
|
||||
copyAssetFolder("Wii", BaseDir + File.separator + "Wii", false);
|
||||
|
||||
// Always copy over the GCPad config in case of change or corruption.
|
||||
// Not a user configurable file.
|
||||
copyAsset("GCPadNew.ini", ConfigDir + File.separator + "GCPadNew.ini", true);
|
||||
copyAsset("WiimoteNew.ini", ConfigDir + File.separator + "WiimoteNew.ini", false);
|
||||
}
|
||||
|
||||
public static boolean areDolphinDirectoriesReady()
|
||||
{
|
||||
return directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
|
||||
}
|
||||
|
||||
private void sendBroadcastState(DirectoryInitializationState state)
|
||||
{
|
||||
Intent localIntent =
|
||||
new Intent(BROADCAST_ACTION)
|
||||
.putExtra(EXTRA_STATE, state);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
|
||||
}
|
||||
|
||||
private void copyAsset(String asset, String output, Boolean overwrite)
|
||||
{
|
||||
Log.verbose("[DirectoryInitializationService] Copying File " + asset + " to " + output);
|
||||
InputStream in;
|
||||
OutputStream out;
|
||||
|
||||
try
|
||||
{
|
||||
File file = new File(output);
|
||||
if (!file.exists() || overwrite)
|
||||
{
|
||||
in = getAssets().open(asset);
|
||||
out = new FileOutputStream(output);
|
||||
copyFile(in, out);
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.error("[DirectoryInitializationService] Failed to copy asset file: " + asset + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void copyAssetFolder(String assetFolder, String outputFolder, Boolean overwrite)
|
||||
{
|
||||
Log.verbose("[DirectoryInitializationService] Copying Folder " + assetFolder + " to " + outputFolder);
|
||||
|
||||
try
|
||||
{
|
||||
for (String file : getAssets().list(assetFolder))
|
||||
{
|
||||
copyAssetFolder(assetFolder + File.separator + file, outputFolder + File.separator + file, overwrite);
|
||||
copyAsset(assetFolder + File.separator + file, outputFolder + File.separator + file, overwrite);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.error("[DirectoryInitializationService] Failed to copy asset folder: " + assetFolder + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void copyFile(InputStream in, OutputStream out) throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
|
||||
while ((read = in.read(buffer)) != -1)
|
||||
{
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import org.dolphinemu.dolphinemu.R;
|
|||
import org.dolphinemu.dolphinemu.activities.AddDirectoryActivity;
|
||||
import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter;
|
||||
import org.dolphinemu.dolphinemu.model.GameProvider;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
||||
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView;
|
||||
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity;
|
||||
|
@ -154,7 +155,7 @@ public final class MainActivity extends AppCompatActivity implements MainView
|
|||
switch (requestCode) {
|
||||
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
StartupHandler.copyAssetsIfNeeded(this);
|
||||
DirectoryInitializationService.startService(this);
|
||||
|
||||
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(
|
||||
getSupportFragmentManager(), this);
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.dolphinemu.dolphinemu.adapters.GameRowPresenter;
|
|||
import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter;
|
||||
import org.dolphinemu.dolphinemu.model.Game;
|
||||
import org.dolphinemu.dolphinemu.model.TvSettingsItem;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
||||
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity;
|
||||
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
|
||||
|
@ -157,7 +158,7 @@ public final class TvMainActivity extends FragmentActivity implements MainView
|
|||
switch (requestCode) {
|
||||
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
StartupHandler.copyAssetsIfNeeded(this);
|
||||
DirectoryInitializationService.startService(this);
|
||||
loadGames();
|
||||
} else {
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package org.dolphinemu.dolphinemu.ui.settings;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
|
@ -12,6 +15,8 @@ import android.widget.Toast;
|
|||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.model.settings.SettingSection;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -22,6 +27,8 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
|
|||
private static final String FRAGMENT_TAG = "settings";
|
||||
private SettingsActivityPresenter mPresenter = new SettingsActivityPresenter(this);
|
||||
|
||||
private ProgressDialog dialog;
|
||||
|
||||
public static void launch(Context context, String menuTag)
|
||||
{
|
||||
Intent settings = new Intent(context, SettingsActivity.class);
|
||||
|
@ -65,6 +72,13 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
|
|||
mPresenter.saveState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
mPresenter.onStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is called, the user has left the settings screen (potentially through the
|
||||
* home button) and will expect their changes to be persisted. So we kick off an
|
||||
|
@ -106,6 +120,47 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
|
|||
transaction.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(
|
||||
receiver,
|
||||
filter);
|
||||
DirectoryInitializationService.startService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showLoading()
|
||||
{
|
||||
if (dialog == null)
|
||||
{
|
||||
dialog = new ProgressDialog(this);
|
||||
dialog.setMessage(getString(R.string.load_settings));
|
||||
dialog.setIndeterminate(true);
|
||||
}
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideLoading()
|
||||
{
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPermissionNeededHint()
|
||||
{
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, SettingSection> getSettings(int file)
|
||||
{
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
package org.dolphinemu.dolphinemu.ui.settings;
|
||||
|
||||
import android.content.IntentFilter;
|
||||
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.utils.DirectoryStateReceiver;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
import org.dolphinemu.dolphinemu.utils.SettingsFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import rx.functions.Action1;
|
||||
|
||||
public final class SettingsActivityPresenter
|
||||
{
|
||||
private static final String KEY_SHOULD_SAVE = "should_save";
|
||||
|
@ -22,6 +27,10 @@ public final class SettingsActivityPresenter
|
|||
|
||||
private boolean mShouldSave;
|
||||
|
||||
private DirectoryStateReceiver directoryStateReceiver;
|
||||
|
||||
private String menuTag;
|
||||
|
||||
public SettingsActivityPresenter(SettingsActivityView view)
|
||||
{
|
||||
mView = view;
|
||||
|
@ -31,12 +40,10 @@ public final class SettingsActivityPresenter
|
|||
{
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
mView.showSettingsFragment(menuTag, false);
|
||||
|
||||
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.onSettingsFileLoaded(mSettings);
|
||||
this.menuTag = menuTag;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -44,6 +51,41 @@ public final class SettingsActivityPresenter
|
|||
}
|
||||
}
|
||||
|
||||
public void onStart()
|
||||
{
|
||||
prepareDolphinDirectoriesIfNeeded();
|
||||
}
|
||||
|
||||
void loadSettingsUI()
|
||||
{
|
||||
mView.showSettingsFragment(menuTag, false);
|
||||
mView.onSettingsFileLoaded(mSettings);
|
||||
}
|
||||
|
||||
private void prepareDolphinDirectoriesIfNeeded()
|
||||
{
|
||||
if (DirectoryInitializationService.areDolphinDirectoriesReady()) {
|
||||
loadSettingsUI();
|
||||
} else {
|
||||
mView.showLoading();
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
|
||||
directoryStateReceiver =
|
||||
new DirectoryStateReceiver(directoryInitializationState -> {
|
||||
if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) {
|
||||
mView.hideLoading();
|
||||
loadSettingsUI();
|
||||
} else if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) {
|
||||
mView.showPermissionNeededHint();
|
||||
mView.hideLoading();
|
||||
}
|
||||
});
|
||||
|
||||
mView.startDirectoryInitializationService(directoryStateReceiver, statusIntentFilter);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSettings(ArrayList<HashMap<String, SettingSection>> settings)
|
||||
{
|
||||
mSettings = settings;
|
||||
|
@ -56,6 +98,12 @@ public final class SettingsActivityPresenter
|
|||
|
||||
public void onStop(boolean finishing)
|
||||
{
|
||||
if (directoryStateReceiver != null)
|
||||
{
|
||||
mView.stopListeningToDirectoryInitializationService(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
|
||||
if (mSettings != null && finishing && mShouldSave)
|
||||
{
|
||||
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package org.dolphinemu.dolphinemu.ui.settings;
|
||||
|
||||
import android.content.IntentFilter;
|
||||
|
||||
import org.dolphinemu.dolphinemu.model.settings.SettingSection;
|
||||
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -99,4 +102,34 @@ public interface SettingsActivityView
|
|||
* @param value New setting for the extension.
|
||||
*/
|
||||
void onExtensionSettingChanged(String key, int value);
|
||||
|
||||
/**
|
||||
* Show loading dialog while loading the settings
|
||||
*/
|
||||
void showLoading();
|
||||
|
||||
/**
|
||||
* Hide the loading the dialog
|
||||
*/
|
||||
void hideLoading();
|
||||
|
||||
/**
|
||||
* Show a hint to the user that the app needs write to external storage access
|
||||
*/
|
||||
void showPermissionNeededHint();
|
||||
|
||||
/**
|
||||
* Start the DirectoryInitializationService and listen for the result.
|
||||
*
|
||||
* @param receiver the broadcast receiver for the DirectoryInitializationService
|
||||
* @param filter the Intent broadcasts to be received.
|
||||
*/
|
||||
void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter);
|
||||
|
||||
/**
|
||||
* Stop listening to the DirectoryInitializationService.
|
||||
*
|
||||
* @param receiver The broadcast receiver to unregister.
|
||||
*/
|
||||
void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package org.dolphinemu.dolphinemu.utils;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState;
|
||||
|
||||
import rx.functions.Action1;
|
||||
|
||||
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(DirectoryInitializationService.EXTRA_STATE);
|
||||
callback.call(state);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package org.dolphinemu.dolphinemu.utils;
|
|||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
|
@ -40,9 +41,9 @@ public class PermissionsHandler {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static boolean hasWriteAccess(FragmentActivity activity) {
|
||||
public static boolean hasWriteAccess(Context context) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
int hasWritePermission = ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE);
|
||||
int hasWritePermission = ContextCompat.checkSelfPermission(context, WRITE_EXTERNAL_STORAGE);
|
||||
return hasWritePermission == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package org.dolphinemu.dolphinemu.utils;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||
import org.dolphinemu.dolphinemu.services.AssetCopyService;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
|
||||
public final class StartupHandler
|
||||
{
|
||||
|
@ -17,9 +15,8 @@ public final class StartupHandler
|
|||
{
|
||||
NativeLibrary.SetUserDirectory(""); // Auto-Detect
|
||||
|
||||
// Only perform these extensive copy operations once.
|
||||
if (PermissionsHandler.checkWritePermission(parent)) {
|
||||
copyAssetsIfNeeded(parent);
|
||||
DirectoryInitializationService.startService(parent);
|
||||
}
|
||||
|
||||
Intent intent = parent.getIntent();
|
||||
|
@ -45,16 +42,4 @@ public final class StartupHandler
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void copyAssetsIfNeeded(FragmentActivity parent) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
|
||||
boolean assetsCopied = preferences.getBoolean("assetsCopied", false);
|
||||
|
||||
if (!assetsCopied)
|
||||
{
|
||||
// Copy assets into appropriate locations.
|
||||
Intent copyAssets = new Intent(parent, AssetCopyService.class);
|
||||
parent.startService(copyAssets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -247,4 +247,6 @@
|
|||
<string name="header_controllers">Controllers</string>
|
||||
|
||||
<string name="write_permission_needed">You need to allow write access to external storage for the emulator to work</string>
|
||||
|
||||
<string name="load_settings">Loading Settings...</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue