`
kalogen
  • 浏览: 880252 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Android 动态加载APK--代码安装、获取资源及Intent调用已安装apk .

 
阅读更多

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

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

截图:

被调用工程TestB:

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

 

  1. public class TestBActivity extends Activity{  
  2.     /** Called when the activity is first created. */  
  3.     @Override  
  4.     public void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.main);  
  7.         Button button=(Button)findViewById(R.id.button1);  
  8.         button.setOnClickListener(new OnClickListener() {  
  9.               
  10.             @Override  
  11.             public void onClick(View v) {  
  12.                 // TODO Auto-generated method stub   
  13.                 Toast.makeText(TestBActivity.this"this is testB", Toast.LENGTH_SHORT).show();  
  14.             }  
  15.         });  
  16.     }  
  17. }  
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文件:

 

  1. protected void InstallAPK(String apkname) {  
  2.         // TODO Auto-generated method stub   
  3.   
  4.         //代码安装   
  5.         String fileName = Environment.getExternalStorageDirectory() + "/"+apkname;   
  6.         Intent intent = new Intent(Intent.ACTION_VIEW);   
  7.         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  8. //       intent.setDataAndType(Uri.parse("file://"+fileName), "application/vnd.android.package-archive");    
  9.          intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");   
  10.         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是否已安装呢:

 

 

  1. protected boolean checkInstall(String pak) {  
  2.     // TODO Auto-generated method stub   
  3.     boolean install=false;  
  4.     PackageManager pm=getPackageManager();  
  5.     try {  
  6.         PackageInfo info=pm.getPackageInfo(pak,1);  
  7.         if (info!=null&&info.activities.length>0) {  
  8.             install=true;  
  9.         }  
  10.     } catch (NameNotFoundException e) {  
  11.         // TODO Auto-generated catch block   
  12.         e.printStackTrace();  
  13.     }  
  14.     return install;  
  15. }  
	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)安装,如果已安装便可代码获取其资源:

 

 

  1. private void getRes(String pak){  
  2.     if (checkInstall(pak)) {  
  3.     try {  
  4.   
  5.             Context ctxTestB = getTestContext(pak);  
  6.             Resources res = ctxTestB.getResources();  
  7.             // 获取字符串string   
  8.             String hello = res.getString(getId("string""hello", pak));  
  9.             ((TextView) findViewById(R.id.testb_string)).setText(hello);  
  10.               
  11.             // 获取图片Drawable   
  12.             Drawable drawable = res.getDrawable(getId("drawable""testb",pak));  
  13.             ((ImageView) findViewById(R.id.testb_drawable)).setImageDrawable(drawable);  
  14.               
  15.             // 获取颜色值   
  16.             int color = res.getColor(getId("color""white",pak));  
  17.             ((TextView) findViewById(R.id.testb_color)).setBackgroundColor(color);  
  18.               
  19.             // 获取布局文件   
  20.             View view = getView(ctxTestB, getId("layout""main",pak));  
  21.             LinearLayout layout = (LinearLayout) findViewById(R.id.testb_layout);  
  22.             layout.addView(view);  
  23.   
  24.     } catch (NameNotFoundException e) {  
  25.     e.printStackTrace();  
  26. }}  
  27. }  
  28.  //获取资源对应的编号   
  29. private int getId(String name, String type,String pak) {  
  30.     return testb.getIdentifier(name, type, pak);  
  31. }  
  32.   
  33.   
  34.  // 获取视图   
  35. public View getView(Context ctx, int id) {  
  36.     return ((LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(id,null);  
  37. }  
  38.   
  39.   
  40.  //获取TestB的Context   
  41. private Context getTestContext(String pak) throws NameNotFoundException {  
  42.     return createPackageContext(pak,Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);  
  43. }  
	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组件启动被调用工程:

 

 

  1. protected void startAPK(String pak) {  
  2.     // TODO Auto-generated method stub   
  3.   
  4.     //代码启动   
  5.     try {  
  6.                       //pak=PACKAGE_TEST_B+".TestBActivity"   
  7.         Context ctxTestB = getTestContext(PACKAGE_TEST_B);  
  8.         Class cls = ctxTestB.getClassLoader().loadClass(pak);  
  9.         TestAActivity.this.startActivity(new Intent(ctxTestB, cls));  
  10.     } catch (ClassNotFoundException e) {  
  11.         e.printStackTrace();  
  12.     } catch (NameNotFoundException e) {  
  13.         // TODO Auto-generated catch block   
  14.         e.printStackTrace();  
  15.     }  
  16. }  
	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类,面向的是应用层:

 

  1. protected File downLoadFile(String httpUrl) {  
  2.                     // TODO Auto-generated method stub   
  3.         String filename="down_TestB.apk";  
  4.         File file=new File(Environment.getExternalStorageDirectory() + "/"+filename);  
  5.   
  6.                     try {  
  7.                             URL url = new URL(httpUrl);  
  8.                             try {  
  9.                                     HttpURLConnection conn = (HttpURLConnection) url  
  10.                                                     .openConnection();  
  11.                                     InputStream is = conn.getInputStream();  
  12.                                     FileOutputStream fos = new FileOutputStream(file);  
  13.                                     byte[] buf = new byte[256];  
  14.                                     conn.connect();  
  15.                                     int count = 0;  
  16.                                     if (conn.getResponseCode()==200) {  
  17.                                            while ((count=is.read(buf))>0) {  
  18.                                               
  19.                                                fos.write(buf, 0, count);  
  20.                                         }  
  21.                                     }  
  22.   
  23.                                     conn.disconnect();  
  24.                                     fos.close();  
  25.                                     is.close();  
  26.                             } catch (IOException e) {  
  27.                                     // TODO Auto-generated catch block   
  28.   
  29.                                     e.printStackTrace();  
  30.                             }  
  31.                     } catch (MalformedURLException e) {  
  32.                             // TODO Auto-generated catch block   
  33.   
  34.                             e.printStackTrace();  
  35.                     }  
  36.   
  37.                     return file;  
  38.             }  
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

分享到:
评论

相关推荐

    android 实现用代码安装apk

    首先,获取APK文件的路径,然后使用`Intent`和`PackageInstaller`来完成安装过程。以下是一个示例函数: ```java public void installApk(Context context, String apkFilePath) { if (Build.VERSION.SDK_INT >=...

    Android动态加载未安装apk

    在Android开发中,有时我们需要实现一个功能,即在运行时动态加载未安装的APK文件。这主要应用于插件化开发、热更新或者模块化的应用架构。动态加载未安装的APK可以让应用在不更新主应用程序的情况下添加或更新功能...

    1个apk安装另一个apk,安装多个apk

    - 对于动态加载APK的情况,考虑使用动态插件框架,如DexClassLoader,它可以在运行时加载和执行新的类库。 以上就是如何在一个APK中安装另一个或多个APK的基本步骤。这个过程需要对Android的安装机制有深入理解,...

    Android 下载APK 安装APK 打开APK

    2. 构建Intent:使用ACTION_VIEW Intent,并设置数据URI指向下载的APK文件,同时设置MIME类型为"application/vnd.android.package-archive"。 3. 启动安装:通过调用startActivityForResult()方法,启动系统的安装...

    Android无需root实现apk的静默安装

    Android的静默安装似乎是一个很有趣很诱人的东西,但是,用普通做法,如果手机没有root权限的话,似乎很难实现静默安装,因为Android并不提供显示的Intent调用,一般是通过以下方式安装apk: Intent intent = new ...

    android两个APK相互调用并传参数

    在两个APK间调用时,如果知道被调用APK的Activity完全限定类名(包括包名),可以直接创建一个显式Intent。例如: ```java Intent intent = new Intent(); intent.setComponent(new ComponentName(...

    安卓安装卸载相关-Android程序无需Root可以安装APK.rar

    开发者可以创建一个启动器应用,该应用接收到安装Intent后,调用系统的安装服务来安装APK。 5. **系统签名**:如果能够获取设备的系统签名密钥,可以对APK进行签名,使其看起来像是系统应用。这样,即使在非Root...

    android 系统调用安装apk

    根据给定文件的标题、描述以及部分内容,我们可以深入探讨两种主要的系统调用安装APK的方法及其相关知识点。 ### 方法一:使用Intent进行安装 这种方法是通过创建一个`Intent`对象,并设置其动作为`ACTION_VIEW`来...

    Android 自动安装apk

    我们可以创建一个隐式Intent,指定ACTION_VIEW和MIME类型为`application/vnd.android.package-archive`,然后传递APK的文件路径作为数据源。这样,系统就会启动安装程序来处理这个Intent。 ```java Intent ...

    android 安装本地apk

    在代码中,我们可以调用`installPackage()`方法,传入APK文件的路径来执行安装操作。例如: ```java Intent installIntent = new Intent(Intent.ACTION_VIEW); installIntent.setDataAndType(Uri.fromFile(new File...

    apk-A启动到apk—B

    在Android开发中,"apk-A启动到apk-B"是一个常见的应用场景,类似于淘宝应用启动支付宝这样的功能,这涉及到跨应用通信和Intent机制。本文将详细解析这个过程中的关键知识点。 首先,`apk-A` 和 `apk-B` 分别代表两...

    Android 通过反射启动未安装的APK中的Activity

    6. **处理权限和安全**:启动未安装的APK的Activity涉及到安全问题,因为这可能导致恶意代码执行。因此,在实际操作中,应确保有足够的权限控制,并对加载的类进行验证,防止潜在的风险。 7. **Intent构造**:构建...

    Android无需Root静默安装apk

    在本文中,我们将探讨如何在不获取Android设备Root权限的情况下实现静默安装APK。 静默安装APK的方法主要分为两种:通过Adb(Android Debug Bridge)和通过自定义服务。Adb是Android开发工具包中的一个重要组成部分...

    Android-自动下载fir.im上的apk

    在Android开发领域,为了方便测试和分发应用,有许多第三方平台提供APK的上传和下载服务,其中fir.im是一个颇受欢迎的平台。本项目“Android-自动下载fir.im上的apk”旨在解决开发者从fir.im手动下载APK的繁琐过程,...

    Unity调用Android安装APK以及重启,7.0及其以上

    在Unity引擎中调用Android设备进行APK安装并实现应用自动重启是一项常见的跨平台功能需求。这个场景通常出现在游戏或应用的更新过程中,用户在Unity游戏中点击更新按钮,然后Unity会调用Android系统API来安装新的APK...

    Android一个apk启动另外一个apk

    在Android平台上,一个APK应用启动另一个APK应用是一个常见的需求,这可能涉及到应用之间的交互、服务调用或者用户引导到不同的应用体验。这个过程主要依赖于Android的Intent机制,Intent是Android系统中用于组件间...

    android 下载并安装apk的代码

    当下载完成后,`DownloadReceiver`会接收到`ACTION_DOWNLOAD_COMPLETE`广播,然后调用`installApk`方法启动安装流程。 安装APK时,需要检查并请求`INSTALL_EXTERNAL_STORAGE`权限(Android 10及以上)或`WRITE_...

    Android代码-soot-infoflow-android

    【Android代码-soot-infoflow-android】是一个针对Android应用程序的安全分析工具包,主要基于Soot框架和InfoFlow算法。Soot是一个强大的Java优化框架,而InfoFlow则是用于静态数据流分析,特别是关注信息泄露和隐私...

    Android应用程序apk安装器程序

    2. 安装逻辑:这部分代码负责解析APK文件,调用Android系统的安装API(如`PackageInstaller`)来执行安装过程。 3. 用户界面:提供简洁的界面,展示APK信息,以及开始安装的按钮。 4. 权限处理:由于安装应用需要...

    android应用下载安装apk升级版本实现demo适配Android10

    本示例“android应用下载安装apk升级版本实现demo适配Android10”聚焦于如何在Android 10(API级别29)及更高版本中实现这一过程。以下是关于这一主题的详细知识: 1. **安全下载APK**:在Android 10中,为了保障...

Global site tag (gtag.js) - Google Analytics