代码中执行apk静默安装

代码中执行apk静默安装

背景:

应用需要升级来添加一些功能,但是需求是静默升级,也就是不需要用户直接去操作.

方法总结:

开始在网上看了一下资料,测试成功之后整理了一下相关修改.实现当前的需求是需要应用用的是当前的签名.
 

如何获取权限和修改未平台签名:

1、首先,我们要做的就是从Android的系统源码的/build/target/product/security目录中,找到两个签名文件: platform.x509.pem和platform.pk8
 
2、在/build/tools/signapk目录下找到signapk.jar文件的源码,编译成signapk.jar文件
 
3、然后在Android项目的manifest.xml文件中,加上INSTALL_PACKAGES的权限。
 
4、导出apk文件,这里选择签名文件导出。右键项目->"Android Tools"->"Export Signed application Package..."
 
5、最后就是执行
java -jar signapk.jar platform.x509.pem platform.pk8 input.apk output.apk
 

方法1:调用PackageManager 的installPackage()方法

代码修改:
这里使用的PackageManager 的installPackage()方法.由于这个方法不是标准的Android公开的API,所以我们要调用需要把Android 编译出的framework.jar 导入到eclipse 工程里面,并把这个jar包顺序提前.由于调用installPackage需要传入 IPackageInstallObserver,所以我们要超级一个 IPackageInstallObserver实例.
public static void installSilent(Context context, String filePath, String pmParams) {
	if (filePath == null || filePath.length() == 0) {
		return ;
	}

	File file = new File(filePath);
	if (file == null || file.length() <= 0 || !file.exists() || !file.isFile()) {
		return ;
	}
	int installFlags = 0;
	Uri packageUri = Uri.fromFile(file);//file是要安装的apk文件

	PackageManager pm = context.getPackageManager();
	installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;

	MyPackageInstallObserver observer = new MyPackageInstallObserver();
	pm.installPackage(packageUri, observer, installFlags, null);

}

private static class MyPackageInstallObserver implements IPackageInstallObserver{

	@Override
	public IBinder asBinder() {
	// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void packageInstalled(String arg0, int arg1)throws RemoteException {
	// TODO Auto-generated method stub

	}

}

 

其他关于判断和获取下载apk的代码,后续再补上.
 

方法2:执行命令pm install -r xxx.apk

注意这个方法是不用导入Android编码编译出来的framework.jar,当时同样也是需要使用平台签名和在AndroidManifest.xml里面添加INSTALL_PAKCAGE的权限.
 
  1.  

方法3:参考系统安装apk的方式(不要验证相关过程),然后调用java反射来实现

在手机里面安装app的时候最好是调用的com.android.packageinstaller.InstallAppProgress.java这个Activity.在它的initView里面可以看到他最后是调用 pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,installerPackageName, verificationParams, null);来实现的,
其中pm就是PackageManger,当是PackageManger只是一个抽象类,这个方法的实现是在ApplicationPackageManager.java里面的.
public void installPackageWithVerificationAndEncryption(Uri packageURI,
            IPackageInstallObserver observer, int flags, String installerPackageName,
            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) 
在ApplicationPackageManager里面可以看到还有一个方法可以实现上面这个安装功能就是
public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,String installerPackageName).
由于我们现在是准备通过反射来实现,为了减少难度和创建参数的麻烦(这里observe的创建就很麻烦),我们就直接使用反射来调用installPakcage()来实现.
但是我们目前不能拿到   IPackageInstallObserver observer对象,因为这个对象只能通过 IPackageInstallObserver .Stub. asInterface(IBinder binder)来获得.而我们不能得到binder对象,所以不能直接调用反射.
这里我们可以直接参考
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/content/pm/IPackageInstallObserver.java ,将IPackageInstallObserver.stub部分拷贝出来.
 
定义一个系统不可见的接口IPackageInstallObserver,所以包名是不能变的
 
