From d5a1ad0a731ce858b9d05a37e971355ed18c3a06 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Wed, 14 Jun 2017 20:19:52 +0000 Subject: [PATCH] android: delay loading of RetroActivity until after permissions are granted --- frontend/drivers/platform_linux.c | 7 - frontend/drivers/platform_linux.h | 1 - .../browser/mainmenu/MainMenuActivity.java | 169 +++++++++++++++--- .../retroactivity/RetroActivityCommon.java | 112 ------------ 4 files changed, 147 insertions(+), 142 deletions(-) diff --git a/frontend/drivers/platform_linux.c b/frontend/drivers/platform_linux.c index bd15721c25..5cbeecfe7b 100644 --- a/frontend/drivers/platform_linux.c +++ b/frontend/drivers/platform_linux.c @@ -1500,11 +1500,6 @@ static void frontend_linux_get_env(int *argc, __android_log_print(ANDROID_LOG_INFO, "RetroArch", "[ENV]: app dir: [%s]\n", app_dir); - /* Check for runtime permissions on Android 6.0+ */ - if (env && android_app->checkRuntimePermissions) - CALL_VOID_METHOD(env, android_app->activity->clazz, - android_app->checkRuntimePermissions); - /* set paths depending on the ability to write * to internal_storage_path */ @@ -1953,8 +1948,6 @@ static void frontend_linux_init(void *data) "onRetroArchExit", "()V"); GET_METHOD_ID(env, android_app->isAndroidTV, class, "isAndroidTV", "()Z"); - GET_METHOD_ID(env, android_app->checkRuntimePermissions, class, - "checkRuntimePermissions", "()V"); CALL_OBJ_METHOD(env, obj, android_app->activity->clazz, android_app->getIntent); diff --git a/frontend/drivers/platform_linux.h b/frontend/drivers/platform_linux.h index 762887b24c..7fe9dc83f7 100644 --- a/frontend/drivers/platform_linux.h +++ b/frontend/drivers/platform_linux.h @@ -161,7 +161,6 @@ struct android_app jmethodID getPendingIntentDownloadsLocation; jmethodID getPendingIntentScreenshotsLocation; jmethodID isAndroidTV; - jmethodID checkRuntimePermissions; }; diff --git a/pkg/android/phoenix/src/com/retroarch/browser/mainmenu/MainMenuActivity.java b/pkg/android/phoenix/src/com/retroarch/browser/mainmenu/MainMenuActivity.java index 2e4a47c1ea..88d25d6ee8 100644 --- a/pkg/android/phoenix/src/com/retroarch/browser/mainmenu/MainMenuActivity.java +++ b/pkg/android/phoenix/src/com/retroarch/browser/mainmenu/MainMenuActivity.java @@ -15,12 +15,158 @@ import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import android.provider.Settings; +import java.util.List; +import java.util.ArrayList; +import android.content.pm.PackageManager; +import android.Manifest; +import android.content.DialogInterface; +import android.app.AlertDialog; +import android.util.Log; + /** * {@link PreferenceActivity} subclass that provides all of the * functionality of the main menu screen. */ public final class MainMenuActivity extends PreferenceActivity { + final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124; + boolean checkPermissions = false; + + public void showMessageOKCancel(String message, DialogInterface.OnClickListener onClickListener) + { + new AlertDialog.Builder(this).setMessage(message) + .setPositiveButton("OK", onClickListener).setCancelable(false) + .setNegativeButton("Cancel", null).create().show(); + } + + private boolean addPermission(List permissionsList, String permission) + { + if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) + { + permissionsList.add(permission); + + // Check for Rationale Option + if (!shouldShowRequestPermissionRationale(permission)) + return false; + } + + return true; + } + + public void checkRuntimePermissions() + { + if (android.os.Build.VERSION.SDK_INT >= 23) + { + // Android 6.0+ needs runtime permission checks + List permissionsNeeded = new ArrayList(); + final List permissionsList = new ArrayList(); + + if (!addPermission(permissionsList, Manifest.permission.READ_EXTERNAL_STORAGE)) + permissionsNeeded.add("Read External Storage"); + if (!addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE)) + permissionsNeeded.add("Write External Storage"); + + if (permissionsList.size() > 0) + { + checkPermissions = true; + + if (permissionsNeeded.size() > 0) + { + // Need Rationale + Log.i("MainMenuActivity", "Need to request external storage permissions."); + + String message = "You need to grant access to " + permissionsNeeded.get(0); + + for (int i = 1; i < permissionsNeeded.size(); i++) + message = message + ", " + permissionsNeeded.get(i); + + showMessageOKCancel(message, + new DialogInterface.OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int which) + { + if (which == AlertDialog.BUTTON_POSITIVE) + { + requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), + REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); + + Log.i("MainMenuActivity", "User accepted request for external storage permissions."); + } + } + }); + } + else + { + requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), + REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); + + Log.i("MainMenuActivity", "Requested external storage permissions."); + } + } + } + + if (!checkPermissions) + { + finalStartup(); + } + } + + public void finalStartup() + { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + Intent retro; + + if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) + { + retro = new Intent(this, RetroActivityFuture.class); + } + else + { + retro = new Intent(this, RetroActivityPast.class); + } + + retro.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + + startRetroActivity( + retro, + null, + prefs.getString("libretro_path", getApplicationInfo().dataDir + "/cores/"), + UserPreferences.getDefaultConfigPath(this), + Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD), + getApplicationInfo().dataDir, + getApplicationInfo().sourceDir); + startActivity(retro); + finish(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) + { + switch (requestCode) + { + case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: + for (int i = 0; i < permissions.length; i++) + { + if(grantResults[i] == PackageManager.PERMISSION_GRANTED) + { + Log.i("MainMenuActivity", "Permission: " + permissions[i] + " was granted."); + } + else + { + Log.i("MainMenuActivity", "Permission: " + permissions[i] + " was not granted."); + } + } + + break; + default: + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + break; + } + + finalStartup(); + } + public static void startRetroActivity(Intent retro, String contentPath, String corePath, String configFilePath, String imePath, String dataDirPath, String dataSourcePath) { @@ -48,28 +194,7 @@ public final class MainMenuActivity extends PreferenceActivity setVolumeControlStream(AudioManager.STREAM_MUSIC); UserPreferences.updateConfigFile(this); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - Intent retro; - - if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) - { - retro = new Intent(this, RetroActivityFuture.class); - } - else - { - retro = new Intent(this, RetroActivityPast.class); - } - retro.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startRetroActivity( - retro, - null, - prefs.getString("libretro_path", getApplicationInfo().dataDir + "/cores/"), - UserPreferences.getDefaultConfigPath(this), - Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD), - getApplicationInfo().dataDir, - getApplicationInfo().sourceDir); - startActivity(retro); - finish(); + checkRuntimePermissions(); } } diff --git a/pkg/android/phoenix/src/com/retroarch/browser/retroactivity/RetroActivityCommon.java b/pkg/android/phoenix/src/com/retroarch/browser/retroactivity/RetroActivityCommon.java index c907f9164c..06e1a8c7ba 100644 --- a/pkg/android/phoenix/src/com/retroarch/browser/retroactivity/RetroActivityCommon.java +++ b/pkg/android/phoenix/src/com/retroarch/browser/retroactivity/RetroActivityCommon.java @@ -1,23 +1,15 @@ package com.retroarch.browser.retroactivity; -import java.util.List; -import java.util.ArrayList; import com.retroarch.browser.preferences.util.UserPreferences; import android.content.res.Configuration; import android.app.UiModeManager; import android.util.Log; -import android.content.pm.PackageManager; -import android.Manifest; -import android.content.DialogInterface; -import android.app.AlertDialog; /** * Class which provides common methods for RetroActivity related classes. */ public class RetroActivityCommon extends RetroActivityLocation { - final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124; - // Exiting cleanly from NDK seems to be nearly impossible. // Have to use exit(0) to avoid weird things happening, even with runOnUiThread() approaches. // Use a separate JNI function to explicitly trigger the readback. @@ -26,110 +18,6 @@ public class RetroActivityCommon extends RetroActivityLocation finish(); } - public void showMessageOKCancel(String message, DialogInterface.OnClickListener onClickListener) - { - new AlertDialog.Builder(this).setMessage(message) - .setPositiveButton("OK", onClickListener).setCancelable(false) - .setNegativeButton("Cancel", null).create().show(); - } - - private boolean addPermission(List permissionsList, String permission) - { - if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) - { - permissionsList.add(permission); - - // Check for Rationale Option - if (!shouldShowRequestPermissionRationale(permission)) - return false; - } - - return true; - } - - public void checkRuntimePermissions() - { - runOnUiThread(new Runnable() { - public void run() { - checkRuntimePermissionsRunnable(); - } - }); - } - - public void checkRuntimePermissionsRunnable() - { - if (android.os.Build.VERSION.SDK_INT >= 23) - { - // Android 6.0+ needs runtime permission checks - List permissionsNeeded = new ArrayList(); - final List permissionsList = new ArrayList(); - - if (!addPermission(permissionsList, Manifest.permission.READ_EXTERNAL_STORAGE)) - permissionsNeeded.add("Read External Storage"); - if (!addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE)) - permissionsNeeded.add("Write External Storage"); - - if (permissionsList.size() > 0) - { - if (permissionsNeeded.size() > 0) - { - // Need Rationale - Log.i("RetroActivity", "Need to request external storage permissions."); - - String message = "You need to grant access to " + permissionsNeeded.get(0); - - for (int i = 1; i < permissionsNeeded.size(); i++) - message = message + ", " + permissionsNeeded.get(i); - - showMessageOKCancel(message, - new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int which) - { - requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), - REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); - - Log.i("RetroActivity", "User accepted request for external storage permissions."); - } - }); - } - else - { - requestPermissions(permissionsList.toArray(new String[permissionsList.size()]), - REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS); - - Log.i("RetroActivity", "Requested external storage permissions."); - } - } - } - } - - @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) - { - switch (requestCode) - { - case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: - for (int i = 0; i < permissions.length; i++) - { - if(grantResults[i] == PackageManager.PERMISSION_GRANTED) - { - Log.i("RetroActivity", "Permission: " + permissions[i] + " was granted."); - } - else - { - Log.i("RetroActivity", "Permission: " + permissions[i] + " was not granted."); - } - } - - break; - default: - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - break; - } - } - public boolean isAndroidTV() { Configuration config = getResources().getConfiguration();