Androidダイナミックロードインストールapkのメソッド


Android開発では、ダイナミックロードが必要な場合が多いですが、今日はandroidでインストールされているapkをダイナミックにロードする方法を学びます.
まず、ロードされるandroidプロジェクトを新規作成し、plugprojと名付けます.
plugprojにクラスDynamicを新規作成します.このクラスでは、いくつかのメソッドを新規作成します.このプロジェクトのインストールとインストールなしで、これらのメソッドをそれぞれロードします.Dynamic.JAvaは以下の通りです.
package com.example.plugproj;

import android.app.Activity;
import android.widget.Toast;

public class Dynamic {
	Activity mActivity = null;
	public void init(Activity activity) {
		// TODO Auto-generated method stub
		mActivity = activity;
	}
	public void showDialog() {
		// TODO Auto-generated method stub
		Toast.makeText(mActivity, "show dialog test gaga",Toast.LENGTH_LONG).show();
	}
	public void showWindow() {
		// TODO Auto-generated method stub
		Toast.makeText(mActivity, "show window test gaga",Toast.LENGTH_LONG).show();
	}
	public int addMethod(int a, int b) {
		// TODO Auto-generated method stub
		return a + b;
	}

}
initメソッドでは、toastが実行できるようにcontextオブジェクトを得るためにmActivityに値を割り当てていることがわかります.
ここでは、plugprojプロジェクトの起動activityにactionを構成する必要があります.このactionで対応するパッケージをロードできます.次のようにします.
 <activity
       android:name="com.example.plugproj.MainActivity"
       android:label="@string/app_name" >
       <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="com.haha.android.plugin"/>
        </intent-filter>
 </activity>

プラグインプロジェクトをインストールします.
次に、plugprojをロードする別のプライマリ・エンジニアリングを見てみましょう.プライマリ・コードは次のとおりです.
              //      ,       apk    
		Intent intent = new Intent("com.haha.android.plugin", null);    
		//          
		PackageManager pm = getPackageManager();    
		List<ResolveInfo> resolveinfoes =  pm.queryIntentActivities(intent, 0);    
		//     activity       
		ActivityInfo actInfo = resolveinfoes.get(0).activityInfo;    

		//        
		String pacageName = actInfo.packageName;    
		//  apk     jar       
		String apkPath = actInfo.applicationInfo.sourceDir;    
		//dex      ,  ,          ,android               
		//          
		String dexOutputDir = getApplicationInfo().dataDir;  

		//native         
		String libPath = actInfo.applicationInfo.nativeLibraryDir;  
		//      , dex           
		DexClassLoader calssLoader = new DexClassLoader(apkPath, dexOutputDir, libPath,    
				this.getClass().getClassLoader());   

		try {
			clazz = calssLoader.loadClass(pacageName+".Dynamic");  
			obj = clazz.newInstance();
			Method initMethod = clazz.getDeclaredMethod("init",Activity.class);
			initMethod.invoke(obj,MainActivity.this);

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
は、次に、上記の3つの方法を実行するonclickイベントである.
        @Override
	public void onClick(View arg0) {
		// TODO Auto-generated method stub
		try {
			switch (arg0.getId()) {
			case R.id.id_dialog:
				Method dialogMethod = clazz.getDeclaredMethod("showDialog",null);
				dialogMethod.invoke(obj, null);
				Log.d("Tag","show dialog runs ...");
				break;
			case R.id.id_window:
				Method windowMethod = clazz.getDeclaredMethod("showWindow",null);
				windowMethod.invoke(obj,null);
				Log.d("Tag","show window runs ...");
				break;
			case R.id.id_plus:
				Class[] param = new Class[2];  
	            param[0] = Integer.TYPE;  
	            param[1] = Integer.TYPE; 
				Method method = clazz.getDeclaredMethod("addMethod",param); 
				int result = (Integer) method.invoke(obj, 22,33);
				Toast.makeText(MainActivity.this,"result is :"+result,Toast.LENGTH_SHORT).show();
				Log.d("Tag","add  runs ...");
				break;
			default:
				Toast.makeText(MainActivity.this,"no property id",Toast.LENGTH_LONG).show();
			}
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	} 

これにより、インストールされたapkをロードする方法が実現される.
次に、ロードがjarファイルにパッケージされている方法を見てみましょう.
まずplugprojをjarファイルとしてエクスポートする必要があります.ここではplugprojとしてエクスポートします.JAr、この時のjarファイルはandroid携帯電話で直接ロードできないことに注意して、私たちは彼をdexファイルに変換する必要があります.どのように変換しますか.sdkの下にdxツールがあります.それを使って実現することができます.plugproj.JArはdxファイルを持つディレクトリにコピーされ、一般的にplatform_toolはbuild_にある場合がありますtoolsフォルダの下で、コマンドでファイルの下に入ります.
次のコマンドを実行します.
dx--dex--output最適化されたjar最適化されていないjar
このとき、android携帯電話が直接ロードできる最適化されたjarファイルが生成されます.このjarファイルを携帯電話で指定したディレクトリにコピーします.
キーコードは次のとおりです.
                String path = "/storage/sdcard0/183/mydynamic_help.jar";
		dexPath = getDir("dex", Context.MODE_PRIVATE).getAbsolutePath();
		dexClassLoader = new DexClassLoader(path, dexPath, null, getClassLoader());
		try {
			clazz = dexClassLoader.loadClass("com.example.plugproj.Dynamic");
			try {
				obj = clazz.newInstance();
				Method method = clazz.getDeclaredMethod("init",Activity.class);
				method.invoke(obj, MainActivity.this);
				Log.d("Tag","dynamic init runs ...");
			} catch (InstantiationException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
ボタンバインドonclickイベント:
public void onClick(View arg0) {
// TODO Auto-generated method stub
try {
	switch (arg0.getId()) {
	case R.id.id_dialog:
		Method method = clazz.getDeclaredMethod("showDialog",null);
		method.invoke(obj, null);
		Log.d("Tag","show dialog runs ...");
		break;
	case R.id.id_window:
		method = clazz.getDeclaredMethod("showWindow",null);
		method.invoke(obj, null);
		Log.d("Tag","show window runs ...");
		break;
	case R.id.id_plus:
	<span style="white-space:pre">	</span>Class[]param = new Class[2];
		param[0] = Integer.TYPE;
		param[1] = Integer.TYPE; 
		method = clazz.getDeclaredMethod("addMethod",param);
		int result = (Integer) method.invoke(obj,23,25);
	<span style="white-space:pre">	</span>Toast.makeText(MainActivity.this,"result is :"+result,Toast.LENGTH_SHORT).show();
		Log.d("Tag","add  runs ...");
		break;
	<span style="white-space:pre">	</span>default:
		Toast.makeText(MainActivity.this,"no property id",Toast.LENGTH_LONG).show();
	}
} catch (NoSuchMethodException e) {
	e.printStackTrace();
} catch (IllegalAccessException e) {
	e.printStackTrace();
} catch (IllegalArgumentException e) {
	e.printStackTrace();
} catch (InvocationTargetException e) {
	e.printStackTrace();
}
}
最後に覚えておいてください.sdカードを読み書きする権限を追加します.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

ソースのダウンロード
動的ロードjar