我有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的方式错了?也许我应该为资源添加一条路径?
非常感谢任何帮助!
答案 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} })。