編輯:關於Android編程
Android中apk文件裡的dex文件是對java編譯出來的.class文件進行重新打包,當然在打包之前會利用自己的協議做一些數據處理,例如優化函數表和變量表。在java程序中是使用classloader來加載這些編譯生成的.class文件,然而在android程序中是通過DexClassLoader來裝載這些文件的.這裡我們就可以通過DexClassLoader在程序A裡面動態裝載程序B中的類,並且來調用B程序中的方法.
1.首先先建立一個普通的Android工程,在這個工程中定義一個叫做plugin的類,類中實現一個簡單的方法,如下所示:
public class PluginClass {
private static String TAG = PluginClass.class.getSimpleName();
public PluginClass(){
Log.i(TAG, "initialized");
}
public void invoke(String s){
Log.i(TAG, s);
}
} 2.將這個Android工程運行到安卓設備當中去3.再重新建立一個Android工程,其中定義一個叫做host的類,在這個類中實現DexClassLoader動態加載第一個工程中的plugin類,如下所示:
public class HostClass {
private static String TAG = HostClass.class.getSimpleName();
private Context mContext = null;
public HostClass(Context contect){
mContext = contect;
}
public void useDexClassLoader(){
Intent intent = new Intent();
intent.setPackage("com.example.plugin");
PackageManager pm = mContext.getPackageManager();
final List plugins = pm.queryIntentActivities(intent,0);
if(plugins.size() <= 0){
Log.i(TAG, "resolve info size is:" + plugins.size());
return;
}
ResolveInfo resolveInfo = plugins.get(0);
ActivityInfo activityInfo = resolveInfo.activityInfo;
String div = System.getProperty("path.separator");
String packageName = activityInfo.packageName;
String dexPath = activityInfo.applicationInfo.sourceDir;
//目標類所在的apk或者jar的路徑,class loader會通過這個路徑來加載目標類文件
String dexOutputDir = mContext.getApplicationInfo().dataDir;
//由於dex文件是包含在apk或者jar文件中的,所以在加載class之前就需要先將dex文件解壓出來,dexOutputDir為解壓路徑
String libPath = activityInfo.applicationInfo.nativeLibraryDir;
//目標類可能使用的c或者c++的庫文件的存放路徑
Log.i(TAG, "div:" + div + " " +
"packageName:" + packageName + " " +
"dexPath:" + dexPath + " " +
"dexOutputDir:" + dexOutputDir + " " +
"libPath:" + libPath);
DexClassLoader dcLoader = new DexClassLoader(dexPath,dexOutputDir,libPath,this.getClass().getClassLoader());
try {
Class> clazz = dcLoader.loadClass(packageName + ".PluginClass");
Object obj = clazz.newInstance();
Class[] param = new Class[1];
param[0] = String.class;
Method action = clazz.getMethod("invoke", param);
action.invoke(obj, "test this function");
} catch (ClassNotFoundException e) {
Log.i(TAG, "ClassNotFoundException");
} catch (InstantiationException e) {
Log.i(TAG, "InstantiationException");
} catch (IllegalAccessException e) {
Log.i(TAG, "IllegalAccessException");
} catch (NoSuchMethodException e) {
Log.i(TAG, "NoSuchMethodException");
} catch (IllegalArgumentException e) {
Log.i(TAG, "IllegalArgumentException");
} catch (InvocationTargetException e) {
Log.i(TAG, "InvocationTargetException");
}
}
} 4.運行第二個工程之後查看log就會發現host通過DexClassLoader加載了pluginclass類,並成功調用了plugin中的方法I/HostClass( 8341): div:: packageName:com.example.plugin dexPath:/data/app/com.example.plugin-1.apk dexOutputDir:/data/data/com.example.host libPath:/data/app-lib/com.example.plugin-1 D/dalvikvm( 8341): DexOpt: --- BEGIN 'com.example.plugin-1.apk' (bootstrap=0) --- D/dalvikvm( 8341): DexOpt: --- END 'com.example.plugin-1.apk' (success) --- D/dalvikvm( 8341): DEX prep '/data/app/com.example.plugin-1.apk': unzip in 39ms, rewrite 723ms I/PluginClass( 8341): initialized I/PluginClass( 8341): test this function D/libEGL ( 8341): loaded /system/lib/egl/libEGL_mali.so D/libEGL ( 8341): loaded /system/lib/egl/libGLESv1_CM_mali.so D/libEGL ( 8341): loaded /system/lib/egl/libGLESv2_mali.so D/OpenGLRenderer( 8341): Enabling debug mode 0 I/HostClass( 8341): div:: packageName:com.example.plugin dexPath:/data/app/com.example.plugin-1.apk dexOutputDir:/data/data/com.example.host libPath:/data/app-lib/com.example.plugin-1 I/PluginClass( 8341): initialized I/PluginClass( 8341): test this function
teamviewer遠程控制 用Android手機遠程控制你的電腦
TeamViewer 是一個在任何防火牆和NAT代理的後台用於遠程控制 ,桌面共享和文件傳輸的簡單且快速的解決方案。為了連接到另一台計算機,只需要在兩台計算
Android ActivityManagerService(AMS)的進程管理
Android中的AMS的職責是比較多的,其中一個比較重要的職責就是app進程的管理,比如我們調用startActivity方法啟動一個activity的時候,可能對應的
Android 動態菜單實現實例代碼
Android 動態菜單先上效果圖比較簡單,主要就是屬性動畫的使用和坐標角度的小細節。實現實現效果: 圖標按照路徑一路縮放漸變過來即可。核心代碼 /** * Item
Android最佳實踐之UI
為多屏設計(一) - 支持多個屏幕尺寸參考地址:http://developer.android.com/training/multiscreen/index.htmlA