Skip to content
Permalink
Browse files
Merge pull request #6258 from mahdihijazi/extract_service
[Android] Refactor AssetCopyService and the way we extract resources …
  • Loading branch information
JosJuice committed Dec 24, 2017
2 parents bedc814 + 2cecb64 commit bfa7c14
Show file tree
Hide file tree
Showing 13 changed files with 374 additions and 138 deletions.
@@ -65,7 +65,7 @@
android:theme="@style/DolphinEmulationGamecube"/>


<service android:name=".services.AssetCopyService"/>
<service android:name=".services.DirectoryInitializationService"/>

<provider
android:name=".model.GameProvider"
@@ -1,24 +1,32 @@
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;
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 View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
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 void onDetach()
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();

This file was deleted.

@@ -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.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 void onRequestPermissionsResult(int requestCode, String[] permissions, in
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);

0 comments on commit bfa7c14

Please sign in to comment.