Fix Android loadJar (#10867)

* Fix Android loadJar

* Using another way

* Code formating

* Fix mod update
This commit is contained in:
Wxp
2025-06-03 02:32:24 +08:00
committed by GitHub
parent 18d852b5c1
commit 7076d1bf97
3 changed files with 70 additions and 24 deletions

View File

@@ -73,28 +73,57 @@ public class AndroidLauncher extends AndroidApplication{
@Override
public ClassLoader loadJar(Fi jar, ClassLoader parent) throws Exception{
//Required to load jar files in Android 14: https://developer.android.com/about/versions/14/behavior-changes-14#safer-dynamic-code-loading
jar.file().setReadOnly();
return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, parent){
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
//check for loaded state
Class<?> loadedClass = findLoadedClass(name);
if(loadedClass == null){
try{
//try to load own class first
loadedClass = findClass(name);
}catch(ClassNotFoundException | NoClassDefFoundError e){
//use parent if not found
return parent.loadClass(name);
try{
jar.file().setReadOnly();
return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, parent){
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
//check for loaded state
Class<?> loadedClass = findLoadedClass(name);
if(loadedClass == null){
try{
//try to load own class first
loadedClass = findClass(name);
}catch(ClassNotFoundException | NoClassDefFoundError e){
//use parent if not found
return parent.loadClass(name);
}
}
}
if(resolve){
resolveClass(loadedClass);
if(resolve){
resolveClass(loadedClass);
}
return loadedClass;
}
return loadedClass;
};
}catch(SecurityException e){
//`setReadOnly` to jar file in `/sdcard/Android/data/...` does not work on some Android 14 device
//But in `/data/...` it works
if(Build.VERSION.SDK_INT < VERSION_CODES.O_MR1){
throw e;
}
};
Fi cacheDir = new Fi(getCacheDir()).child("mods");
cacheDir.mkdirs();
//long file name support
Fi modCacheDir = cacheDir.child(jar.nameWithoutExtension());
Fi modCache = modCacheDir.child(Long.toHexString(jar.lastModified()) + ".zip");
if(modCacheDir.equals(jar.parent())){
//should not reach here, just in case
throw e;
}
//Cache will be deleted when mod is removed
if(!modCache.exists() || jar.length() != modCache.length()){
modCacheDir.mkdirs();
jar.copyTo(modCache);
}
modCache.file().setReadOnly();
return loadJar(modCache, parent);
}
}
@Override