最近在研究Android动态加载APK技术,偶有小得,共享一下,欢迎交流。

首先是Android 动态加载已安装的APK

截图:

被调用工程TestB:

其工程已添加了字符串、颜色和图片资源,这里不写了,读者可自行添加。

[java] view plain copy print ?
  1. publicclassTestBActivityextendsActivity{
  2. /**Calledwhentheactivityisfirstcreated.*/
  3. @Override
  4. publicvoidonCreate(BundlesavedInstanceState){
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.main);
  7. Buttonbutton=(Button)findViewById(R.id.button1);
  8. button.setOnClickListener(newOnClickListener(){
  9. @Override
  10. publicvoidonClick(Viewv){
  11. //TODOAuto-generatedmethodstub
  12. Toast.makeText(TestBActivity.this,"thisistestB",Toast.LENGTH_SHORT).show();
  13. }
  14. });
  15. }
  16. }
public class TestBActivity extends Activity{/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Button button=(Button)findViewById(R.id.button1);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubToast.makeText(TestBActivity.this, "this is testB", Toast.LENGTH_SHORT).show();}});}}

接着把TestB打包为TestB.apk,放到sdcard的根目录。


调用工程TestA:

首先应该是安装apk文件:

[java] view plain copy print ?
  1. protectedvoidInstallAPK(Stringapkname){
  2. //TODOAuto-generatedmethodstub
  3. //代码安装
  4. StringfileName=Environment.getExternalStorageDirectory()+"/"+apkname;
  5. Intentintent=newIntent(Intent.ACTION_VIEW);
  6. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  7. //intent.setDataAndType(Uri.parse("file://"+fileName),"application/vnd.android.package-archive");
  8. intent.setDataAndType(Uri.fromFile(newFile(fileName)),"application/vnd.android.package-archive");
  9. 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是否已安装呢:

[java] view plain copy print ?
  1. protectedbooleancheckInstall(Stringpak){
  2. //TODOAuto-generatedmethodstub
  3. booleaninstall=false;
  4. PackageManagerpm=getPackageManager();
  5. try{
  6. PackageInfoinfo=pm.getPackageInfo(pak,1);
  7. if(info!=null&&info.activities.length>0){
  8. install=true;
  9. }
  10. }catch(NameNotFoundExceptione){
  11. //TODOAuto-generatedcatchblock
  12. e.printStackTrace();
  13. }
  14. returninstall;
  15. }
protected boolean checkInstall(String pak) {// TODO Auto-generated method stubboolean 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 blocke.printStackTrace();}return install;}


如果未安装,便调用InstallAPK(String apkname)安装,如果已安装便可代码获取其资源:

[java] view plain copy print ?
  1. privatevoidgetRes(Stringpak){
  2. if(checkInstall(pak)){
  3. try{
  4. ContextctxTestB=getTestContext(pak);
  5. Resourcesres=ctxTestB.getResources();
  6. //获取字符串string
  7. Stringhello=res.getString(getId("string","hello",pak));
  8. ((TextView)findViewById(R.id.testb_string)).setText(hello);
  9. //获取图片Drawable
  10. Drawabledrawable=res.getDrawable(getId("drawable","testb",pak));
  11. ((ImageView)findViewById(R.id.testb_drawable)).setImageDrawable(drawable);
  12. //获取颜色值
  13. intcolor=res.getColor(getId("color","white",pak));
  14. ((TextView)findViewById(R.id.testb_color)).setBackgroundColor(color);
  15. //获取布局文件
  16. Viewview=getView(ctxTestB,getId("layout","main",pak));
  17. LinearLayoutlayout=(LinearLayout)findViewById(R.id.testb_layout);
  18. layout.addView(view);
  19. }catch(NameNotFoundExceptione){
  20. e.printStackTrace();
  21. }}
  22. }
  23. //获取资源对应的编号
  24. privateintgetId(Stringname,Stringtype,Stringpak){
  25. returntestb.getIdentifier(name,type,pak);
  26. }
  27. //获取视图
  28. publicViewgetView(Contextctx,intid){
  29. return((LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(id,null);
  30. }
  31. //获取TestB的Context
  32. privateContextgetTestContext(Stringpak)throwsNameNotFoundException{
  33. returncreatePackageContext(pak,Context.CONTEXT_IGNORE_SECURITY|Context.CONTEXT_INCLUDE_CODE);
  34. }
private void getRes(String pak){if (checkInstall(pak)) {try {Context ctxTestB = getTestContext(pak);Resources res = ctxTestB.getResources();// 获取字符串stringString hello = res.getString(getId("string", "hello", pak));((TextView) findViewById(R.id.testb_string)).setText(hello);// 获取图片DrawableDrawable 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的Contextprivate Context getTestContext(String pak) throws NameNotFoundException {return createPackageContext(pak,Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);}


接下来再来看看怎么使用Intent组件启动被调用工程:

[java] view plain copy print ?
  1. protectedvoidstartAPK(Stringpak){
  2. //TODOAuto-generatedmethodstub
  3. //代码启动
  4. try{
  5. //pak=PACKAGE_TEST_B+".TestBActivity"
  6. ContextctxTestB=getTestContext(PACKAGE_TEST_B);
  7. Classcls=ctxTestB.getClassLoader().loadClass(pak);
  8. TestAActivity.this.startActivity(newIntent(ctxTestB,cls));
  9. }catch(ClassNotFoundExceptione){
  10. e.printStackTrace();
  11. }catch(NameNotFoundExceptione){
  12. //TODOAuto-generatedcatchblock
  13. e.printStackTrace();
  14. }
  15. }
protected void startAPK(String pak) {// TODO Auto-generated method stub//代码启动try {                       //pak=PACKAGE_TEST_B+".TestBActivity"ContextctxTestB = 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 blocke.printStackTrace();}}


以下为扩展内容:

比如加上网络下载apk文件功能,然后再安装,这里使用的是URL通信协议,用HttpURLConnection类,面向的是应用层:

[java] view plain copy print ?
  1. protectedFiledownLoadFile(StringhttpUrl){
  2. //TODOAuto-generatedmethodstub
  3. Stringfilename="down_TestB.apk";
  4. Filefile=newFile(Environment.getExternalStorageDirectory()+"/"+filename);
  5. try{
  6. URLurl=newURL(httpUrl);
  7. try{
  8. HttpURLConnectionconn=(HttpURLConnection)url
  9. .openConnection();
  10. InputStreamis=conn.getInputStream();
  11. FileOutputStreamfos=newFileOutputStream(file);
  12. byte[]buf=newbyte[256];
  13. conn.connect();
  14. intcount=0;
  15. if(conn.getResponseCode()==200){
  16. while((count=is.read(buf))>0){
  17. fos.write(buf,0,count);
  18. }
  19. }
  20. conn.disconnect();
  21. fos.close();
  22. is.close();
  23. }catch(IOExceptione){
  24. //TODOAuto-generatedcatchblock
  25. e.printStackTrace();
  26. }
  27. }catch(MalformedURLExceptione){
  28. //TODOAuto-generatedcatchblock
  29. e.printStackTrace();
  30. }
  31. returnfile;
  32. }
protected File downLoadFile(String httpUrl) {                // TODO Auto-generated method stubString 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

更多相关文章

  1. 解决新建Android工程时自动生成appcompat_v7
  2. Android 利用JNI调用Android Java代码函数
  3. Android浮动窗口实现原理及代码实例
  4. Unable to resolve target 'android-18' android导入工程报错
  5. ubuntu下载android源代码
  6. Android 权限控制代码分析
  7. android 高级工程师成长之路(Android高手应该精通哪些内容?)

随机推荐

  1. Spark join种类(>3种)及join选择依据
  2. java培训班多久能学会的?
  3. 尝尝鲜|Spark 3.1自适应执行计划
  4. 使用Rust编写推箱子游戏基础篇
  5. java实操|mysql数据增量同步到kafka
  6. spark on yarn 内存分配详解
  7. 前端培训班出来的不会写项目怎么办?
  8. find和grep
  9. IP地址分类及网络配置方法和多网卡绑定技
  10. 拨开零售电商数字化转型迷雾,电商RPA应用