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 чи більш пізньої версії, щоб встановити модифікацію, продовжити?