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

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

截图:

被调用工程TestB:

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

[java] view plain copy
  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. }

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


调用工程TestA:

首先应该是安装apk文件:

[java] view plain copy
  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);


但是安装之前是不是要先检测一下TestB.apk是否已安装呢:

[java] view plain copy
  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. }


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

[java] view plain copy
  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. }

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

[java] view plain copy
  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. }


以下为扩展内容:

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

[java] view plain copy
  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. }

更多相关文章

  1. Android实践 -- Android文件储存系统 应用篇
  2. Android添加资源文件编译,R文件未重新生成解决办法
  3. 1.4.2 Android Studio工程目录结构分析
  4. 转 Android:文件下载和写入SD卡学习小结
  5. Android 之如何添加 android private libraries 中的包的源代码
  6. android下快速检索出媒体文件所在文件夹
  7. Android 7.0 之后抓包 unknown 和证书无效的解决方案(无需改代码)
  8. Android RIL代码详细分析

随机推荐

  1. Android中使用tint属性和backgroundTint
  2. Android开发学习之Xml解析归纳
  3. ANDROID JNI之JAVA域与c域的互操作
  4. iOS还是Android?我应该选哪个平台来做应用
  5. VisionMobile:移动平台生态系统冲突报告(
  6. Android开发面试经——5.常见面试官提问A
  7. Android连接Tomcat服务器
  8. Android BSP成长计划随笔之虚拟设备搭建
  9. Android studio中正确引入so文件的方法
  10. android H5 应用内跳转Scheme协议