platform/android: Add option to import/export save files

Also some typos and reformatting parts of the code


Former-commit-id: 0f1de44fab44a09c49d08421a3c2032123d3023b
Former-commit-id: 810b6b1bce1f7feeee7c33bec5ff16915367db17
This commit is contained in:
Michel Heily 2020-09-30 23:55:32 +03:00 committed by MishMish
parent 3c6628138c
commit d1bf01d562
6 changed files with 118 additions and 22 deletions

View file

@ -51,6 +51,7 @@ dependencies {
implementation 'com.google.android.material:material:1.1.0'
implementation "androidx.documentfile:documentfile:1.0.1"
implementation 'androidx.preference:preference:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'commons-io:commons-io:2.6'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'

View file

@ -11,11 +11,25 @@
<application
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:isGame="true"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!-- Needed for Android >= Nougat for file access -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.mrmichel.rustdroid_emu.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<activity android:name=".ui.snapshots.SnapshotPickerActivity" />
<activity
android:name=".ui.snapshots.SnapshotListFragment"
@ -26,7 +40,8 @@
<activity
android:name=".ui.EmulatorActivity"
android:label="@string/title_activity_emulator" />
<activity android:name=".ui.SettingsActivity"
<activity
android:name=".ui.SettingsActivity"
android:label="Settings" />
<activity android:name=".ui.SplashActivity">
<intent-filter>

View file

@ -5,9 +5,12 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.FileProvider;
import com.mrmichel.rustdroid_emu.ui.EmulatorActivity;
@ -35,7 +38,7 @@ public class Util {
}
public static void showAlertDiaglogAndExit(final Activity activity, Exception e) {
public static void showAlertDialogAndExit(final Activity activity, Exception e) {
new AlertDialog.Builder(activity)
.setTitle(e.toString())
.setMessage(e.getMessage())
@ -50,6 +53,15 @@ public class Util {
.show();
}
public static void showAlertDialog(final Activity activity, Exception e) {
new AlertDialog.Builder(activity)
.setTitle(e.toString())
.setMessage(e.getMessage())
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
public static byte[] compressBitmapToByteArray(Bitmap bitmap) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 10, byteArrayOutputStream);
@ -77,7 +89,7 @@ public class Util {
int len;
while ( (len = gis.read(buffer, 0, 8192)) != -1) {
while ((len = gis.read(buffer, 0, 8192)) != -1) {
outputStream.write(buffer, 0, len);
}
gis.close();
@ -88,14 +100,14 @@ public class Util {
}
}
public static byte[] readFile(File file) throws FileNotFoundException, IOException {
public static byte[] readFile(File file) throws IOException {
byte[] buffer = new byte[8192];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(file);
int len;
while ( (len = fis.read(buffer, 0, 8192)) != -1) {
while ((len = fis.read(buffer, 0, 8192)) != -1) {
outputStream.write(buffer, 0, len);
}
fis.close();
@ -123,4 +135,30 @@ public class Util {
md.update(bytes);
return byteArrayToHexString(md.digest());
}
public static void shareFile(Context context, File file, String message) throws FileNotFoundException {
if (!file.exists()) {
throw new FileNotFoundException("file does not exist");
}
final Uri uri;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
uri = Uri.fromFile(file);
} else {
uri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
}
if (uri == null) {
throw new FileNotFoundException("could not find file to share");
}
Intent intentShareFile = new Intent(Intent.ACTION_SEND);
intentShareFile.setType("*/*");
intentShareFile.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intentShareFile.putExtra(Intent.EXTRA_STREAM, uri);
intentShareFile.putExtra(Intent.EXTRA_TEXT, message);
context.startActivity(Intent.createChooser(intentShareFile, message));
}
}

View file

@ -4,10 +4,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
@ -210,7 +206,7 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
// onRomLoaded(rom, savePath);
// } catch (Exception e) {
// Log.e(TAG, "got error while reading rom file");
// Util.showAlertDiaglogAndExit(this, e);
// Util.showAlertDialogAndExit(this, e);
// }
// }
if (requestCode == LOAD_SNAPSHOT_REQUESTCODE) {
@ -224,7 +220,7 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
try {
emulator.loadState(pickedSnapshot.load());
} catch (Exception e) {
Util.showAlertDiaglogAndExit(this, e);
Util.showAlertDialogAndExit(this, e);
}
resumeEmulation();
@ -261,7 +257,7 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
// try {
// emulator.open(bios, rom, savePath);
// } catch (EmulatorBindings.NativeBindingException e) {
// Util.showAlertDiaglogAndExit(this, e);
// Util.showAlertDialogAndExit(this, e);
// }
//
// createThreads();
@ -297,7 +293,7 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
outState.putBoolean("turbo", false);
} catch (Exception e) {
Util.showAlertDiaglogAndExit(this, e);
Util.showAlertDialogAndExit(this, e);
}
}
@ -367,7 +363,7 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
emulator.setTurbo(turbo);
} catch (Exception e) {
Util.showAlertDiaglogAndExit(thisActivity, e);
Util.showAlertDialogAndExit(thisActivity, e);
}
} else {
@ -380,7 +376,7 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
romData = Util.readFile(romMetadata.getRomFile());
this.emulator.open(bios, romData, romMetadata.getBackupFile().getAbsolutePath(), skipBios);
} catch (Exception e) {
Util.showAlertDiaglogAndExit(this, e);
Util.showAlertDialogAndExit(this, e);
return;
}
@ -478,7 +474,7 @@ public class EmulatorActivity extends AppCompatActivity implements View.OnClickL
} catch (EmulatorBindings.NativeBindingException e) {
Log.e(TAG, e.toString());
Util.showAlertDiaglogAndExit(this, e);
Util.showAlertDialogAndExit(this, e);
} finally {
resumeEmulation();
}

View file

@ -25,9 +25,11 @@ import com.mrmichel.rustdroid_emu.R;
import com.mrmichel.rustdroid_emu.Util;
import com.mrmichel.rustdroid_emu.core.RomManager;
import com.mrmichel.rustdroid_emu.ui.SettingsActivity;
import com.mrmichel.rustdroid_emu.ui.SettingsFragment;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
@ -38,6 +40,7 @@ public class RomListActivity extends AppCompatActivity {
private static final int REQUEST_IMPORT_ROM = 100;
private static final int REQUEST_IMPORT_DIR = 101;
private static final int REQUEST_SET_IMAGE = 102;
private static final int REQUEST_IMPORT_SAVE = 103;
private static String[] ALLOWED_EXTENSIONS = {"gba", "zip", "bin"};
@ -111,6 +114,20 @@ public class RomListActivity extends AppCompatActivity {
intent.setType("image/*");
intent.putExtra("romId", entry.getId());
startActivityForResult(intent, REQUEST_SET_IMAGE);
return true;
case R.id.action_export_save_file:
File backupFile = entry.getBackupFile();
try {
Util.shareFile(this, backupFile, "Sending " + backupFile.getName());
} catch (FileNotFoundException e) {
Util.showAlertDialog(this, e);
}
return true;
case R.id.action_import_save_file:
intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, REQUEST_IMPORT_SAVE);
return true;
default:
return super.onContextItemSelected(item);
}
@ -128,12 +145,14 @@ public class RomListActivity extends AppCompatActivity {
switch (item.getItemId()) {
case R.id.action_import_rom:
doImportRom();
return true;
case R.id.action_import_directory:
doImportDirectory();
return true;
case R.id.action_settings:
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
@ -189,12 +208,29 @@ public class RomListActivity extends AppCompatActivity {
}
catch (Exception e) {
Util.showAlertDiaglogAndExit(this, e);
Util.showAlertDialogAndExit(this, e);
return;
}
Log.d(TAG, "found bitmap");
romManager.updateScreenshot(romId, bitmap);
break;
case REQUEST_IMPORT_SAVE:
try {
InputStream inputStream = getContentResolver().openInputStream(data.getData());
byte[] saveData = new byte[inputStream.available()];
inputStream.read(saveData);
inputStream.close();
File file = selectedEntry.getBackupFile();
Log.d(TAG, "Saving imported save to " + file.getAbsolutePath());
FileOutputStream fos = new FileOutputStream(file);
fos.write(saveData);
fos.close();
} catch (Exception e) {
Util.showAlertDialogAndExit(this, e);
}
break;
}

View file

@ -14,13 +14,12 @@
<item
android:id="@+id/action_set_screenshot"
android:title="@string/action_set_screenshot"
/>
android:title="@string/action_set_screenshot" />
<item
android:id="@+id/action_view_snapshots"
android:title="@string/action_view_snapshot"
app:showAsAction="withText"
android:id="@+id/action_view_snapshots" />
app:showAsAction="withText" />
<item
@ -28,4 +27,15 @@
android:icon="@android:drawable/ic_menu_delete"
android:title="@string/action_delete"
app:showAsAction="ifRoom|withText" />
<item
android:id="@+id/action_import_save_file"
android:icon="@android:drawable/ic_menu_save"
android:title="Import Save File" />
<item
android:id="@+id/action_export_save_file"
android:icon="@android:drawable/ic_menu_share"
android:title="Export Save File" />
</menu>