diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 9bba60d..526b4c2 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,7 +4,7 @@ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 1ac4798..85193ab 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,36 @@ \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 7786a0c..08c9a28 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,8 +12,8 @@ android { applicationId "com.zane.smapiinstaller" minSdkVersion 19 targetSdkVersion 30 - versionCode 71 - versionName "3.7.6.9" + versionCode 72 + versionName "3.7.6.10" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cff4025..7688709 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,7 +9,7 @@ - + @@ -30,6 +30,7 @@ android:configChanges="orientation|keyboard|screenSize" android:networkSecurityConfig="@xml/network_security_config" android:theme="@style/AppTheme" + android:preserveLegacyExternalStorage="true" android:requestLegacyExternalStorage="true" tools:ignore="UnusedAttribute" android:largeHeap="true"> diff --git a/app/src/main/assets/apk/StardewModdingAPI.dll b/app/src/main/assets/apk/StardewModdingAPI.dll index 85cf2bd..5d6fe9b 100644 Binary files a/app/src/main/assets/apk/StardewModdingAPI.dll and b/app/src/main/assets/apk/StardewModdingAPI.dll differ diff --git a/app/src/main/java/com/zane/smapiinstaller/MainActivity.java b/app/src/main/java/com/zane/smapiinstaller/MainActivity.java index 55958ca..a27f1ba 100644 --- a/app/src/main/java/com/zane/smapiinstaller/MainActivity.java +++ b/app/src/main/java/com/zane/smapiinstaller/MainActivity.java @@ -1,7 +1,6 @@ package com.zane.smapiinstaller; import android.Manifest; -import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -95,13 +94,7 @@ public class MainActivity extends AppCompatActivity { requestPermissions(); } }); - try { - Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); - intent.setData(Uri.parse("package:" + this.getPackageName())); - startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION); - } catch (ActivityNotFoundException ignored){ - startActivityForResult(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION), ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION); - } + CommonLogic.openPermissionSetting(this); } else { this.finish(); } diff --git a/app/src/main/java/com/zane/smapiinstaller/logic/ActivityResultHandler.java b/app/src/main/java/com/zane/smapiinstaller/logic/ActivityResultHandler.java index d853fa0..773ff44 100644 --- a/app/src/main/java/com/zane/smapiinstaller/logic/ActivityResultHandler.java +++ b/app/src/main/java/com/zane/smapiinstaller/logic/ActivityResultHandler.java @@ -12,6 +12,7 @@ import java.util.function.BiConsumer; public class ActivityResultHandler { public static final int REQUEST_CODE_APP_INSTALL = 1001; public static final int REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION = 1002; + public static final int REQUEST_CODE_OBB_FILES_ACCESS_PERMISSION = 1003; public static ConcurrentHashMap> listenerMap = new ConcurrentHashMap<>(); diff --git a/app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java b/app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java index 341b896..8e84e7b 100644 --- a/app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java +++ b/app/src/main/java/com/zane/smapiinstaller/logic/CommonLogic.java @@ -11,6 +11,8 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; +import android.provider.DocumentsContract; +import android.provider.Settings; import android.util.Log; import android.view.View; import android.view.animation.Animation; @@ -55,6 +57,8 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; +import androidx.annotation.RequiresApi; +import androidx.documentfile.provider.DocumentFile; import pxb.android.axml.AxmlReader; import pxb.android.axml.AxmlVisitor; import pxb.android.axml.AxmlWriter; @@ -210,7 +214,9 @@ public class CommonLogic { * @return 操作是否成功 */ public static boolean unpackSmapiFiles(Context context, String apkPath, boolean checkMode, String packageName, long versionCode) { - checkMusic(packageName, checkMode); + if(!checkMusic(context)){ + return false; + } List apkFilesManifests = CommonLogic.findAllApkFileManifest(context); filterManifest(apkFilesManifests, packageName, versionCode); List manifestEntries = null; @@ -268,11 +274,26 @@ public class CommonLogic { return true; } - private static void checkMusic(String packageName, boolean checkMode) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && StringUtils.equals(packageName, Constants.ORIGIN_PACKAGE_NAME_GOOGLE)) { - File pathFrom = new File(FileUtils.getStadewValleyBasePath(), "Android/obb/" + packageName); - File pathTo = new File(FileUtils.getStadewValleyBasePath(), "Android/obb/" + Constants.TARGET_PACKAGE_NAME); + private static boolean checkMusic(Context context) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + File pathFrom = new File(FileUtils.getStadewValleyBasePath(), "Android/obb/" + Constants.ORIGIN_PACKAGE_NAME_GOOGLE); + File pathTo = new File(FileUtils.getStadewValleyBasePath(), "StardewValley"); if (pathFrom.exists() && pathFrom.isDirectory()) { + if (!pathFrom.canRead()) { + ActivityResultHandler.registerListener(ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION, (resultCode, data) -> { + if (resultCode == Activity.RESULT_OK) { + if (data == null) { + return; + } + Uri uri = data.getData(); + if (uri == null) { + return; + } + context.getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + } + }); + openObbRootPermission((Activity) context, ActivityResultHandler.REQUEST_CODE_OBB_FILES_ACCESS_PERMISSION); + } if (!pathTo.exists()) { pathTo.mkdirs(); } @@ -291,6 +312,7 @@ public class CommonLogic { } } } + return true; } private static void unpackFromApk(String apkPath, boolean checkMode, ManifestEntry entry, File targetFile) { @@ -445,6 +467,41 @@ public class CommonLogic { }); } + @RequiresApi(api = Build.VERSION_CODES.R) + public static void openPermissionSetting(Activity activity) { + try { + Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); + intent.addCategory("android.intent.category.DEFAULT"); + intent.setData(Uri.parse("package:" + activity.getPackageName())); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + activity.startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION); + } catch (ActivityNotFoundException ignored){ + Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + activity.getPackageName())); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + activity.startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION); + } + catch (ActivityNotFoundException ignored2) { + intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + activity.startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_ALL_FILES_ACCESS_PERMISSION); + } + } + } + + public static void openObbRootPermission(Activity context, int REQUEST_CODE_FOR_DIR) { + Uri uri1 = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fobb"); + DocumentFile documentFile = DocumentFile.fromTreeUri(context, uri1); + Intent intent1 = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); + intent1.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION + | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION + | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); + intent1.putExtra(DocumentsContract.EXTRA_INITIAL_URI, documentFile.getUri()); + context.startActivityForResult(intent1, REQUEST_CODE_FOR_DIR); + } + public static void showPrivacyPolicy(View view, BiConsumer callback) { Context context = view.getContext(); String policy = FileUtils.getLocaledAssetText(context, "privacy_policy.txt"); diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index b59e456..3159f09 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -87,6 +87,6 @@ Перепишіть у Parallel Необхідно увімкнути дозвіл встановлення з невідомих джерел для встановлення фреймворку мода, відкрити налаштування? Перепишіть загублене - Ім'я запатченого застосунка + Ім\'я запатченого застосунка Потрібен дозвіл на доступ до всіх файлів на Android Q чи більш пізньої версії, щоб встановити модифікацію, продовжити?