Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -73,28 +73,57 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
@Override
|
@Override
|
||||||
public ClassLoader loadJar(Fi jar, ClassLoader parent) throws Exception{
|
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
|
//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();
|
try{
|
||||||
return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, parent){
|
jar.file().setReadOnly();
|
||||||
@Override
|
return new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, parent){
|
||||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
|
@Override
|
||||||
//check for loaded state
|
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
|
||||||
Class<?> loadedClass = findLoadedClass(name);
|
//check for loaded state
|
||||||
if(loadedClass == null){
|
Class<?> loadedClass = findLoadedClass(name);
|
||||||
try{
|
if(loadedClass == null){
|
||||||
//try to load own class first
|
try{
|
||||||
loadedClass = findClass(name);
|
//try to load own class first
|
||||||
}catch(ClassNotFoundException | NoClassDefFoundError e){
|
loadedClass = findClass(name);
|
||||||
//use parent if not found
|
}catch(ClassNotFoundException | NoClassDefFoundError e){
|
||||||
return parent.loadClass(name);
|
//use parent if not found
|
||||||
|
return parent.loadClass(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(resolve){
|
if(resolve){
|
||||||
resolveClass(loadedClass);
|
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
|
@Override
|
||||||
|
|||||||
@@ -182,3 +182,4 @@ MonoChronos
|
|||||||
RushieWashie
|
RushieWashie
|
||||||
ITY
|
ITY
|
||||||
Iniquit
|
Iniquit
|
||||||
|
DSFdsfWxp
|
||||||
|
|||||||
@@ -413,11 +413,22 @@ public class Mods implements Loadable{
|
|||||||
|
|
||||||
/** Removes a mod file and marks it for requiring a restart. */
|
/** Removes a mod file and marks it for requiring a restart. */
|
||||||
public void removeMod(LoadedMod mod){
|
public void removeMod(LoadedMod mod){
|
||||||
if(!android && mod.loader != null){
|
boolean deleted = true;
|
||||||
try{
|
|
||||||
ClassLoaderCloser.close(mod.loader);
|
if(mod.loader != null){
|
||||||
}catch(Exception e){
|
if(android){
|
||||||
Log.err(e);
|
//Try to remove cache for Android 14 security problem
|
||||||
|
Fi cacheDir = new Fi(Core.files.getCachePath()).child("mods");
|
||||||
|
Fi modCacheDir = cacheDir.child(mod.file.nameWithoutExtension());
|
||||||
|
if(modCacheDir.exists()){
|
||||||
|
deleted = modCacheDir.deleteDirectory();
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
try{
|
||||||
|
ClassLoaderCloser.close(mod.loader);
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.err(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,7 +436,7 @@ public class Mods implements Loadable{
|
|||||||
mod.root.delete();
|
mod.root.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean deleted = mod.file.isDirectory() ? mod.file.deleteDirectory() : mod.file.delete();
|
deleted &= mod.file.isDirectory() ? mod.file.deleteDirectory() : mod.file.delete();
|
||||||
|
|
||||||
if(!deleted){
|
if(!deleted){
|
||||||
ui.showErrorMessage("@mod.delete.error");
|
ui.showErrorMessage("@mod.delete.error");
|
||||||
@@ -1112,6 +1123,11 @@ public class Mods implements Loadable{
|
|||||||
//close the classloader for jar mods
|
//close the classloader for jar mods
|
||||||
if(!android){
|
if(!android){
|
||||||
ClassLoaderCloser.close(other.loader);
|
ClassLoaderCloser.close(other.loader);
|
||||||
|
}else if(other.loader != null){
|
||||||
|
//Try to remove cache for Android 14 security problem
|
||||||
|
Fi cacheDir = new Fi(Core.files.getCachePath()).child("mods");
|
||||||
|
Fi modCacheDir = cacheDir.child(other.file.nameWithoutExtension());
|
||||||
|
modCacheDir.deleteDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
//close zip file
|
//close zip file
|
||||||
|
|||||||
Reference in New Issue
Block a user