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

相关推荐