Динамически загружать 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 ()).

Другие вопросы по тегам