patch-loader: 優化配置和資源處理
Add a shared Gson instance and harden config/module/asset loading to avoid NPEs and crashes. Guard legacy module iteration, use apply() for SharedPreferences, throw when config asset is missing, reuse GSON for parsing, and null-check resource streams before copying. Also set provider dex file writable only if created and remove some unused imports. These changes improve resilience when manager/asset data is unavailable and clean up file handling.
This commit is contained in:
parent
59dc353e0e
commit
74bbeb9bda
|
|
@ -41,13 +41,11 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.attribute.PosixFilePermissions;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
import dalvik.system.DexFile;
|
import dalvik.system.DexFile;
|
||||||
|
|
@ -66,6 +64,8 @@ public class LSPApplication {
|
||||||
private static final int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
|
private static final int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
|
||||||
private static final int PER_USER_RANGE = 100000;
|
private static final int PER_USER_RANGE = 100000;
|
||||||
|
|
||||||
|
private static final Gson GSON = new Gson();
|
||||||
|
|
||||||
private static ActivityThread activityThread;
|
private static ActivityThread activityThread;
|
||||||
private static LoadedApk stubLoadedApk;
|
private static LoadedApk stubLoadedApk;
|
||||||
private static LoadedApk appLoadedApk;
|
private static LoadedApk appLoadedApk;
|
||||||
|
|
@ -105,16 +105,18 @@ public class LSPApplication {
|
||||||
service = new RemoteApplicationService(context);
|
service = new RemoteApplicationService(context);
|
||||||
List<Module> m = service.getLegacyModulesList();
|
List<Module> m = service.getLegacyModulesList();
|
||||||
JSONArray moduleArr = new JSONArray();
|
JSONArray moduleArr = new JSONArray();
|
||||||
for (Module module : m) {
|
if (m != null) {
|
||||||
JSONObject moduleObj = new JSONObject();
|
for (Module module : m) {
|
||||||
moduleObj.put("path", module.apkPath);
|
JSONObject moduleObj = new JSONObject();
|
||||||
moduleObj.put("packageName", module.packageName);
|
moduleObj.put("path", module.apkPath);
|
||||||
moduleArr.put(moduleObj);
|
moduleObj.put("packageName", module.packageName);
|
||||||
|
moduleArr.put(moduleObj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SharedPreferences shared = context.getSharedPreferences("npatch", Context.MODE_PRIVATE);
|
SharedPreferences shared = context.getSharedPreferences("npatch", Context.MODE_PRIVATE);
|
||||||
shared.edit().putString("modules", moduleArr.toString()).commit();
|
shared.edit().putString("modules", moduleArr.toString()).apply();
|
||||||
Log.e(TAG, "Success update module scope");
|
Log.e(TAG, "Success update module scope");
|
||||||
}catch (Exception e){
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to connect to manager, fallback to fixed local service");
|
Log.e(TAG, "Failed to connect to manager, fallback to fixed local service");
|
||||||
service = new NeoLocalApplicationService(context);
|
service = new NeoLocalApplicationService(context);
|
||||||
}
|
}
|
||||||
|
|
@ -153,8 +155,9 @@ public class LSPApplication {
|
||||||
var baseClassLoader = stubLoadedApk.getClassLoader();
|
var baseClassLoader = stubLoadedApk.getClassLoader();
|
||||||
|
|
||||||
try (var is = baseClassLoader.getResourceAsStream(CONFIG_ASSET_PATH)) {
|
try (var is = baseClassLoader.getResourceAsStream(CONFIG_ASSET_PATH)) {
|
||||||
|
if (is == null) throw new IOException("Config file not found in assets");
|
||||||
BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||||
config = new Gson().fromJson(streamReader, PatchConfig.class);
|
config = GSON.fromJson(streamReader, PatchConfig.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Failed to load config file", e);
|
Log.e(TAG, "Failed to load config file", e);
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -180,7 +183,7 @@ public class LSPApplication {
|
||||||
FileUtils.deleteFolderIfExists(originPath);
|
FileUtils.deleteFolderIfExists(originPath);
|
||||||
Files.createDirectories(originPath);
|
Files.createDirectories(originPath);
|
||||||
try (InputStream is = baseClassLoader.getResourceAsStream(ORIGINAL_APK_ASSET_PATH)) {
|
try (InputStream is = baseClassLoader.getResourceAsStream(ORIGINAL_APK_ASSET_PATH)) {
|
||||||
Files.copy(is, cacheApkPath);
|
if (is != null) Files.copy(is, cacheApkPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Path providerPath = null;
|
Path providerPath = null;
|
||||||
|
|
@ -189,9 +192,13 @@ public class LSPApplication {
|
||||||
try {
|
try {
|
||||||
Files.deleteIfExists(providerPath);
|
Files.deleteIfExists(providerPath);
|
||||||
try (InputStream is = baseClassLoader.getResourceAsStream(PROVIDER_DEX_ASSET_PATH)) {
|
try (InputStream is = baseClassLoader.getResourceAsStream(PROVIDER_DEX_ASSET_PATH)) {
|
||||||
Files.copy(is, providerPath);
|
if (is != null) Files.copy(is, providerPath);
|
||||||
|
}
|
||||||
|
if (Files.exists(providerPath)) {
|
||||||
|
providerPath.toFile().setWritable(false);
|
||||||
|
} else {
|
||||||
|
providerPath = null;
|
||||||
}
|
}
|
||||||
providerPath.toFile().setWritable(false);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "Failed to inject provider:" + Log.getStackTraceString(e));
|
Log.e(TAG, "Failed to inject provider:" + Log.getStackTraceString(e));
|
||||||
providerPath = null;
|
providerPath = null;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ public class Constants {
|
||||||
final static public String LOADER_DEX_ASSET_PATH = "assets/npatch/loader.dex";
|
final static public String LOADER_DEX_ASSET_PATH = "assets/npatch/loader.dex";
|
||||||
final static public String META_LOADER_DEX_ASSET_PATH = "assets/npatch/metaloader.dex";
|
final static public String META_LOADER_DEX_ASSET_PATH = "assets/npatch/metaloader.dex";
|
||||||
final static public String PROVIDER_DEX_ASSET_PATH = "assets/npatch/mtprovider.dex";
|
final static public String PROVIDER_DEX_ASSET_PATH = "assets/npatch/mtprovider.dex";
|
||||||
final static public String ORIGINAL_APK_ASSET_PATH = "assets/npatch/origin.apk.np";
|
final static public String ORIGINAL_APK_ASSET_PATH = "assets/npatch/origin.apk";
|
||||||
final static public String EMBEDDED_MODULES_ASSET_PATH = "assets/npatch/modules/";
|
final static public String EMBEDDED_MODULES_ASSET_PATH = "assets/npatch/modules/";
|
||||||
|
|
||||||
final static public String PATCH_FILE_SUFFIX = "-npatched.apk";
|
final static public String PATCH_FILE_SUFFIX = "-npatched.apk";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue