remove custom AndroidManifest.xml parsing and instead use PackageParser

This has the advantage, that AndroidManifest.xml is only parsed once.
This commit is contained in:
Julian Winkler
2024-06-10 23:24:29 +02:00
parent f249e1c487
commit b15bf203a7
8 changed files with 126 additions and 232 deletions

View File

@@ -3,13 +3,11 @@ package android.app;
import android.R;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageParser;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -53,23 +51,16 @@ public class Activity extends ContextWrapper implements Window.Callback {
*/
private static Activity createMainActivity(String className, long native_window) throws Exception {
if (className == null) {
XmlResourceParser parser = Context.this_application.getAssets().openXmlResourceParser("AndroidManifest.xml");
for (; parser.getEventType() != XmlResourceParser.END_DOCUMENT; parser.next()) {
if (parser.getEventType() == XmlResourceParser.START_TAG && "activity".equals(parser.getName())) {
className = parser.getAttributeValue("http://schemas.android.com/apk/res/android", "name");
}
// check if it is the main activity
if (parser.getEventType() == XmlResourceParser.START_TAG && "action".equals(parser.getName())) {
if ("android.intent.action.MAIN".equals(parser.getAttributeValue("http://schemas.android.com/apk/res/android", "name"))) {
for (PackageParser.Activity activity: pkg.activities) {
for (PackageParser.IntentInfo intent: activity.intents) {
if (intent.matchAction("android.intent.action.MAIN")) {
className = activity.className;
break;
}
}
if (className != null)
break;
}
parser.close();
if(className.indexOf('.') == -1)
className = "." + className;
if (className.startsWith("."))
className = Context.this_application.getPackageName() + className;
} else {
className = className.replace('/', '.');
}
@@ -87,24 +78,13 @@ public class Activity extends ContextWrapper implements Window.Callback {
CharSequence label = null;
CharSequence app_label = null;
try (XmlResourceParser parser = getAssets().openXmlResourceParser("AndroidManifest.xml")) {
for (; parser.getEventType() != XmlResourceParser.END_DOCUMENT; parser.next()) {
if (parser.getEventType() == XmlResourceParser.START_TAG && "application".equals(parser.getName())) {
TypedArray a = obtainStyledAttributes(parser, R.styleable.AndroidManifestApplication);
app_label = a.getText(R.styleable.AndroidManifestApplication_label);
a.recycle();
} else if (parser.getEventType() == XmlResourceParser.START_TAG && "activity".equals(parser.getName())) {
if (getClass().getName().equals(parser.getAttributeValue("http://schemas.android.com/apk/res/android", "name"))) {
TypedArray a = obtainStyledAttributes(parser, R.styleable.AndroidManifestActivity);
label = a.getText(R.styleable.AndroidManifestActivity_label);
a.recycle();
break;
}
}
for (PackageParser.Activity activity: pkg.activities) {
if (getClass().getName().equals(activity.className)) {
label = getText(activity.info.labelRes);
break;
}
} catch (Exception e) {
e.printStackTrace();
}
app_label = getText(pkg.applicationInfo.labelRes);
if (label != null) {
setTitle(label);
} else if (app_label != null) {

View File

@@ -2,23 +2,18 @@ package android.app;
import android.os.Bundle;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.R;
import android.content.Context;
import android.content.ContextWrapper;
public class Application extends ContextWrapper {
private String app_icon_path = null;
private String app_label = null;
public long native_window;
private String get_app_icon_path() {
return app_icon_path;
return getString(pkg.applicationInfo.icon);
}
private String get_app_label() {
return app_label;
return getString(pkg.applicationInfo.labelRes);
}
public interface ActivityLifecycleCallbacks {
@@ -47,19 +42,6 @@ public class Application extends ContextWrapper {
public Application() {
super(new Context());
/* TODO: is this the right place to put this? */
try (XmlResourceParser parser = getAssets().openXmlResourceParser("AndroidManifest.xml")) {
for (; parser.getEventType() != XmlResourceParser.END_DOCUMENT; parser.next()) {
if (parser.getEventType() == XmlResourceParser.START_TAG && "application".equals(parser.getName())) {
TypedArray a = getResources().obtainAttributes(parser, R.styleable.AndroidManifestApplication);
app_icon_path = a.getString(R.styleable.AndroidManifestApplication_icon);
app_label = a.getString(R.styleable.AndroidManifestApplication_label);
a.recycle();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Called when the application is starting, before any activity, service,

View File

@@ -18,23 +18,19 @@ package android.app;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.XmlResourceParser;
// import android.graphics.PixelFormat;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.os.MessageQueue;
import android.util.AttributeSet;
import android.view.InputQueue;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
// import android.view.inputmethod.InputMethodManager;
import java.io.File;
@@ -161,30 +157,16 @@ 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 (XmlResourceParser parser = getAssets().openXmlResourceParser("AndroidManifest.xml")) {
for (; parser.getEventType() != XmlResourceParser.END_DOCUMENT; parser.next()) {
if (parser.getEventType() == XmlResourceParser.START_TAG && "activity".equals(parser.getName())) {
if (!getClass().getName().equals(parser.getAttributeValue("http://schemas.android.com/apk/res/android", "name"))) {
continue;
}
for (; !(parser.getEventType() == XmlResourceParser.END_TAG && "activity".equals(parser.getName())); parser.next()) {
if (parser.getEventType() == XmlResourceParser.START_TAG && "meta-data".equals(parser.getName())) {
String name = parser.getAttributeValue("http://schemas.android.com/apk/res/android", "name");
String value = parser.getAttributeValue("http://schemas.android.com/apk/res/android", "value");
if (META_DATA_LIB_NAME.equals(name)) {
libname = value;
}
if (META_DATA_FUNC_NAME.equals(name)) {
funcname = value;
}
}
}
break;
for (PackageParser.Activity activity : pkg.activities) {
if (getClass().getName().equals(activity.className)) {
if (activity.metaData != null) {
String ln = activity.metaData.getString(META_DATA_LIB_NAME);
if (ln != null) libname = ln;
ln = activity.metaData.getString(META_DATA_FUNC_NAME);
if (ln != null) funcname = ln;
}
break;
}
} catch (Exception e) {
e.printStackTrace();
}
String path = null;