静默安装:
在某个触发点自动后台安装指定apk.没有安装界面.新软件自动安装,有旧版本的默默卸载,然后再安装,并且在不受系统设置中的第三方软件安装开关的限制.
自己跟踪记录的源码流程
Filemanager中点击apk包之后发送了一个intent出去
|
Android会去系统中的packagemanager中查询哪个apk能响应这个操作.
找到PackageInstaller这个apk.文件路劲位于packages\apps\PackageInstaller
|
系统会启动这个Activity来进行安装操作
本文档只贴出具体安装的过程,舍弃ui操作,并加以简单说明
|
|
|
|
好了.回归主题.静默安装的关键代码已经出来了.只有一行
pm.installPackage(mPackageURI,observer, installFlags(0), installerPackageName);
看源码中该函数说明必须要加上android.Manifest.permission#INSTALL_PACKAGES才行,此权限只有system应用才能使用.所以此应用必须放入system/app下,才能保证其有效.方法就是反射
静默安装的第一种方法:
package com.tnt.autoinstall; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.net.Uri; import android.os.Bundle; import android.app.Activity; public class MainActivity extends Activity { private Uri packageUri; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); packageUri = getPackageUri(); install(); } private void install() { try { Class<?> pmService; Class<?> activityTherad; Method method; activityTherad = Class.forName("android.app.ActivityThread"); Class<?> paramTypes[] = getParamTypes(activityTherad , "getPackageManager"); method = activityTherad.getMethod("getPackageManager", paramTypes); Object PackageManagerService = method.invoke(activityTherad); pmService = PackageManagerService.getClass(); Class<?> paramTypes1[] = getParamTypes(pmService , "installPackage"); method = pmService.getMethod("installPackage", paramTypes1); method.invoke(PackageManagerService , packageUri , null , 0 , null); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }catch (ClassNotFoundException e1) { e1.printStackTrace(); } } private Class<?>[] getParamTypes(Class<?> cls, String mName) { Class<?> cs[] = null; Method[] mtd = cls.getMethods(); for (int i = 0; i < mtd.length; i++) { if (!mtd[i].getName().equals(mName)) { continue; } cs = mtd[i].getParameterTypes(); } return cs; } private Uri getPackageUri() { File file = new File("/storage/sdcard0/download/1.apk"); return Uri.fromFile(file); } }
通过adb命令的方式来处理,代码如下,把上面的install函数替换下面代码
private boolean install() { String[] args = {"pm", "install", "-r", packageUri.getPath()}; String result = null; ProcessBuilder processBuilder = new ProcessBuilder(args);; Process process = null; InputStream errIs = null; InputStream inIs = null; try{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); int read = -1; process = processBuilder.start(); errIs = process.getErrorStream(); while((read = errIs.read()) != -1){ baos.write(read); } baos.write('\n'); inIs = process.getInputStream(); while((read = inIs.read()) != -1){ baos.write(read); } byte[] data = baos.toByteArray(); result = new String(data); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(errIs != null){ errIs.close(); } if(inIs != null){ inIs.close(); } }catch(Exception e){ e.printStackTrace(); } if(process != null){ process.destroy(); } } if(result != null && (result.endsWith("Success")||result.endsWith("Success\n"))) { return true; } return false; }
下面看下卸载过程
同样的.需要增加一个权限android:name="android.permission.DELETE_PACKAGES".放入system/app中.
卸载方式一:adb shell pm方式
private void uninstall2() { String[] args = { "pm", "uninstall", "com.popcap.pvzthird" }; String result = null; ProcessBuilder processBuilder = new ProcessBuilder(args); ; Process process = null; InputStream errIs = null; InputStream inIs = null; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); int read = -1; process = processBuilder.start(); errIs = process.getErrorStream(); while ((read = errIs.read()) != -1) { baos.write(read); } baos.write('\n'); inIs = process.getInputStream(); while ((read = inIs.read()) != -1) { baos.write(read); } byte[] data = baos.toByteArray(); result = new String(data); } catch (Exception e) { e.printStackTrace(); } finally { try { if (errIs != null) { errIs.close(); } if (inIs != null) { inIs.close(); } } catch (Exception e) { e.printStackTrace(); } if (process != null) { process.destroy(); } } }
卸载方式二:反射调用系统函数
Class<?> pmService; Class<?> activityTherad; Method method; activityTherad = Class.forName("android.app.ActivityThread"); Class<?> paramTypes[] = getParamTypes(activityTherad, "getPackageManager"); method = activityTherad.getMethod("getPackageManager", paramTypes); Object PackageManagerService = method.invoke(activityTherad); pmService = PackageManagerService.getClass(); Class<?> paramTypes1[] = getParamTypes(pmService, "deletePackage"); method = pmService.getMethod("deletePackage", paramTypes1); method.invoke(PackageManagerService, "com.popcap.pvzthird", null, 0);