diff --git a/platform/android/app/build.gradle b/platform/android/app/build.gradle index f074fd7..e29fd39 100644 --- a/platform/android/app/build.gradle +++ b/platform/android/app/build.gradle @@ -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' diff --git a/platform/android/app/src/main/AndroidManifest.xml b/platform/android/app/src/main/AndroidManifest.xml index 1319d68..2b2a0c4 100644 --- a/platform/android/app/src/main/AndroidManifest.xml +++ b/platform/android/app/src/main/AndroidManifest.xml @@ -11,11 +11,25 @@ + + + + + + - diff --git a/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/Util.java b/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/Util.java index cd295f8..3a40bcf 100644 --- a/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/Util.java +++ b/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/Util.java @@ -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)); + } } diff --git a/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/ui/EmulatorActivity.java b/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/ui/EmulatorActivity.java index 444828c..cae22cd 100644 --- a/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/ui/EmulatorActivity.java +++ b/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/ui/EmulatorActivity.java @@ -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(); } diff --git a/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/ui/library/RomListActivity.java b/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/ui/library/RomListActivity.java index b6edb45..013c715 100644 --- a/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/ui/library/RomListActivity.java +++ b/platform/android/app/src/main/java/com/mrmichel/rustdroid_emu/ui/library/RomListActivity.java @@ -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; } diff --git a/platform/android/app/src/main/res/menu/menu_context_rom.xml b/platform/android/app/src/main/res/menu/menu_context_rom.xml index e680f2a..2fd57d1 100644 --- a/platform/android/app/src/main/res/menu/menu_context_rom.xml +++ b/platform/android/app/src/main/res/menu/menu_context_rom.xml @@ -14,13 +14,12 @@ + android:title="@string/action_set_screenshot" /> + app:showAsAction="withText" /> + + + + +