Android 动态加载APK--代码安装、获取资源及Intent调用已安装apk .
最近在研究Android动态加载APK技术,偶有小得,共享一下,欢迎交流。
首先是Android 动态加载已安装的APK
截图:
被调用工程TestB:
其工程已添加了字符串、颜色和图片资源,这里不写了,读者可自行添加。
public class TestBActivity extends Activity{ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button=(Button)findViewById(R.id.button1); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(TestBActivity.this, "this is testB", Toast.LENGTH_SHORT).show(); } }); } }
public class TestBActivity extends Activity{ /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button button=(Button)findViewById(R.id.button1); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(TestBActivity.this, "this is testB", Toast.LENGTH_SHORT).show(); } }); } }
接着把TestB打包为TestB.apk,放到sdcard的根目录。
调用工程TestA:
首先应该是安装apk文件:
protected void InstallAPK(String apkname) { // TODO Auto-generated method stub //代码安装 String fileName = Environment.getExternalStorageDirectory() + "/"+apkname; Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // intent.setDataAndType(Uri.parse("file://"+fileName), "application/vnd.android.package-archive"); intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive"); TestAActivity.this.startActivityForResult(intent, 1);
protected void InstallAPK(String apkname) { // TODO Auto-generated method stub //代码安装 String fileName = Environment.getExternalStorageDirectory() + "/"+apkname; Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // intent.setDataAndType(Uri.parse("file://"+fileName), "application/vnd.android.package-archive"); intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive"); TestAActivity.this.startActivityForResult(intent, 1);
但是安装之前是不是要先检测一下TestB.apk是否已安装呢:
protected boolean checkInstall(String pak) { // TODO Auto-generated method stub boolean install=false; PackageManager pm=getPackageManager(); try { PackageInfo info=pm.getPackageInfo(pak,1); if (info!=null&&info.activities.length>0) { install=true; } } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return install; }
protected boolean checkInstall(String pak) { // TODO Auto-generated method stub boolean install=false; PackageManager pm=getPackageManager(); try { PackageInfo info=pm.getPackageInfo(pak,1); if (info!=null&&info.activities.length>0) { install=true; } } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return install; }
如果未安装,便调用InstallAPK(String apkname)安装,如果已安装便可代码获取其资源:
private void getRes(String pak){ if (checkInstall(pak)) { try { Context ctxTestB = getTestContext(pak); Resources res = ctxTestB.getResources(); // 获取字符串string String hello = res.getString(getId("string", "hello", pak)); ((TextView) findViewById(R.id.testb_string)).setText(hello); // 获取图片Drawable Drawable drawable = res.getDrawable(getId("drawable", "testb",pak)); ((ImageView) findViewById(R.id.testb_drawable)).setImageDrawable(drawable); // 获取颜色值 int color = res.getColor(getId("color", "white",pak)); ((TextView) findViewById(R.id.testb_color)).setBackgroundColor(color); // 获取布局文件 View view = getView(ctxTestB, getId("layout", "main",pak)); LinearLayout layout = (LinearLayout) findViewById(R.id.testb_layout); layout.addView(view); } catch (NameNotFoundException e) { e.printStackTrace(); }} } //获取资源对应的编号 private int getId(String name, String type,String pak) { return testb.getIdentifier(name, type, pak); } // 获取视图 public View getView(Context ctx, int id) { return ((LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(id,null); } //获取TestB的Context private Context getTestContext(String pak) throws NameNotFoundException { return createPackageContext(pak,Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE); }
private void getRes(String pak){ if (checkInstall(pak)) { try { Context ctxTestB = getTestContext(pak); Resources res = ctxTestB.getResources(); // 获取字符串string String hello = res.getString(getId("string", "hello", pak)); ((TextView) findViewById(R.id.testb_string)).setText(hello); // 获取图片Drawable Drawable drawable = res.getDrawable(getId("drawable", "testb",pak)); ((ImageView) findViewById(R.id.testb_drawable)).setImageDrawable(drawable); // 获取颜色值 int color = res.getColor(getId("color", "white",pak)); ((TextView) findViewById(R.id.testb_color)).setBackgroundColor(color); // 获取布局文件 View view = getView(ctxTestB, getId("layout", "main",pak)); LinearLayout layout = (LinearLayout) findViewById(R.id.testb_layout); layout.addView(view); } catch (NameNotFoundException e) { e.printStackTrace(); }} } //获取资源对应的编号 private int getId(String name, String type,String pak) { return testb.getIdentifier(name, type, pak); } // 获取视图 public View getView(Context ctx, int id) { return ((LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(id,null); } //获取TestB的Context private Context getTestContext(String pak) throws NameNotFoundException { return createPackageContext(pak,Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE); }
接下来再来看看怎么使用Intent组件启动被调用工程:
protected void startAPK(String pak) { // TODO Auto-generated method stub //代码启动 try { //pak=PACKAGE_TEST_B+".TestBActivity" Context ctxTestB = getTestContext(PACKAGE_TEST_B); Class cls = ctxTestB.getClassLoader().loadClass(pak); TestAActivity.this.startActivity(new Intent(ctxTestB, cls)); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
protected void startAPK(String pak) { // TODO Auto-generated method stub //代码启动 try { //pak=PACKAGE_TEST_B+".TestBActivity" Context ctxTestB = getTestContext(PACKAGE_TEST_B); Class cls = ctxTestB.getClassLoader().loadClass(pak); TestAActivity.this.startActivity(new Intent(ctxTestB, cls)); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NameNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
以下为扩展内容:
比如加上网络下载apk文件功能,然后再安装,这里使用的是URL通信协议,用HttpURLConnection类,面向的是应用层:
protected File downLoadFile(String httpUrl) { // TODO Auto-generated method stub String filename="down_TestB.apk"; File file=new File(Environment.getExternalStorageDirectory() + "/"+filename); try { URL url = new URL(httpUrl); try { HttpURLConnection conn = (HttpURLConnection) url .openConnection(); InputStream is = conn.getInputStream(); FileOutputStream fos = new FileOutputStream(file); byte[] buf = new byte[256]; conn.connect(); int count = 0; if (conn.getResponseCode()==200) { while ((count=is.read(buf))>0) { fos.write(buf, 0, count); } } conn.disconnect(); fos.close(); is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return file; }
protected File downLoadFile(String httpUrl) { // TODO Auto-generated method stub String filename="down_TestB.apk"; File file=new File(Environment.getExternalStorageDirectory() + "/"+filename); try { URL url = new URL(httpUrl); try { HttpURLConnection conn = (HttpURLConnection) url .openConnection(); InputStream is = conn.getInputStream(); FileOutputStream fos = new FileOutputStream(file); byte[] buf = new byte[256]; conn.connect(); int count = 0; if (conn.getResponseCode()==200) { while ((count=is.read(buf))>0) { fos.write(buf, 0, count); } } conn.disconnect(); fos.close(); is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return file; }
此工程还可扩展,比如获取未安装apk或者已安装apk的版本、图标等资源,和已安装的apk进行版本比较,以确定是否要升级新版本。关于此可以看下我的另一篇博文《Android获取未安装和已安装apk的版本、图标等资源》。
Ok,到此结束,本人QQ:957411207,欢迎交流。
原文地址:http://blog.csdn.net/zhang957411207/article/details/7581070
相关推荐
yangChong 2020-08-03
zyygive 2020-07-29
yangChong 2020-07-29
绿豆饼 2020-07-28
adb shell cd system/app rm *.apk21. 获取管理员权限: adb root22. 启动Activity: adb shell am start -n 包名/包名+类名。
蓝天梦 2020-07-28
rookieding 2020-07-26
zyygive 2020-06-11
zyygive 2020-06-09
安辉 2020-05-27
KarlMarxs 2020-05-15
xilove0 2020-04-20
laijunfeng 2020-04-07
KarlMarxs 2020-02-23
Soinice 2020-02-18
zyygive 2020-02-17
ProgrammerFan00 2020-02-16
Ubuntu黑客 2020-02-14
89590098 2020-02-01