load layout XMLs directly from apk file

This commit is contained in:
Julian Winkler 2023-05-20 12:38:34 +02:00
parent db53d3679f
commit 3709e30f64
5 changed files with 13 additions and 24 deletions

View file

@ -43,9 +43,6 @@ example with custom width/height: `android-translation-layer path/to/org.happysa
NOTE: you might need to copy some files out from the apk under `ANDROID_APP_DATA_DIR`
(defaults to `~/.local/share/android_translation_layer/`), e.g the `assets` folder;
additionally, resources (`res`) currently need to be "decompiled" (e.g. by apktool, though this
additionally replaces hex IDs with string names, which then needs to be manually reversed;
android studio's `inspect apk` feature is known to keep the integers)
NOTE: on X11, Gtk might decide to use GLX, which completely messes up our EGL-dependent code.
If you have a debug build of Gtk, you can use GDK_DEBUG=gl-egl to force the use of EGL
NOTE: we don't currently handle signed apks; simply remove the META-INF folder from an apk to skip signature verification

View file

@ -4,6 +4,7 @@ import android.content.Context;
import android.content.ComponentName;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.widget.TextView;
@ -136,15 +137,7 @@ public class Activity extends Context {
public void setContentView(int layoutResID) throws Exception {
System.out.println("- setContentView - yay!");
String layout_xml_file = android.os.Environment.getExternalStorageDirectory().getPath() + "/" + getString(layoutResID);
System.out.println("loading layout from: " + layout_xml_file);
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput( new FileReader(layout_xml_file) );
XmlResourceParser xpp = Context.this_application.getResources().getLayout(layoutResID);
root_view = layout_inflater.inflate(xpp, null, false);

View file

@ -19,6 +19,9 @@ package android.content.res;
import com.reandroid.arsc.chunk.TableBlock;
import com.reandroid.arsc.value.ResValueMap;
import com.reandroid.arsc.chunk.xml.ResXmlPullParser;
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
@ -479,13 +482,12 @@ public final class AssetManager {
block.close();
return rp;*/
XmlPullParserFactory factory = XmlPullParserFactory.newInstance("android.util.DecompiledXmlResourceParser", this.getClass());
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput( new FileReader(android.os.Environment.getExternalStorageDirectory().getPath() + "/" + fileName) );
return (XmlResourceParser)xpp;
InputStream inStream = ClassLoader.getSystemClassLoader().getResourceAsStream(fileName);
ResXmlDocument resXmlDocument = new ResXmlDocument();
resXmlDocument.readBytes(inStream);
ResXmlPullParser xpp = new ResXmlPullParser();
xpp.setResXmlDocument(resXmlDocument);
return xpp;
}
/**

View file

@ -692,7 +692,7 @@ public class View extends Object {
public View() {} // FIXME
public View(AttributeSet attrs) {
id = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "id", 0);
id = attrs.getAttributeResourceValue("http://schemas.android.com/apk/res/android", "id", 0);
if(id != 0)
view_by_id.put(id, this);

View file

@ -213,11 +213,8 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
if(ret) {
printf("can't stat %s (%s); we don't currently support parsing certain resources from the apk file, "
"so you will need to create this directory and put in those resources\n"
"some of these resources need to be preprocessed, apktool is mostly fine except it replaces "
"the numeric values in the layout xml files with what it assumes was in the source xml; "
"android studio's apk anylyzer (for example) leaves the 'compiled' integer values that our code expects\n"
"NOTE: if the app you're trying to run doesn't use any such resources, simply create the directory "
"and leave it empty (this will be done automatically once the maunal preprocessing step is not required)\n",
"and leave it empty (this will be done automatically once the maunal extraction step is not required)\n",
app_data_dir, strerror(errno));
exit(1);
}