Динамически загружать APK, который использует ресурсы
У меня есть 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 ответа
Вы можете обратиться к следующему проекту с открытым исходным кодом: 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, используйте getResource.
Чтобы получить ресурсы из других apk, вам нужно использовать getResourcesForApplication (). Очевидно, что главный apk не имеет этой иконки в сгенерированном виде. R
класс, но сервис один. Таким образом, в Сервисе, когда вы пытаетесь получить доступ к ресурсам, это должно выглядеть так:
Resources res = packageManager.getResourcesForApplication("com.your_service");
Drawable icon = res.getDrawable(iconId);
К сожалению, я думаю, что просто невозможно пройти iconId
в уведомлении, и вам нужно будет загрузить ресурс самостоятельно перед использованием в уведомлении (например, настройка RemoteViews
и используйте Notification.Builder.setContent ()).