Существует два трюка для создания библиотеки динамической загрузки в Android
используйте sharedUserId
в AndroidManifest для ваших приложений и проекта библиотеки
используйте dalvik.system.DexClassLoader
для загрузки библиотеки
Код библиотеки:
Он содержит только код Java без особых точек входа для Android. AndroidManifest.xml просто содержит этот android:sharedUserId
атрибут
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testlib"
android:sharedUserId="com.example.testlib"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" />
<application android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@style/AppTheme">
</application>
</manifest>
TestCore.java
package com.example.testlib;
public class TestCore implements ITestCore{
private int count = 0;
public String testString(String arg) {
String res = arg + " " + count;
count++;
return res;
}
}
Пример кода приложения
Приложение, которое использует библиотеку. Вот только AndroidManifest.xml и TestApplication.java, которые делают свое дело. Все остальные сотрудники, работающие с приложениями, работают как обычно.
AndroidManifest.xml
Будьте осторожны, чтобы использовать то же значение android: sharedUserId в AndroidManifest.xml как библиотечное
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testapp"
android:sharedUserId="com.example.testlib"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name=".TestApplication" >
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="android.app.Activity" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
</manifest>
ITestCore.java
Интерфейс библиотеки должен быть объявлен в приложении, чтобы избежать использования отражения
package com.example.testlib;
public interface ITestCore {
String testString(String arg);
}
TestApplication.java
В обработчике applicationCreate приложения происходит реальная работа
package com.example.testapp;
import com.example.testlib.ITestCore;
import dalvik.system.DexClassLoader;
import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.util.Log;
public class TestApplication extends Application {
ClassLoader libClassLoader;
@Override
public void onCreate() {
PackageManager pm = getPackageManager();
String libSrcPath = null;
for (ApplicationInfo app : pm.getInstalledApplications(0)) {
if (app.packageName.equals("com.rhomobile.testlibrary")) {
libSrcPath = app.sourceDir;
Log.d("TestApplication", ">>>>>>>>>>>>>>> package: " + app.packageName + ", sourceDir: " + app.sourceDir);
}
}
try {
libClassLoader = new DexClassLoader(libSrcPath, getDir("dex", 0).getAbsolutePath(), null, getClassLoader());
Class<?> clazz = libClassLoader.loadClass("com.rhomobile.testlib.TestCore");
try {
ITestCore core = (ITestCore)clazz.newInstance();
String str = core.testString("TestApplication 1:");
Log.i("TestApplication", ">>>>>>>>>>>>>>> output: " + str);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
Log.e("TestApplication", libClassLoader.toString());
e.printStackTrace();
}
}
}