From 3f0fa315b2672093d4fa7c7266b1820fed41d6ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 11 May 2026 11:37:42 +0200 Subject: [PATCH] Refactor the Java file picker code --- .../ppsspp/DocumentResultProxyActivity.java | 42 +++++++++------- .../ppsspp/ImageResultProxyActivity.java | 48 ++++++++++--------- android/src/org/ppsspp/ppsspp/NativeApp.java | 1 + 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/android/src/org/ppsspp/ppsspp/DocumentResultProxyActivity.java b/android/src/org/ppsspp/ppsspp/DocumentResultProxyActivity.java index 508137a549..cae1424c18 100644 --- a/android/src/org/ppsspp/ppsspp/DocumentResultProxyActivity.java +++ b/android/src/org/ppsspp/ppsspp/DocumentResultProxyActivity.java @@ -1,6 +1,7 @@ package org.ppsspp.ppsspp; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -14,6 +15,18 @@ import androidx.documentfile.provider.DocumentFile; public class DocumentResultProxyActivity extends AppCompatActivity { public static final String TAG = "PPSSPP"; + private void returnWithResult(int resultCode, int requestId, String resultPath) { + Intent returnIntent = new Intent(this, PpssppActivity.class); + returnIntent.putExtra("result_code", resultCode); + returnIntent.putExtra("request_id", requestId); + if (resultPath != null) { + returnIntent.putExtra("result_path", resultPath); + } + returnIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); + startActivity(returnIntent); + finish(); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -29,7 +42,7 @@ public class DocumentResultProxyActivity extends AppCompatActivity { result -> { Log.i(TAG, "DocumentResultProxy: Packing return intent, requestId = " + requestId); - Intent returnIntent = new Intent(this, PpssppActivity.class); + String resultPath = null; if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { Uri uri = result.getData().getData(); if (uri != null) { @@ -48,35 +61,30 @@ public class DocumentResultProxyActivity extends AppCompatActivity { } catch (Exception e) { Log.w(TAG, "DocumentResultProxy: Exception getting permissions or DocumentFile: " + e); } - returnIntent.putExtra("result_path", uri.toString()); + resultPath = uri.toString(); } else { Log.w(TAG, "DocumentResultProxy: URI is null in result data"); } } - returnIntent.putExtra("result_code", result.getResultCode()); - returnIntent.putExtra("request_id", requestId); - - // This flag is key: it finds the existing instance of your main activity - returnIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - startActivity(returnIntent); - finish(); + returnWithResult(result.getResultCode(), requestId, resultPath); } ); + // Only launch the picker if we are starting fresh. If we're being recreated (e.g. rotation), + // the ActivityResultRegistry will handle delivering the pending result to the launcher + // automatically, and we don't want to launch the picker a second time. if (savedInstanceState == null) { if (pickerIntent != null) { try { + // throw new ActivityNotFoundException(); // Use this for testing the fallback. launcher.launch(pickerIntent); + } catch (ActivityNotFoundException e) { + NativeApp.reportException(e, "DocumentResultProxy: failed to launch picker intent, activity not found: " + pickerIntent.getAction()); + returnWithResult(NativeApp.RESULT_ERROR_ACTIVITY_NOT_FOUND, requestId, null); } catch (Exception e) { - NativeApp.reportException(e, "DocumentResultProxy: failed to launch picker intent " + pickerIntent.getAction()); - // Return to main activity with an error result. - Intent returnIntent = new Intent(this, PpssppActivity.class); - returnIntent.putExtra("result_code", NativeApp.RESULT_ERROR_ACTIVITY_NOT_FOUND); - returnIntent.putExtra("request_id", requestId); - returnIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - startActivity(returnIntent); - finish(); + NativeApp.reportException(e, "DocumentResultProxy: failed to launch picker intent, other error: " + pickerIntent.getAction()); + returnWithResult(NativeApp.RESULT_ERROR_OTHER_ACTIVITY_ERROR, requestId, null); } } else { Log.e(TAG, "DocumentResultProxy: No picker intent provided"); diff --git a/android/src/org/ppsspp/ppsspp/ImageResultProxyActivity.java b/android/src/org/ppsspp/ppsspp/ImageResultProxyActivity.java index d0cea8d00b..3a778fe67e 100644 --- a/android/src/org/ppsspp/ppsspp/ImageResultProxyActivity.java +++ b/android/src/org/ppsspp/ppsspp/ImageResultProxyActivity.java @@ -1,6 +1,7 @@ package org.ppsspp.ppsspp; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -110,6 +111,18 @@ public class ImageResultProxyActivity extends AppCompatActivity { } } + private void returnWithResult(int resultCode, int requestId, String resultPath) { + Intent returnIntent = new Intent(this, PpssppActivity.class); + returnIntent.putExtra("result_code", resultCode); + returnIntent.putExtra("request_id", requestId); + if (resultPath != null) { + returnIntent.putExtra("result_path", resultPath); + } + returnIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); + startActivity(returnIntent); + finish(); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -125,39 +138,30 @@ public class ImageResultProxyActivity extends AppCompatActivity { result -> { Log.i(TAG, "Packing return intent, requestId = " + requestId); - Intent returnIntent = new Intent(this, PpssppActivity.class); + String localPath; if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { - String localPath = copyAndDownscaleToCache(result.getData().getData()); - Log.i(TAG, "Putting extra: " + localPath); - // Pass the result back to the SingleInstance activity. - returnIntent.putExtra("result_path", localPath); + localPath = copyAndDownscaleToCache(result.getData().getData()); + } else { + localPath = null; } - returnIntent.putExtra("result_code", result.getResultCode()); - returnIntent.putExtra("request_id", requestId); - - // This flag is key: it finds the existing instance of your main activity - returnIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - startActivity(returnIntent); - finish(); + returnWithResult(result.getResultCode(), requestId, localPath); } ); - // Only launch the picker if we are starting fresh. If we're being recreated, - // the ActivityResultRegistry will handle delivering the pending result to the launcher. + // Only launch the picker if we are starting fresh. If we're being recreated (e.g. rotation), + // the ActivityResultRegistry will handle delivering the pending result to the launcher + // automatically, and we don't want to launch the picker a second time. if (savedInstanceState == null) { if (pickerIntent != null) { try { launcher.launch(pickerIntent); + } catch (ActivityNotFoundException e) { + NativeApp.reportException(e, "ImageResultProxy: failed to launch picker intent, activity not found: " + pickerIntent.getAction()); + returnWithResult(NativeApp.RESULT_ERROR_ACTIVITY_NOT_FOUND, requestId, null); } catch (Exception e) { - NativeApp.reportException(e, "ImageResultProxy: failed to launch picker intent " + pickerIntent.getAction()); - // Return to main activity with an error result. - Intent returnIntent = new Intent(this, PpssppActivity.class); - returnIntent.putExtra("result_code", NativeApp.RESULT_ERROR_ACTIVITY_NOT_FOUND); - returnIntent.putExtra("request_id", requestId); - returnIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - startActivity(returnIntent); - finish(); + NativeApp.reportException(e, "ImageResultProxy: failed to launch picker intent, other error: " + pickerIntent.getAction()); + returnWithResult(NativeApp.RESULT_ERROR_OTHER_ACTIVITY_ERROR, requestId, null); } } else { Log.e(TAG, "No picker intent provided"); diff --git a/android/src/org/ppsspp/ppsspp/NativeApp.java b/android/src/org/ppsspp/ppsspp/NativeApp.java index 708b6b4670..d3fe003379 100644 --- a/android/src/org/ppsspp/ppsspp/NativeApp.java +++ b/android/src/org/ppsspp/ppsspp/NativeApp.java @@ -27,6 +27,7 @@ public class NativeApp { public static final int RESULT_OK = -1; public static final int RESULT_CANCELED = 0; public static final int RESULT_ERROR_ACTIVITY_NOT_FOUND = 1; + public static final int RESULT_ERROR_OTHER_ACTIVITY_ERROR = 2; public static native void init(String model, int deviceType, String languageRegion, String apkPath, String dataDir, String externalStorageDir, String extFilesDir, String nativeLibDir, String additionalStorageDirs, String cacheDir, String shortcutParam, String installerName, int androidVersion, String board); public static native void audioInit();