1

I have service.apk that is using resources to show a notification in the status bar.

I am dynamically loading the class that is using these resources but then the resources for the notifications disappear somehow, and I'm getting this error:

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

The code that dynamically loads:

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

I'm thinking maybe the way I'm loading the apk is wrong? Maybe I should add a path for the resources?

Any Help would be very much appreciated!

Ravit D
  • 907
  • 9
  • 27
  • This looks like it is going to be extremely complicated, if it is even possible a at all. What are you really trying to achieve in terms of functionality that you feel this is the way to go about it? – Chris Stratton Feb 26 '14 at 20:20
  • The service.apk is using resources to show a notification in the status bar (and not in the drop down menu) which is only possible using resources. I need to dynamically load that service.apk and have it still show the notifications... – Ravit D Feb 27 '14 at 07:32
  • But what do you hope to achieve by dynamically loading the services apk? It is unlikely to do what you imagine. – Chris Stratton Feb 27 '14 at 13:15
  • @ChrisStratton That's because the code of the service.apk resides in a different partition than the place I load it from. I have to do it this way... – Ravit D Feb 27 '14 at 13:20
  • But why do you want to load the service apk at all? What do you imagine you will be able to do by launching it in a process belonging to your app userid, rather than having the system start it in the usual way as its own process? This resources issue is likely a trivial distraction from the real difficulty of this unusual scheme. – Chris Stratton Feb 27 '14 at 14:37

2 Answers2

1

you can refer to the following open source project: https://github.com/singwhatiwanna/dynamic-load-apk/blob/master/README-en.md

following is the key thinking: first, apk can be loaded by host android application, ignored that it is on sdcard or on system directory. but how can we do this? two problems need to be resolved: resource and activity's lifecircle. the above project resolves this two problems, now, Dynamically load apk that uses resources is possible, use DexClassLoader and provide new AssetManager can satisfy your demand.

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

then, resources can be visited by R identifer, use getResource.

  • 1
    would be good to provide a bit more info regarding what this open source project does and how it helps, a sentence is fine. – JackDev Nov 12 '14 at 05:31
0

To obtain resources from other apk, You need to use getResourcesForApplication(). It's obvious that main apk doesn't have that icon in it's generated R class, but Service one has. So, in the Service, whenever You're trying to access resources, it should look like:

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

Unfortunately, I think it'll not be possible to just pass iconId in notification and You'll need to load resource yourself before using in notification (e.g. setup RemoteViews and use Notification.Builder.setContent()).

sandrstar
  • 12,503
  • 8
  • 58
  • 65
  • The serviceImpl.apk is the one publishing an icon in the status bar, and for that it must pass resource-id. So I guess it shouldn't load resources, since the resources exist in its apk. – Ravit D Mar 04 '14 at 08:36
  • I believe your guess is wrong. If You launch service in another app context it work the way I've described. Only solution possible now - to load resources by yourself, id will not work, because it's not presented in main app. Probably you don't need to use PathClassLoader and launch the service using normal way (e.g. intent) - then there will be no problem with resource ids. – sandrstar Mar 04 '14 at 08:39
  • I must use dynamic loading to load that service. That's the request. – Ravit D Mar 09 '14 at 15:46