2014-02-26 104 views
1

我有service.apk使用资源在状态栏中显示通知。动态加载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: [email protected]

动态加载代码:

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的方式是错误的?也许我应该为资源添加路径?

任何帮助将非常感谢!

+0

这看起来会变得非常复杂,如果它甚至有可能的话。在功能方面,你真的想要达到什么目标?你觉得这是它的方法吗? –

+0

service.apk正在使用资源在状态栏中显示通知(而不是在下拉菜单中),只能使用资源。我需要动态加载该service.apk并让它仍然显示通知... –

+0

但你希望通过动态加载服务apk实现什么?这是不可能做你想象的。 –

回答

0

要从其他apk获取资源,您需要使用getResourcesForApplication()。很显然,主apk没有这个图标,在它生成的R类中,但服务一。 所以,在服务,当你要访问的资源,它应该看起来像:

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

不幸的是,我认为这将是不可能的,只是传递通知iconId和你需要在通知中使用之前自己加载资源(例如设置为RemoteViews并使用Notification.Builder.setContent())。

+0

serviceImpl.apk是在状态栏中发布图标的人员,为此它必须传递资源ID。所以我猜它不应该加载资源,因为资源存在于它的apk中。 –

+0

我相信你的猜测是错误的。如果您在另一个应用上下文中启动服务,它将按照我所描述的方式工作。现在唯一可能的解决方案 - 自己加载资源,id不起作用,因为它没有在主应用程序中显示。可能你不需要使用PathClassLoader并使用正常方式启动服务(例如intent) - 那么资源id将不会出现问题。 – sandrstar

+0

我必须使用动态加载来加载该服务。这就是要求。 –

1

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

下面是重点思考: 第一,APK可以通过主机Android应用程序被加载,忽略了它是在SD卡或系统目录。但我们如何做到这一点?需要解决两个问题:资源和活动的生命周期。上面的项目解决了这两个问题,现在,使用资源的动态加载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标识符访问资源,使用getResource。

+1

可以提供更多关于这个开源项目的信息,以及它如何提供帮助,这句话很好。 – JackDev