Support for Android java mods

This commit is contained in:
Anuken 2020-09-25 14:21:30 -04:00
parent 85d32cd510
commit 2cc93924f1
4 changed files with 39 additions and 13 deletions

View File

@ -7,7 +7,6 @@ import android.content.pm.*;
import android.net.*;
import android.os.Build.*;
import android.os.*;
import android.provider.Settings.*;
import android.telephony.*;
import arc.*;
import arc.backend.android.*;
@ -15,7 +14,7 @@ import arc.files.*;
import arc.func.*;
import arc.scene.ui.layout.*;
import arc.util.*;
import arc.util.serialization.*;
import dalvik.system.*;
import mindustry.*;
import mindustry.game.Saves.*;
import mindustry.io.*;
@ -23,7 +22,6 @@ import mindustry.net.*;
import mindustry.ui.dialogs.*;
import java.io.*;
import java.lang.System;
import java.lang.Thread.*;
import java.util.*;
@ -73,12 +71,25 @@ public class AndroidLauncher extends AndroidApplication{
public void shareFile(Fi file){
}
@Override
public Class<?> loadJar(Fi jar, String mainClass) throws Exception{
DexClassLoader loader = new DexClassLoader(jar.file().getPath(), getFilesDir().getPath(), null, getClassLoader());
return Class.forName(mainClass, true, loader);
}
@Override
public void showFileChooser(boolean open, String extension, Cons<Fi> cons){
showFileChooser(open, cons, extension);
}
void showFileChooser(boolean open, Cons<Fi> cons, String... extensions){
String extension = extensions[0];
if(VERSION.SDK_INT >= VERSION_CODES.Q){
Intent intent = new Intent(open ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType(extension.equals("zip") && !open ? "application/zip" : "*/*");
intent.setType(extension.equals("zip") && !open && extensions.length == 1 ? "application/zip" : "*/*");
addResultListener(i -> startActivityForResult(intent, i), (code, in) -> {
if(code == Activity.RESULT_OK && in != null && in.getData() != null){
Uri uri = in.getData();
@ -108,7 +119,7 @@ public class AndroidLauncher extends AndroidApplication{
});
}else if(VERSION.SDK_INT >= VERSION_CODES.M && !(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
chooser = new FileChooser(open ? "@open" : "@save", file -> file.extension().equalsIgnoreCase(extension), open, file -> {
chooser = new FileChooser(open ? "@open" : "@save", file -> Structs.contains(extensions, file.extension().toLowerCase()), open, file -> {
if(!open){
cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension));
}else{
@ -124,10 +135,19 @@ public class AndroidLauncher extends AndroidApplication{
perms.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
requestPermissions(perms.toArray(new String[0]), PERMISSION_REQUEST_CODE);
}else{
if(open){
new FileChooser("@open", file -> Structs.contains(extensions, file.extension().toLowerCase()), true, cons).show();
}else{
super.showFileChooser(open, extension, cons);
}
}
}
@Override
public void showMultiFileChooser(Cons<Fi> cons, String... extensions){
showFileChooser(true, cons, extensions);
}
@Override
public void beginForceLandscape(){

View File

@ -14,10 +14,18 @@ import mindustry.type.*;
import mindustry.ui.dialogs.*;
import rhino.*;
import java.net.*;
import static mindustry.Vars.*;
public interface Platform{
/** Dynamically loads a jar file. */
default Class<?> loadJar(Fi jar, String mainClass) throws Exception{
URLClassLoader classLoader = new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, ClassLoader.getSystemClassLoader());
return classLoader.loadClass(mainClass);
}
/** Steam: Update lobby visibility.*/
default void updateLobby(){}
@ -121,7 +129,7 @@ public interface Platform{
}
/**
* Show a file chooser for multiple file types. Only supported on desktop.
* Show a file chooser for multiple file types.
* @param cons Selection listener
* @param extensions File extensions to filter
*/

View File

@ -25,7 +25,6 @@ import mindustry.type.*;
import mindustry.ui.*;
import java.io.*;
import java.net.*;
import static mindustry.Vars.*;
@ -634,12 +633,11 @@ public class Mods implements Loadable{
//make sure the main class exists before loading it; if it doesn't just don't put it there
if(mainFile.exists()){
//mobile versions don't support class mods
if(mobile){
throw new IllegalArgumentException("Java class mods are not supported on mobile.");
if(ios){
throw new IllegalArgumentException("Java class mods are not supported on iOS.");
}
URLClassLoader classLoader = new URLClassLoader(new URL[]{sourceFile.file().toURI().toURL()}, ClassLoader.getSystemClassLoader());
Class<?> main = classLoader.loadClass(mainClass);
Class<?> main = platform.loadJar(sourceFile, mainClass);
metas.put(main, meta);
mainMod = (Mod)main.getDeclaredConstructor().newInstance();
}else{

View File

@ -33,7 +33,7 @@ public class CrashSender{
+ "OS: " + System.getProperty("os.name") + " x" + (OS.is64Bit ? "64" : "32") + "\n"
+ "Java Version: " + System.getProperty("java.version") + "\n"
+ "Java Architecture: " + System.getProperty("sun.arch.data.model") + "\n"
+ mods.list().size + " Mods: " + mods.list().toString(", ", mod -> mod.name + ":" + mod.meta.version)
+ mods.list().size + " Mods: " + (mods.list().isEmpty() ? "none" : mods.list().toString(", ", mod -> mod.name + ":" + mod.meta.version))
+ "\n\n" + error;
}