代码中执行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的权限.
方法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;
}
package android.content.pm;public interface IPackageInstallObserver extends android.os.IInterface {public abstract static class Stub extends android.os.Binder implements android.content.pm.IPackageInstallObserver {public Stub() {throw new RuntimeException("Stub!");}public static android.content.pm.IPackageInstallObserver asInterface(android.os.IBinder obj) {throw new RuntimeException("Stub!");}public android.os.IBinder asBinder() {throw new RuntimeException("Stub!");}public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)throws android.os.RemoteException {throw new RuntimeException("Stub!");}}public abstract void packageInstalled(java.lang.String packageName, int returnCode) throws android.os.RemoteException;}
创建一个回调接口OnInstalledPackaged (参考InstallAppProgress.java就可以)
package com.example.install;public interface OnInstalledPackaged {public void packageInstalled(String packageName, int returnCode);}
实现ApplicationManager(这个主要是参考InstallAppProgress,设置了回调接口)
package com.example.install;import java.io.File;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import android.content.Context;import android.content.pm.IPackageInstallObserver;import android.content.pm.PackageManager;import android.net.Uri;import android.os.RemoteException;public class ApplicationManager {public final int INSTALL_REPLACE_EXISTING = 2;public static final int INSTALL_SUCCEEDED = 1;private PackageInstallObserver observer;private PackageManager pm;private Method method;private OnInstalledPackaged onInstalledPackaged;class PackageInstallObserver extends IPackageInstallObserver.Stub {public void packageInstalled(String packageName, int returnCode) throws RemoteException {if (onInstalledPackaged != null) {onInstalledPackaged.packageInstalled(packageName, returnCode);}}}public ApplicationManager(Context context) throws SecurityException, NoSuchMethodException {observer = new PackageInstallObserver();pm = context.getPackageManager();Class<?>[] types = new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class};method = pm.getClass().getMethod("installPackage", types);}public void setOnInstalledPackaged(OnInstalledPackaged onInstalledPackaged) {this.onInstalledPackaged = onInstalledPackaged;}public void installPackage(String apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {installPackage(new File(apkFile));}public void installPackage(File apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {if (!apkFile.exists()) throw new IllegalArgumentException();Uri packageURI = Uri.fromFile(apkFile);installPackage(packageURI);}public void installPackage(Uri apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {method.invoke(pm, new Object[] {apkFile, observer, INSTALL_REPLACE_EXISTING, null});}}
调用反射
public void installSlient2() {try {final ApplicationManager am = new ApplicationManager(this);am.setOnInstalledPackaged(new OnInstalledPackaged() {public void packageInstalled(String packageName, int returnCode) {if (returnCode == ApplicationManager.INSTALL_SUCCEEDED) {Log.d(TAG, "Install succeeded");} else {Log.d(TAG, "Install failed: " + returnCode);}}});String newAppPath = getNewAppPath();am.installPackage(newAppPath+ File.separator + "111.apk");} catch (Exception e) {Log.e(TAG, "", e);}}
后来发现方法3太麻烦了,可以参考方法2 直接在ApplicationManager里面创建一个实现了IPackageInstallObserver接口的MyPackageInstallObserver内部类.
参考
http://blog.youkuaiyun.com/liliang497/article/details/8479668
android静默安装探讨: http://blog.youkuaiyun.com/sdvch/article/details/16832941
http://blog.youkuaiyun.com/sdvch/article/details/16832959
http://www.cnblogs.com/brucenan/archive/2012/10/04/2711817.html
本文介绍了三种在Android设备上静默安装APK的方法:利用PackageManager的installPackage()方法、执行命令pminstall-r apk路径、使用反射调用ApplicationPackageManager的installPackage()方法,并详细解释了每种方法的具体步骤。
3674

被折叠的 条评论
为什么被折叠?



