From 3b9ded827059f7bb477fc507d8f4cc73e591ee78 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 21 Aug 2025 21:49:45 +0800 Subject: [PATCH] request access if needed to use backup and restore --- forge-gui-android/src/forge/app/Main.java | 39 ++++++------ forge-gui-ios/src/forge/ios/Main.java | 10 ++++ forge-gui-mobile-dev/src/forge/app/Main.java | 10 ++++ .../src/forge/adventure/scene/StartScene.java | 4 ++ .../src/forge/screens/settings/FilesPage.java | 60 ++++++++++--------- .../java/forge/interfaces/IDeviceAdapter.java | 2 + 6 files changed, 78 insertions(+), 47 deletions(-) diff --git a/forge-gui-android/src/forge/app/Main.java b/forge-gui-android/src/forge/app/Main.java index ad95dac3349..6ebbe6793c8 100644 --- a/forge-gui-android/src/forge/app/Main.java +++ b/forge-gui-android/src/forge/app/Main.java @@ -253,9 +253,7 @@ public class Main extends AndroidApplication { text.setGravity(Gravity.LEFT); text.setTypeface(Typeface.SERIF); String SP = "Storage Permission"; - if (needExternalFileAccess()) { - SP = "All File Access Permission"; - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { SP = "Photos and Videos, Music and Audio Permissions"; } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { SP = "Files & Media Permissions"; @@ -267,11 +265,8 @@ public class Main extends AndroidApplication { " 2) Tap Permissions\n" + " 3) Enable the " + SP + ".\n\n" + "(You can tap anywhere to exit and restart the app)\n\n"; - String allFileAccessSteps = " 1) Tap \"App Settings\" Button.\n" + - " 2) Enable the " + SP + ".\n\n" + - "(You can tap anywhere to exit and restart the app)\n\n"; if (ex) { - title = needExternalFileAccess() ? "All File Access Permission" : manageApp ? "Forge AutoUpdater Permission...\n" : "Forge didn't initialize!\n"; + title = manageApp ? "Forge AutoUpdater Permission...\n" : "Forge didn't initialize!\n"; steps = manageApp ? " 1) Tap \"App Settings\" Button.\n" + " 2) Enable \"Allow apps from this source\"\n" + "(You can tap anywhere to exit and restart the app)\n\n" : msg + "\n\n"; @@ -280,7 +275,7 @@ public class Main extends AndroidApplication { SpannableString ss1 = new SpannableString(title); ss1.setSpan(new StyleSpan(Typeface.BOLD), 0, ss1.length(), 0); text.append(ss1); - text.append(needExternalFileAccess() ? allFileAccessSteps : steps); + text.append(steps); row.addView(text); row.setGravity(Gravity.CENTER); @@ -309,16 +304,7 @@ public class Main extends AndroidApplication { button.setTextColor(Color.RED); button.setOnClickListener(v -> { - if (needExternalFileAccess()) { - /* - This is needed for Android 11 and upwards to have access on external storage (direct file path) - ie adventure mode -> data -> restore. Though its not fast like the app-specific storage... - */ - Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); - Uri uri = Uri.fromParts("package", getPackageName(), null); - intent.setData(uri).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - } else if (manageApp) { + if (manageApp) { Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES) .setData(Uri.parse(String.format("package:%s", getPackageName()))) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -354,7 +340,7 @@ public class Main extends AndroidApplication { public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); handler.postDelayed(() -> { - if (needExternalFileAccess() || !permissiongranted || exception) { + if (!permissiongranted || exception) { displayMessage(forgeLogo, adapter, exception, msg, false); } else if (title.isEmpty() && steps.isEmpty()) { if (isLandscape) { @@ -678,6 +664,21 @@ public class Main extends AndroidApplication { return new AndroidUpnpServiceConfiguration(); } + @Override + public boolean needFileAccess() { + return needExternalFileAccess(); + } + + @Override + public void requestFileAcces() { + /* This is needed for Android 11 and upwards to have access on external storage (direct file path) + ie adventure mode -> data -> restore. Though it's not fast like the app-specific storage...*/ + Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); + Uri uri = Uri.fromParts("package", getPackageName(), null); + intent.setData(uri).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + @Override public boolean isConnectedToInternet() { //if it can't determine Internet connection within two seconds, assume not connected diff --git a/forge-gui-ios/src/forge/ios/Main.java b/forge-gui-ios/src/forge/ios/Main.java index 4accc728cd7..7473ee70d33 100644 --- a/forge-gui-ios/src/forge/ios/Main.java +++ b/forge-gui-ios/src/forge/ios/Main.java @@ -145,5 +145,15 @@ public class Main extends IOSApplication.Delegate { // not used return null; } + + @Override + public boolean needFileAccess() { + return false; + } + + @Override + public void requestFileAcces() { + + } } } \ No newline at end of file diff --git a/forge-gui-mobile-dev/src/forge/app/Main.java b/forge-gui-mobile-dev/src/forge/app/Main.java index bb2074cb25f..3028c0d78d5 100644 --- a/forge-gui-mobile-dev/src/forge/app/Main.java +++ b/forge-gui-mobile-dev/src/forge/app/Main.java @@ -153,5 +153,15 @@ public class Main { // shouldn't be reached return null; } + + @Override + public boolean needFileAccess() { + return false; + } + + @Override + public void requestFileAcces() { + + } } } diff --git a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java index c6e918cf1bf..f461bdc2e8b 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java @@ -126,6 +126,10 @@ public class StartScene extends UIScene { } public boolean backup() { + if (Forge.getDeviceAdapter().needFileAccess()) { + Forge.getDeviceAdapter().requestFileAcces(); + return true; + } if (backupDialog == null) { backupDialog = createGenericDialog(Forge.getLocalizer().getMessage("lblData"), null, Forge.getLocalizer().getMessage("lblBackup"), diff --git a/forge-gui-mobile/src/forge/screens/settings/FilesPage.java b/forge-gui-mobile/src/forge/screens/settings/FilesPage.java index f01d988cb83..bce5a794ba4 100644 --- a/forge-gui-mobile/src/forge/screens/settings/FilesPage.java +++ b/forge-gui-mobile/src/forge/screens/settings/FilesPage.java @@ -57,37 +57,41 @@ public class FilesPage extends TabPage { lstItems.addItem(new Extra(Forge.getLocalizer().getMessage("lblBackupRestore"), Forge.getLocalizer().getMessage("lblBackupRestoreDescription")) { @Override public void select() { + if (Forge.getDeviceAdapter().needFileAccess()) { + Forge.getDeviceAdapter().requestFileAcces(); + return; + } FOptionPane.showOptionDialog(Forge.getLocalizer().getMessage("lblPlsSelectActions"), "", FOptionPane.QUESTION_ICON, ImmutableList.of(Forge.getLocalizer().getMessage("lblBackup"), Forge.getLocalizer().getMessage("lblRestore"), Forge.getLocalizer().getMessage("lblCancel")), 2, new Callback() { @Override public void run(Integer result) { - switch (result) { - case 0: - FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblBackupMsg"), true, () -> { - File source = new FileHandle(ForgeProfileProperties.getUserDir()).file(); - File target = new FileHandle(Forge.getDeviceAdapter().getDownloadsDir()).file(); - try { - ZipUtil.zip(source, target, ZipUtil.backupClsFile); - FOptionPane.showMessageDialog(Forge.getLocalizer().getMessage("lblSuccess") + "\n" + target.getAbsolutePath() + File.separator + ZipUtil.backupClsFile, Forge.getLocalizer().getMessage("lblBackup"), FOptionPane.INFORMATION_ICON); - } catch (IOException e) { - FOptionPane.showMessageDialog(e.toString(), Forge.getLocalizer().getMessage("lblError"), FOptionPane.ERROR_ICON); - } - })); - break; - case 1: - FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblRestoreMsg"), true, () -> { - File source = new FileHandle(Forge.getDeviceAdapter().getDownloadsDir() + ZipUtil.backupClsFile).file(); - File target = new FileHandle(ForgeProfileProperties.getUserDir()).file().getParentFile(); - try { - String msg = ZipUtil.unzip(source, target); - FOptionPane.showMessageDialog(Forge.getLocalizer().getMessage("lblSuccess") + "\n" + msg, Forge.getLocalizer().getMessage("lblRestore"), FOptionPane.INFORMATION_ICON); - } catch (IOException e) { - FOptionPane.showMessageDialog(e.toString(), Forge.getLocalizer().getMessage("lblError"), FOptionPane.ERROR_ICON); - } - })); - break; - default: - break; - } + switch (result) { + case 0: + FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblBackupMsg"), true, () -> { + File source = new FileHandle(ForgeProfileProperties.getUserDir()).file(); + File target = new FileHandle(Forge.getDeviceAdapter().getDownloadsDir()).file(); + try { + ZipUtil.zip(source, target, ZipUtil.backupClsFile); + FOptionPane.showMessageDialog(Forge.getLocalizer().getMessage("lblSuccess") + "\n" + target.getAbsolutePath() + File.separator + ZipUtil.backupClsFile, Forge.getLocalizer().getMessage("lblBackup"), FOptionPane.INFORMATION_ICON); + } catch (IOException e) { + FOptionPane.showMessageDialog(e.toString(), Forge.getLocalizer().getMessage("lblError"), FOptionPane.ERROR_ICON); + } + })); + break; + case 1: + FThreads.invokeInEdtLater(() -> LoadingOverlay.show(Forge.getLocalizer().getMessage("lblRestoreMsg"), true, () -> { + File source = new FileHandle(Forge.getDeviceAdapter().getDownloadsDir() + ZipUtil.backupClsFile).file(); + File target = new FileHandle(ForgeProfileProperties.getUserDir()).file().getParentFile(); + try { + String msg = ZipUtil.unzip(source, target); + FOptionPane.showMessageDialog(Forge.getLocalizer().getMessage("lblSuccess") + "\n" + msg, Forge.getLocalizer().getMessage("lblRestore"), FOptionPane.INFORMATION_ICON); + } catch (IOException e) { + FOptionPane.showMessageDialog(e.toString(), Forge.getLocalizer().getMessage("lblError"), FOptionPane.ERROR_ICON); + } + })); + break; + default: + break; + } } }); } diff --git a/forge-gui/src/main/java/forge/interfaces/IDeviceAdapter.java b/forge-gui/src/main/java/forge/interfaces/IDeviceAdapter.java index 6f13a16b74e..1e8f9f212cd 100644 --- a/forge-gui/src/main/java/forge/interfaces/IDeviceAdapter.java +++ b/forge-gui/src/main/java/forge/interfaces/IDeviceAdapter.java @@ -27,4 +27,6 @@ public interface IDeviceAdapter { Pair getRealScreenSize(boolean real); ArrayList getGamepads(); UpnpServiceConfiguration getUpnpPlatformService(); + boolean needFileAccess(); + void requestFileAcces(); }