auto extract native libraries and detect lib name for NativeActivity

This commit is contained in:
Julian Winkler 2023-06-06 22:08:00 +02:00
parent 83a2647637
commit 334274c9e5
3 changed files with 46 additions and 8 deletions

View file

@ -29,14 +29,6 @@ or just
`android-translation-layer [path to apk] -l [activity to launch]`
to use the default data dir of `~/.local/share/android_translation_layer/`
NOTE: for apps which use the built-in NativeActivity mechanism, simply specify `-l android/app/NativeActivity`
if `android.app.lib_name` is set in the manifest, you currently need to rename the lib to `libmain.so`, which is the default.
in cases where there's alread a different lib with that name, you need to add a way to pass the lib name to the NativeActivity class
if `android.app.func_name` is set in the manifest, then you need to add a way to pass this to the NativeActivity class
(currently, the default of `ANativeActivity_onCreate` is always used, which works for all apps using `android_native_app_glue`)
TODO: figure out a mechanism for passing these to the NativeActivity class
TODO_LONGTERM: parse AndroidManifest.xml
NOTE: some apps don't like runtime changes to resolution, and currently GLSurfaceView will stretch instead of changing resolution
to sidestep this, we allow for specifying the initial resolution, which will currently always get passed as the screen resolution to the app and to GLSurfaceView even when you resize the window.
example with custom width/height: `android-translation-layer path/to/org.happysanta.gd_29.apk -l org/happysanta/gd/GDActivity -w 540 -h 960`

View file

@ -37,6 +37,12 @@ import android.view.WindowManager;
//import android.view.inputmethod.InputMethodManager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
import com.reandroid.arsc.chunk.xml.ResXmlAttribute;
import com.reandroid.arsc.chunk.xml.ResXmlElement;
/**
* Convenience for implementing an activity that will be implemented
@ -161,6 +167,30 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
throw new RuntimeException("Error getting activity info", e);
}*/
// parse AndroidManifest.xml to get name and entry of native lib
try (InputStream inStream = ClassLoader.getSystemClassLoader().getResourceAsStream("AndroidManifest.xml")) {
for (ResXmlElement activity: AndroidManifestBlock.load(inStream).listActivities()) {
if (!getClass().getName().equals(activity.searchAttributeByResourceId(AndroidManifestBlock.ID_name).getValueAsString())) {
continue;
}
for (ResXmlElement metaData: activity.listElements(AndroidManifestBlock.TAG_meta_data)) {
ResXmlAttribute name = metaData.searchAttributeByResourceId(AndroidManifestBlock.ID_name);
ResXmlAttribute value = metaData.searchAttributeByResourceId(AndroidManifestBlock.ID_value);
if (name == null || value == null){
continue;
}
if (META_DATA_LIB_NAME.equals(name.getValueAsString())){
libname = value.getValueAsString();
}
if (META_DATA_FUNC_NAME.equals(name.getValueAsString())){
funcname = value.getValueAsString();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
String path = null;
File libraryFile = new File(new File(android.os.Environment.getExternalStorageDirectory(), "lib"),

View file

@ -16,6 +16,18 @@
#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/* 0666*/
#endif
#ifdef __x86_64__
#define NATIVE_ARCH "x86_64"
#elifdef __i386__
#define NATIVE_ARCH "x86"
#elifdef __aarch64__
#define NATIVE_ARCH "arm64-v8a"
#elifdef __arm__
#define NATIVE_ARCH "armeabi-v7a"
#else
#error unknown native architecture
#endif
GtkWidget *window;
// standard Gtk Application stuff, more or less
@ -272,6 +284,8 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
char *app_lib_dir = malloc(strlen(app_data_dir) + strlen("/lib") + 1); // +1 for NULL
strcpy(app_lib_dir, app_data_dir);
strcat(app_lib_dir, "/lib");
// create lib dir
mkdir(app_lib_dir, DEFFILEMODE | S_IXUSR | S_IXGRP | S_IXOTH);
// calling directly into the shim bionic linker to whitelist the app's lib dir as containing bionic-linked libraries
dl_parse_library_path(app_lib_dir, ":");
@ -326,6 +340,8 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
(*env)->CallVoidMethod(env, java_runtime, loadLibrary_with_classloader, _JSTRING("translation_layer_main"), class_loader);
extract_from_apk("assets/", "assets/");
/* extract native libraries from apk*/
extract_from_apk("lib/" NATIVE_ARCH "/", "lib/");
/* -- run the main activity's onCreate -- */