編輯:關於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 List4.運行第二個工程之後查看log就會發現host通過DexClassLoader加載了pluginclass類,並成功調用了plugin中的方法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"); } } }
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 是一個在任何防火牆和NAT代理的後台用於遠程控制 ,桌面共享和文件傳輸的簡單且快速的解決方案。為了連接到另一台計算機,只需要在兩台計算
Android中的AMS的職責是比較多的,其中一個比較重要的職責就是app進程的管理,比如我們調用startActivity方法啟動一個activity的時候,可能對應的
Android 動態菜單先上效果圖比較簡單,主要就是屬性動畫的使用和坐標角度的小細節。實現實現效果: 圖標按照路徑一路縮放漸變過來即可。核心代碼 /** * Item
為多屏設計(一) - 支持多個屏幕尺寸參考地址:http://developer.android.com/training/multiscreen/index.htmlA