14

I have 1 .jar file on sdCard (i used dx tool to compile a usual .jar to dex.. otherwise android will complain at runtime)

The class that i want to use is actually a Activity & by "use" i mean Inflate!

A) i've noticed that if i load class like this, loaded class will have as package parrent the package of parrent-class (the one in which i run the code: example: real-package of class in jar library: "com.something" & my-app-package: "com.wonderfull" -> loaded class is in "com.wonderfull.com.something" :) ) -> retested: it keeps the original package, just as in the library

B) In "best" case scenario i get this error:

Unable to instantiate activity ComponentInfo{com.appno2/com.appno1.futureLib.LibActivity}: java.lang.ClassNotFoundException: com.appno1.futureLib.LibActivity in loader dalvik.system.PathClassLoader[/data/app/com.appno2-1.apk]

C) In manifest i've placed Activity (the one to be loaded dinamically) like this:

activity android:name="com.appno1.futureLib.LibActivity" android:label="@string/app_name" > /activity>

So i repeat question from title: is it possible to dinamically load a Activity class from a jar library on the sdCard & actually use it ?

In case of "Why would you want this?" - just curios! + as a concept: the posibility to download actual code of app (in the form of a jar of something) just after user entered a valid licence

Update: - this ideea works with fragments (meaning class to be imported is a fragment)

Current conclusion: - it is possible to have: lame java classes or even android UI related classes in a external .jar (on sdCard for example, or to be downloaded from internet..etc) & load them dinamically at need. Oh yeah: you cant work this way this activities :( .. probably not even services..

More info #1: Is it possible to dynamically load a library at runtime from an Android application?

More info #2: http://android-developers.blogspot.ro/2011/07/custom-class-loading-in-dalvik.html

Regardin URLClassLoader: this works (without involving DalvikClassLoader - ClassNotFoundException && obviosly: still cant inflate a activity loaded like this)

File file = new File("/sdcard/myLib.jar");
File tmpDir = getDir("dex", 0);
ClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}, this.getClass().getClassLoader());
DexClassLoader classloader = new DexClassLoader(file.getAbsolutePath(), tmpDir.getAbsolutePath(), null, loader);
Class<Object> classref = (Class<Object>) classloader.loadClass("packageInLib.ClassName");
Object myInstance = classref.getConstructor().newInstance();

Or instead of "loadClass"
Class<?> classref = Class.forName("packageInLib.ClassName", true, dalvikClassLoader);
Community
  • 1
  • 1
pulancheck1988
  • 2,024
  • 3
  • 28
  • 46
  • Hi @pulancheck1988, got any wayout .? – Nitesh May 23 '16 at 05:25
  • Hi, is there a solution to this problem. I am stuck at java.lang.ClassNotFoundException as explained below because the loader does not search the "updated" DexPathList apparently –  Jun 18 '21 at 13:51

2 Answers2

1

I got similar scenarios.

If u do not put below codes in AndroidManifest.xml

<activity android:name="com.appno1.futureLib.LibActivity" android:label="@string/app_name" > </activity>

U will get below error.

10-21 17:04:25.860: E/AndroidRuntime(11050): Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {... ...}; have you declared this activity in your AndroidManifest.xml?

But if u register the activity in your client application, then java.lang.ClassNotFoundException will be got.

The loader tried to search com.appno1.futureLib.LibActivity in [/data/app/com.appno2-1.apk]. Obviously this is not expected. I believed com.appno.futureLib.LibActivity is located in the .jar file.

If there is a way to let the loader to search LibActivity in the .jar file, the problem may be solved.

whogiawho
  • 466
  • 9
  • 21
  • Hi. So: activity is in jar (from sdCard).. if i create instance of object & check class type -> Activity so this is OK! In manifest i have "com.appno1.futureLib.LibActivity" (ive tried also without "com.appno1." .. in any case if this were wrong -> error would contain "Are sure you have declared xxx in manifest??") -> seems legit! But i still get "ClassNotFoundException: com.appno1.futureLib.LibActivity in loader " .. next test i will intentionally alter .classpath file – pulancheck1988 Oct 21 '12 at 09:43
  • whogiawho, how do you register the activity?? – Ivan Mar 22 '13 at 11:30
  • @Ivan To register an activity, you create a new `` tag in the calling application's AndroidManifest.xml, as @whogiawho demonstrates above. – Kenny Worden Jul 05 '17 at 14:30
0

You can scan JAR files for their contents and load classes with URLClassloader. It is standard Java (I have a JavaSE implementation if you wish to take a look), but it is included in the Android API, so I think it should work fine.

URLClassloader on developer.android.com

Basically you get a ClassLoader (dirty code warning!):

File file = new File("/sdcard/jars/myDynamicLib.jar");
ClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}, this.getClass().getClassLoader());

you need your metadata XML or whatever describes what to load:

jar.getInputStream(jar.getEntry("myMetaData.xml"));

You load the information (the way you parse it depends on the format you use: you can have it already loaded with your app as well) - now you have the classname.

And now you just attempt loading:

Class<?> classref = Class.forName(className, true, loader);
instance = (MyType) classref.getConstructor().newInstance();

Again, although I haven't tried such things on Droid, I think this should work fine.

That makes it up. You need the path to the JAR file, and the name of the class to load. The class loader will pull the classes out of the JAR for you.

Powerslave
  • 1,408
  • 15
  • 16
  • URLClassLoading work..but DalvikClassLoader has to be involved, else ClassNotFoundException - since jar actually contains dex classes (instead of .jar it could be a .apk, .zip file).. i've added in question some code (i can format it there better) – pulancheck1988 Oct 22 '12 at 08:19
  • you will get in premission trouble! every activity should be defined in manifest! – Korniltsev Anatoly Oct 22 '12 at 08:28
  • @KorniltsevAnatoly @pulancheck1988 There is something called `dalvik.system.PathClassLoader` I think that's simliar to `URLClassLoader`. – Powerslave Oct 22 '12 at 12:36
  • I don't know if it is solved yet, but anyways... How about having some host Activity in the application and loading Views or Fragments instead? – Powerslave Feb 25 '13 at 12:55
  • Hi, With the help of fragment you can achieve it very easily. – User10001 Sep 18 '18 at 11:10