Is it possible to dynamically load a library at runtime from an Android application?
Sorry, I'm late and the question has already an accepted answer, but yes, you can download and execute external libraries. Here is the way I did:
I was wondering whether this was feasible so I wrote the following class:
package org.shlublu.android.sandbox;
import android.util.Log;
public class MyClass {
public MyClass() {
Log.d(MyClass.class.getName(), "MyClass: constructor called.");
}
public void doSomething() {
Log.d(MyClass.class.getName(), "MyClass: doSomething() called.");
}
}
And I packaged it in a DEX file that I saved on my device's SD card as /sdcard/shlublu.jar
.
Then I wrote the "stupid program" below, after having removed MyClass
from my Eclipse project and cleaned it:
public class Main extends Activity {
@SuppressWarnings("unchecked")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
final String libPath = Environment.getExternalStorageDirectory() + "/shlublu.jar";
final File tmpDir = getDir("dex", 0);
final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getAbsolutePath(), null, this.getClass().getClassLoader());
final Class<Object> classToLoad = (Class<Object>) classloader.loadClass("org.shlublu.android.sandbox.MyClass");
final Object myInstance = classToLoad.newInstance();
final Method doSomething = classToLoad.getMethod("doSomething");
doSomething.invoke(myInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
It basically loads the class MyClass
that way:
create a
DexClassLoader
use it to extract the class
MyClass
from"/sdcard/shlublu.jar"
and store this class to the application's
"dex"
private directory (internal storage of the phone).
Then, it creates an instance of MyClass
and invokes doSomething()
on the created instance.
And it works... I see the traces defined in MyClass
in my LogCat:
I've tried on both an emulator 2.1 and on my physical HTC cellphone (which is running Android 2.2 and which is NOT rooted).
This means you can create external DEX files for the application to download and execute them. Here it was made the hard way (ugly Object
casts, Method.invoke()
ugly calls...), but it must be possible to play with Interface
s to make something cleaner.
Wow. I'm the first surprised. I was expecting a SecurityException
.
Some facts to help investigating more:
- My DEX shlublu.jar was signed, but not my app
- My app was executed from Eclipse / USB connection. So this is an unsigned APK compiled in DEBUG mode
How to dynamically load a compiled native library into an Android application?
In some sense, your task is trivial. Java defines System.load()
which should work as
System.load("/tmp/libhello_world.so");
Unlike loadLibrary()
, here you specify the path explicitly, and the name is not required to start with lib
and end with .so
. Still the system may impose other restrictions on the path from which a library can be loaded. E.g. you cannot load a library from external storage, i.e. /sdcard
. Only system apps have permission to load libraries from /system/libs
(except the few whitelisted libraries).
But, as @CommonsWare explained in his comment, the requirements of Google Play Store and other established app distribution channels do not allow loading libraries or otherwise executing binaries that don't come from their (Google Play, etc.) secured channels.
As for jniLinbs
folder, this is not the only way to inject native libs into an APK or bundle. There are different ways to force gradle to add some files to the libs
section, so that the app on device will be able to load these with System.load()
.
How to add a dynamic library to Android?
Recent post on the Android blog explains exactly what I needed:
The Dalvik VM provides facilities for developers to perform custom class loading. Instead of loading Dalvik executable (“dex”) files from the default location, an application can load them from alternative locations such as internal storage or over the network.
The key is to use DexClassLoader to load the needed library. After that the code can be accessed either through interfaces, or by using reflection.
How to achieve Dynamic code Loading in Android?
It sounds like you need look at Feature Delivery.
Related Topics
How to Add a Border to the Top and Bottom of an Android View
Android Youtube App Play Video Intent
Check If Application Is on Its First Run
Android View.Getdrawingcache Returns Null, Only Null
Error Inflating Class Fragment
Outofmemoryerror: Bitmap Size Exceeds Vm Budget :- Android
How to Disable Landscape Mode in Android
How to Dynamically Update a Listview on Android
How to Resume Existing Fragment from Backstack
How to Save Recyclerview'S Scroll Position Using Recyclerview.State
Using Intent in an Android Application to Show Another Activity
How to Use Jni Bitmap Operations for Helping to Avoid Oom When Using Large Images
Difference Between App:Srccompat and Android:Src in Android's Layout Xml
Android Read Text Raw Resource File