动态加载使用资源的apk

时间:2014-02-26 20:04:54

标签: android apk dynamic-loading

我有service.apk正在使用资源在状态栏中显示通知。

我正在动态加载使用这些资源的类,但是通知的资源以某种方式消失了,我收到了这个错误:

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

动态加载的代码:

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);

我想也许我加载apk的方式错了?也许我应该为资源添加一条路径?

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

您可以参考以下开源项目: https://github.com/singwhatiwanna/dynamic-load-apk/blob/master/README-en.md

以下是关键思路: 首先,apk可以由主机android应用程序加载,忽略它在sdcard或系统目录上。但是我们怎么做呢?需要解决两个问题:资源和活动的生命周期。上面的项目解决了这两个问题,现在,动态加载apk可以使用资源,使用DexClassLoader并提供新的AssetManager可以满足您的需求。

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());
}

然后,R identifer可以访问资源,使用getResource。

答案 1 :(得分:0)

要从其他apk获取资源,您需要使用getResourcesForApplication()。很明显,主apk在它生成的R类中没有那个图标,但是服务一个。 因此,在服务中,每当您尝试访问资源时,它应该如下所示:

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

不幸的是,我认为在通知中传递iconId是不可能的,您需要在使用通知之前自己加载资源(例如设置RemoteViews并使用{{3} })。