1.Bug fix

2.Add permission check dialog
This commit is contained in:
ZaneYork 2020-06-22 18:46:28 +08:00
parent 2a79a72ff9
commit 41f0b8765f
13 changed files with 94 additions and 31 deletions

View File

@ -12,8 +12,8 @@ android {
applicationId "com.zane.smapiinstaller" applicationId "com.zane.smapiinstaller"
minSdkVersion 19 minSdkVersion 19
targetSdkVersion 28 targetSdkVersion 28
versionCode 46 versionCode 47
versionName "1.5.5" versionName "1.5.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true

View File

@ -1,5 +1,5 @@
{ {
"version": 21, "version": 23,
"contents": [ "contents": [
{ {
"type": "COMPAT", "type": "COMPAT",
@ -14,16 +14,16 @@
"name": "SMAPI for Galaxy Store", "name": "SMAPI for Galaxy Store",
"assetPath": "compat/samsung_138/", "assetPath": "compat/samsung_138/",
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.6.1", "description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.6.1",
"url": "http://zaneyork.cn/download/compat/smapi_samsung_138_16.zip", "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_17.zip",
"hash": "20cf2ce515dcf05596d523387b244c9e14c235387db61545e7067835e5856626" "hash": "ac6cff4a1decb19fc01da7314e79483f2a77d34523665370d62f8bf69dcf09dc"
}, },
{ {
"type": "COMPAT", "type": "COMPAT",
"name": "SMAPI for Amazon Store", "name": "SMAPI for Amazon Store",
"assetPath": "compat/amazon_138/", "assetPath": "compat/amazon_138/",
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.6.1", "description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.6.1",
"url": "http://zaneyork.cn/download/compat/smapi_amazon_138_6.zip", "url": "http://zaneyork.cn/download/compat/smapi_amazon_138_7.zip",
"hash": "f487f8f14fcdd0ee31ca4e3b731e6e9114bc4b43a50c930f651a939e927eeb5d" "hash": "8a63e326ab122df5157a6c70c6cac8b8669ec81701f687746b80b7a860578dbb"
}, },
{ {
"type": "LOCALE", "type": "LOCALE",

View File

@ -1,5 +1,5 @@
{ {
"version": 21, "version": 23,
"contents": [ "contents": [
{ {
"type": "COMPAT", "type": "COMPAT",
@ -14,16 +14,16 @@
"name": "SMAPI for Galaxy Store", "name": "SMAPI for Galaxy Store",
"assetPath": "compat/samsung_138/", "assetPath": "compat/samsung_138/",
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.6.1", "description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.6.1",
"url": "http://zaneyork.cn/download/compat/smapi_samsung_138_16.zip", "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_17.zip",
"hash": "20cf2ce515dcf05596d523387b244c9e14c235387db61545e7067835e5856626" "hash": "ac6cff4a1decb19fc01da7314e79483f2a77d34523665370d62f8bf69dcf09dc"
}, },
{ {
"type": "COMPAT", "type": "COMPAT",
"name": "SMAPI for Amazon Store", "name": "SMAPI for Amazon Store",
"assetPath": "compat/amazon_138/", "assetPath": "compat/amazon_138/",
"description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.6.1", "description": "SMAPI compat package for game 1.4.4.138 - latest, SMAPI 3.6.1",
"url": "http://zaneyork.cn/download/compat/smapi_amazon_138_6.zip", "url": "http://zaneyork.cn/download/compat/smapi_amazon_138_7.zip",
"hash": "f487f8f14fcdd0ee31ca4e3b731e6e9114bc4b43a50c930f651a939e927eeb5d" "hash": "8a63e326ab122df5157a6c70c6cac8b8669ec81701f687746b80b7a860578dbb"
}, },
{ {
"type": "LOCALE", "type": "LOCALE",

View File

@ -1,5 +1,5 @@
{ {
"version": 21, "version": 23,
"contents": [ "contents": [
{ {
"type": "COMPAT", "type": "COMPAT",
@ -14,16 +14,16 @@
"name": "SMAPI untuk Galaxy Store", "name": "SMAPI untuk Galaxy Store",
"assetPath": "compat/samsung_138/", "assetPath": "compat/samsung_138/",
"description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.138 - terbaru, SMAPI 3.6.1", "description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.138 - terbaru, SMAPI 3.6.1",
"url": "http://zaneyork.cn/download/compat/smapi_samsung_138_16.zip", "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_17.zip",
"hash": "20cf2ce515dcf05596d523387b244c9e14c235387db61545e7067835e5856626" "hash": "ac6cff4a1decb19fc01da7314e79483f2a77d34523665370d62f8bf69dcf09dc"
}, },
{ {
"type": "COMPAT", "type": "COMPAT",
"name": "SMAPI untuk Amazon Store", "name": "SMAPI untuk Amazon Store",
"assetPath": "compat/amazon_138/", "assetPath": "compat/amazon_138/",
"description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.138 - terbaru, SMAPI 3.6.1", "description": "Paket kompatibilitas SMAPI untuk versi 1.4.4.138 - terbaru, SMAPI 3.6.1",
"url": "http://zaneyork.cn/download/compat/smapi_amazon_138_6.zip", "url": "http://zaneyork.cn/download/compat/smapi_amazon_138_7.zip",
"hash": "f487f8f14fcdd0ee31ca4e3b731e6e9114bc4b43a50c930f651a939e927eeb5d" "hash": "8a63e326ab122df5157a6c70c6cac8b8669ec81701f687746b80b7a860578dbb"
}, },
{ {
"type": "LOCAL", "type": "LOCAL",

View File

@ -1,5 +1,5 @@
{ {
"version": 21, "version": 23,
"contents": [ "contents": [
{ {
"type": "COMPAT", "type": "COMPAT",
@ -14,16 +14,16 @@
"name": "SMAPI三星商店兼容包", "name": "SMAPI三星商店兼容包",
"assetPath": "compat/samsung_138/", "assetPath": "compat/samsung_138/",
"description": "SMAPI三星商店兼容包 适用版本1.4.4.138至今, SMAPI 3.6.1", "description": "SMAPI三星商店兼容包 适用版本1.4.4.138至今, SMAPI 3.6.1",
"url": "http://zaneyork.cn/download/compat/smapi_samsung_138_16.zip", "url": "http://zaneyork.cn/download/compat/smapi_samsung_138_17.zip",
"hash": "20cf2ce515dcf05596d523387b244c9e14c235387db61545e7067835e5856626" "hash": "ac6cff4a1decb19fc01da7314e79483f2a77d34523665370d62f8bf69dcf09dc"
}, },
{ {
"type": "COMPAT", "type": "COMPAT",
"name": "SMAPI亚马逊商店兼容包", "name": "SMAPI亚马逊商店兼容包",
"assetPath": "compat/amazon_138/", "assetPath": "compat/amazon_138/",
"description": "SMAPI亚马逊商店兼容包 适用版本1.4.4.138至今, SMAPI 3.6.1", "description": "SMAPI亚马逊商店兼容包 适用版本1.4.4.138至今, SMAPI 3.6.1",
"url": "http://zaneyork.cn/download/compat/smapi_amazon_138_6.zip", "url": "http://zaneyork.cn/download/compat/smapi_amazon_138_7.zip",
"hash": "f487f8f14fcdd0ee31ca4e3b731e6e9114bc4b43a50c930f651a939e927eeb5d" "hash": "8a63e326ab122df5157a6c70c6cac8b8669ec81701f687746b80b7a860578dbb"
}, },
{ {
"type": "LOCALE", "type": "LOCALE",

View File

@ -26,6 +26,7 @@ import com.zane.smapiinstaller.constant.DialogAction;
import com.zane.smapiinstaller.dto.AppUpdateCheckResultDto; import com.zane.smapiinstaller.dto.AppUpdateCheckResultDto;
import com.zane.smapiinstaller.entity.AppConfig; import com.zane.smapiinstaller.entity.AppConfig;
import com.zane.smapiinstaller.entity.FrameworkConfig; import com.zane.smapiinstaller.entity.FrameworkConfig;
import com.zane.smapiinstaller.logic.ActivityResultHandler;
import com.zane.smapiinstaller.logic.CommonLogic; import com.zane.smapiinstaller.logic.CommonLogic;
import com.zane.smapiinstaller.logic.ConfigManager; import com.zane.smapiinstaller.logic.ConfigManager;
import com.zane.smapiinstaller.logic.GameLauncher; import com.zane.smapiinstaller.logic.GameLauncher;
@ -42,6 +43,7 @@ import java.io.File;
import java.util.Locale; import java.util.Locale;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
@ -97,6 +99,12 @@ public class MainActivity extends AppCompatActivity {
} }
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
ActivityResultHandler.triggerListener(requestCode, resultCode, data);
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);

View File

@ -0,0 +1,24 @@
package com.zane.smapiinstaller.logic;
import android.content.Intent;
import java.util.concurrent.ConcurrentHashMap;
import java9.util.function.BiConsumer;
public class ActivityResultHandler {
public static int REQUEST_CODE_APP_INSTALL = 1001;
public static ConcurrentHashMap<Integer, BiConsumer<Integer, Intent>> listenerMap = new ConcurrentHashMap<>();
public static void registerListener(int requestCode, BiConsumer<Integer, Intent> listener) {
listenerMap.put(requestCode, listener);
}
public static void triggerListener(int requestCode, int resultCode, Intent data) {
BiConsumer<Integer, Intent> biConsumer = listenerMap.get(requestCode);
if(biConsumer != null) {
biConsumer.accept(resultCode, data);
}
}
}

View File

@ -8,6 +8,7 @@ import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.provider.Settings;
import android.util.Log; import android.util.Log;
import com.android.apksig.ApkSigner; import com.android.apksig.ApkSigner;
@ -19,11 +20,14 @@ import com.google.common.collect.Iterables;
import com.google.common.hash.Hashing; import com.google.common.hash.Hashing;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.zane.smapiinstaller.BuildConfig; import com.zane.smapiinstaller.BuildConfig;
import com.zane.smapiinstaller.MainActivity;
import com.zane.smapiinstaller.R; import com.zane.smapiinstaller.R;
import com.zane.smapiinstaller.constant.Constants; import com.zane.smapiinstaller.constant.Constants;
import com.zane.smapiinstaller.constant.DialogAction;
import com.zane.smapiinstaller.constant.ManifestPatchConstants; import com.zane.smapiinstaller.constant.ManifestPatchConstants;
import com.zane.smapiinstaller.entity.ApkFilesManifest; import com.zane.smapiinstaller.entity.ApkFilesManifest;
import com.zane.smapiinstaller.entity.ManifestEntry; import com.zane.smapiinstaller.entity.ManifestEntry;
import com.zane.smapiinstaller.utils.DialogUtils;
import com.zane.smapiinstaller.utils.FileUtils; import com.zane.smapiinstaller.utils.FileUtils;
import com.zane.smapiinstaller.utils.ZipUtils; import com.zane.smapiinstaller.utils.ZipUtils;
@ -126,13 +130,12 @@ public class ApkPatcher {
return distFile.getAbsolutePath(); return distFile.getAbsolutePath();
} else if (advancedStage == 1) { } else if (advancedStage == 1) {
File contentFolder = new File(externalFilesDir.getAbsolutePath() + "/StardewValley/Content"); File contentFolder = new File(externalFilesDir.getAbsolutePath() + "/StardewValley/Content");
if(contentFolder.exists()) { if (contentFolder.exists()) {
if(!contentFolder.isDirectory()) { if (!contentFolder.isDirectory()) {
errorMessage.set(context.getString(R.string.error_directory_exists_with_same_filename, contentFolder.getAbsolutePath())); errorMessage.set(context.getString(R.string.error_directory_exists_with_same_filename, contentFolder.getAbsolutePath()));
return null; return null;
} }
} } else {
else {
extract(0); extract(0);
} }
ZipUtils.removeEntries(sourceDir, "assets/Content", distFile.getAbsolutePath(), (progress) -> emitProgress((int) (progress * 0.05))); ZipUtils.removeEntries(sourceDir, "assets/Content", distFile.getAbsolutePath(), (progress) -> emitProgress((int) (progress * 0.05)));
@ -189,7 +192,7 @@ public class ApkPatcher {
List<ManifestEntry> manifestEntries = apkFilesManifest.getManifestEntries(); List<ManifestEntry> manifestEntries = apkFilesManifest.getManifestEntries();
errorMessage.set(null); errorMessage.set(null);
List<ZipUtils.ZipEntrySource> entries = StreamSupport.stream(manifestEntries).map(entry -> { List<ZipUtils.ZipEntrySource> entries = StreamSupport.stream(manifestEntries).map(entry -> {
if(entry.isAdvanced() && !advanced) { if (entry.isAdvanced() && !advanced) {
return null; return null;
} }
byte[] bytes; byte[] bytes;
@ -209,11 +212,9 @@ public class ApkPatcher {
errorMessage.set(StringUtils.stripToEmpty(errorMessage.get()) + "\n" + errorMsg); errorMessage.set(StringUtils.stripToEmpty(errorMessage.get()) + "\n" + errorMsg);
return null; return null;
} }
} } else if (StringUtils.equals(crc, entry.getPatchedCrc())) {
else if(StringUtils.equals(crc, entry.getPatchedCrc())){
bytes = originBytes; bytes = originBytes;
} } else {
else {
String errorMsg = context.getString(R.string.error_patch_crc_incorrect, entry.getTargetPath(), crc); String errorMsg = context.getString(R.string.error_patch_crc_incorrect, entry.getTargetPath(), crc);
errorMessage.set(StringUtils.stripToEmpty(errorMessage.get()) + "\n" + errorMsg); errorMessage.set(StringUtils.stripToEmpty(errorMessage.get()) + "\n" + errorMsg);
return null; return null;
@ -402,6 +403,20 @@ public class ApkPatcher {
* @param apkPath 安装包路径 * @param apkPath 安装包路径
*/ */
public void install(String apkPath) { public void install(String apkPath) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
boolean haveInstallPermission = context.getPackageManager().canRequestPackageInstalls();
if (!haveInstallPermission) {
DialogUtils.showConfirmDialog(MainActivity.instance, R.string.confirm, R.string.request_unknown_source_permission, ((dialog, dialogAction) -> {
if(dialogAction == DialogAction.POSITIVE) {
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
ActivityResultHandler.registerListener(ActivityResultHandler.REQUEST_CODE_APP_INSTALL, (resultCode, data) -> this.install(apkPath));
MainActivity.instance.startActivityForResult(intent, ActivityResultHandler.REQUEST_CODE_APP_INSTALL);
}
}));
return;
}
}
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(fromFile(new File(apkPath)), "application/vnd.android.package-archive"); intent.setDataAndType(fromFile(new File(apkPath)), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

View File

@ -104,6 +104,19 @@ public class DialogUtils {
materialDialog.show(); materialDialog.show();
}); });
} }
public static void showConfirmDialog(Activity context, int title, int message, BiConsumer<MaterialDialog, DialogAction> callback) {
CommonLogic.runOnUiThread(context, (activity) -> {
MaterialDialog materialDialog = new MaterialDialog(activity, MaterialDialog.getDEFAULT_BEHAVIOR()).title(title, null).message(message, null, null).positiveButton(R.string.confirm, null, dialog -> {
callback.accept(dialog, DialogAction.POSITIVE);
return null;
}).negativeButton(R.string.cancel, null, dialog -> {
callback.accept(dialog, DialogAction.NEGATIVE);
return null;
});
DialogUtils.setCurrentDialog(materialDialog);
materialDialog.show();
});
}
/** /**
* 显示确认对话框 * 显示确认对话框

View File

@ -81,4 +81,5 @@
<string name="error_directory_exists_with_same_filename">%1$s不是一個文件夾, 請手動刪除該文件</string> <string name="error_directory_exists_with_same_filename">%1$s不是一個文件夾, 請手動刪除該文件</string>
<string name="error_patch_crc_incorrect">增量更新%1$s失敗: CRC (%2$s))</string> <string name="error_patch_crc_incorrect">增量更新%1$s失敗: CRC (%2$s))</string>
<string name="settings_rewrite_in_parallel">多線程重寫</string> <string name="settings_rewrite_in_parallel">多線程重寫</string>
<string name="request_unknown_source_permission">需要开启未知源权限以安装Mod框架是否前往设置开启</string>
</resources> </resources>

View File

@ -81,4 +81,5 @@
<string name="error_directory_exists_with_same_filename">%1$s不是一个文件夹, 请手动删除该文件</string> <string name="error_directory_exists_with_same_filename">%1$s不是一个文件夹, 请手动删除该文件</string>
<string name="error_patch_crc_incorrect">增量更新%1$s失败: CRC (%2$s))</string> <string name="error_patch_crc_incorrect">增量更新%1$s失败: CRC (%2$s))</string>
<string name="settings_rewrite_in_parallel">多线程重写</string> <string name="settings_rewrite_in_parallel">多线程重写</string>
<string name="request_unknown_source_permission">需要开启未知源权限以安装Mod框架是否前往设置开启</string>
</resources> </resources>

View File

@ -85,4 +85,5 @@
<string name="error_directory_exists_with_same_filename">%1$s is not a directory, please delete it manually.</string> <string name="error_directory_exists_with_same_filename">%1$s is not a directory, please delete it manually.</string>
<string name="error_patch_crc_incorrect">Patch %1$s failed: CRC (%2$s))</string> <string name="error_patch_crc_incorrect">Patch %1$s failed: CRC (%2$s))</string>
<string name="settings_rewrite_in_parallel">Rewrite in Parallel</string> <string name="settings_rewrite_in_parallel">Rewrite in Parallel</string>
<string name="request_unknown_source_permission">Needs to switch unknown source permission on to install mod framework, open settings?</string>
</resources> </resources>