Dynamically load apk that uses resources

邮差的信 提交于 2019-12-09 23:10:54

问题


I have service.apk that is using resources to show a notification in the status bar.

I am dynamically loading the class that is using these resources but then the resources for the notifications disappear somehow, and I'm getting this error:

W/ResourceType( 1142): No known package when getting value for resource number 0x7f020001 W/StatusBarIconView( 1142): Icon not found in 2130837505: 7f020001 W/StatusBarIconView( 1142): No icon for slot android/0x20 W/ActivityManager( 941): crashApplication: trying to crash self! D/NotificationService( 941): onNotification error pkg=android tag=null id=32; will crashApplication(uid=1000, pid=941) W/StatusBar( 1142): removeNotification for unknown key: android.os.BinderProxy@41b166b8

The code that dynamically loads:

PathClassLoader classLoader =
                new PathClassLoader("system/app/ServiceImpl.apk",
                               ClassLoader.getSystemClassLoader());
              Class someClass =
            classLoader.loadClass("com.bla.ServiceImpl");
              Constructor<Class> ctor = someClass.getConstructor(Context.class);
              Object someObject = ctor.newInstance(context);

I'm thinking maybe the way I'm loading the apk is wrong? Maybe I should add a path for the resources?

Any Help would be very much appreciated!


回答1:


you can refer to the following open source project: https://github.com/singwhatiwanna/dynamic-load-apk/blob/master/README-en.md

following is the key thinking: first, apk can be loaded by host android application, ignored that it is on sdcard or on system directory. but how can we do this? two problems need to be resolved: resource and activity's lifecircle. the above project resolves this two problems, now, Dynamically load apk that uses resources is possible, use DexClassLoader and provide new AssetManager can satisfy your demand.

protected void loadResources() {
    try {
        AssetManager assetManager = AssetManager.class.newInstance();
        Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
        addAssetPath.invoke(assetManager, mDexPath);
        mAssetManager = assetManager;
    } catch (Exception e) {
        e.printStackTrace();
    }
    Resources superRes = super.getResources();
    mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),
            superRes.getConfiguration());
    mTheme = mResources.newTheme();
    mTheme.setTo(super.getTheme());
}

then, resources can be visited by R identifer, use getResource.




回答2:


To obtain resources from other apk, You need to use getResourcesForApplication(). It's obvious that main apk doesn't have that icon in it's generated R class, but Service one has. So, in the Service, whenever You're trying to access resources, it should look like:

Resources res = packageManager.getResourcesForApplication("com.your_service");
Drawable icon = res.getDrawable(iconId);

Unfortunately, I think it'll not be possible to just pass iconId in notification and You'll need to load resource yourself before using in notification (e.g. setup RemoteViews and use Notification.Builder.setContent()).



来源:https://stackoverflow.com/questions/22052091/dynamically-load-apk-that-uses-resources

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!