public void installSlient() {
	String newAppPath = getNewAppPath();
	try {
		Runtime.getRuntime().exec("pm install "+ newAppPath+ File.separator + "111.apk");
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

private String getNewAppPath() {
	try {
		String f = Environment.getExternalStorageDirectory().getCanonicalPath();
		Log.d(TAG,"getNewAppPath f=" +f);
		return f;
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return null;
}

 

 
 
  1. package android.content.pm;
  2.  
  3. public interface IPackageInstallObserver extends android.os.IInterface {
  4.  
  5. public abstract static class Stub extends android.os.Binder implements android.content.pm.IPackageInstallObserver {
  6. public Stub() {
  7. throw new RuntimeException("Stub!");
  8. }
  9.  
  10. public static android.content.pm.IPackageInstallObserver asInterface(android.os.IBinder obj) {
  11. throw new RuntimeException("Stub!");
  12. }
  13.  
  14. public android.os.IBinder asBinder() {
  15. throw new RuntimeException("Stub!");
  16. }
  17.  
  18. public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
  19. throws android.os.RemoteException {
  20. throw new RuntimeException("Stub!");
  21. }
  22. }
  23.  
  24. public abstract void packageInstalled(java.lang.String packageName, int returnCode) throws android.os.RemoteException;
  25. }
创建一个回调接口 OnInstalledPackaged (参考InstallAppProgress.java就可以)
  1. package com.example.install;
  2.  
  3. public interface OnInstalledPackaged {
  4. public void packageInstalled(String packageName, int returnCode);
  5. }
 
实现 ApplicationManager(这个主要是参考InstallAppProgress,设置了回调接口 )
  1. package com.example.install;
  2. import java.io.File;
  3. import java.lang.reflect.InvocationTargetException;
  4. import java.lang.reflect.Method;
  5.  
  6. import android.content.Context;
  7. import android.content.pm.IPackageInstallObserver;
  8. import android.content.pm.PackageManager;
  9. import android.net.Uri;
  10. import android.os.RemoteException;
  11.  
  12. public class ApplicationManager {
  13. public final int INSTALL_REPLACE_EXISTING = 2;
  14. public static final int INSTALL_SUCCEEDED = 1;
  15.  
  16. private PackageInstallObserver observer;
  17. private PackageManager pm;
  18. private Method method;
  19.  
  20. private OnInstalledPackaged onInstalledPackaged;
  21.  
  22. class PackageInstallObserver extends IPackageInstallObserver.Stub {
  23.  
  24. public void packageInstalled(String packageName, int returnCode) throws RemoteException {
  25. if (onInstalledPackaged != null) {
  26. onInstalledPackaged.packageInstalled(packageName, returnCode);
  27. }
  28. }
  29. }
  30.  
  31. public ApplicationManager(Context context) throws SecurityException, NoSuchMethodException {
  32.  
  33. observer = new PackageInstallObserver();
  34. pm = context.getPackageManager();
  35.  
  36. Class<?>[] types = new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class};
  37. method = pm.getClass().getMethod("installPackage", types);
  38. }
  39.  
  40. public void setOnInstalledPackaged(OnInstalledPackaged onInstalledPackaged) {
  41. this.onInstalledPackaged = onInstalledPackaged;
  42. }
  43.  
  44. public void installPackage(String apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
  45. installPackage(new File(apkFile));
  46. }
  47.  
  48. public void installPackage(File apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
  49. if (!apkFile.exists()) throw new IllegalArgumentException();
  50. Uri packageURI = Uri.fromFile(apkFile);
  51. installPackage(packageURI);
  52. }
  53.  
  54. public void installPackage(Uri apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
  55. method.invoke(pm, new Object[] {apkFile, observer, INSTALL_REPLACE_EXISTING, null});
  56. }
  57.  
  58. }
调用反射
  1. public void installSlient2() {
  2. try {
  3. final ApplicationManager am = new ApplicationManager(this);
  4. am.setOnInstalledPackaged(new OnInstalledPackaged() {
  5. public void packageInstalled(String packageName, int returnCode) {
  6. if (returnCode == ApplicationManager.INSTALL_SUCCEEDED) {
  7. Log.d(TAG, "Install succeeded");
  8. } else {
  9. Log.d(TAG, "Install failed: " + returnCode);
  10. }
  11. }
  12. });
  13.  
  14. String newAppPath = getNewAppPath();
  15. am.installPackage(newAppPath+ File.separator + "111.apk");
  16. } catch (Exception e) {
  17. Log.e(TAG, "", e);
  18. }
  19. }
后来发现方法3太麻烦了,可以参考方法2 直接在ApplicationManager里面创建一个实现了IPackageInstallObserver接口的MyPackageInstallObserver内部类.
 
参考
http://blog.csdn.net/liliang497/article/details/8479668
android静默安装探讨:  http://blog.csdn.net/sdvch/article/details/16832941
http://blog.csdn.net/sdvch/article/details/16832959
http://www.cnblogs.com/brucenan/archive/2012/10/04/2711817.html
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值