5

Android 静默安装和卸载

 2 years ago
source link: http://www.androidchina.net/7880.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
  1. 需要放到 /system/app里作为系统app

二. 适用环境

  1. 机顶盒开发,系统开发,车机开发,智能设备开发。

1. 在 AndroidManifest.xml 中

1.1. 在清单文件 AndroidManifest.xml 添加 android.uid.system 声明为系统应用。

1.2. 权限
java 

<uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 
<uses-permission android:name="android.permission.DELETE_PACKAGES" /> 
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> 
再添加读写权限这个可以实现安装时读取路径 
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

1.3 总配置步骤图

W~(LD8IUF59QKEAI8`V}S3H.png

2. 代码部分 (两种方法都可以实现,现在项目选择了第二种)

之前公司开发时机器是api 17 ,获取了系统里pm的代码通过aidl实现加反射实现 这个方法也是比较正规的做法

去你们系统的源码里找到android.content.pm把里面的代码拷拷出来看图这几个就够了。

Q)Q5U%ZJU28KF)()UA@FQK1.png

 安装
 public void installApp(final String path, final String packageNames){
    File apkFile = new File(path);
       /* 当前app无法访问外置sd卡文件,exists()会为false所以直接抛异常最好
     if(!apkFile.exists()){
           sendBroadcastMsg(packageNames,false,"路径错误");
           return;
      }*/
       try {
           Class<?> clazz = Class.forName("android.os.ServiceManager");
           Method method_getService = clazz.getMethod("getService", String.class);
          IBinder bind = (IBinder) method_getService.invoke(null, "package");
           IPackageManager iPm = IPackageManager.Stub.asInterface(bind);
           iPm.installPackage(Uri.fromFile(apkFile), new IPackageInstallObserver.Stub(){
               @Override
               public void packageInstalled(String packageName, int returnCode) throws RemoteException {

               }
           }, 2, apkFile.getName());
       } catch (Exception e) {
           sendBroadcastMsg(packageNames,false,"安装异常");
           e.printStackTrace();
       }
   }
 卸载
 public void uninstallApp(String packageName){
       try {
           Class<?> clazz = Class.forName("android.os.ServiceManager");
           Method method_getService = clazz.getMethod("getService",String.class);
           IBinder bind = (IBinder) method_getService.invoke(null, "package");
           IPackageManager iPm = IPackageManager.Stub.asInterface(bind);
           iPm.deletePackageAsUser(packageName,null,0,2);
           System.out.println("=================>>卸载成功");
       } catch (Exception e) {
           e.printStackTrace();
           System.out.println("=================>>卸载失败");
       }
   }
方法二 (兼容到6.0,6.0以上没测过,现在用的是这种没一点问题兼容公司所以系统,无需AIDL)
1. rxjava版 安装如果不要rxjava可以new Thread但要记住线程里不要有刷新ui操作
    private void install(final String packageName, final String filePath) {
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                File file = new File(filePath);
                if (filePath == null || filePath.length() == 0 || file == null) {
                    e.onNext(0);
                    return;
                }
                String[] args = { "pm", "install", "-r", filePath };
                ProcessBuilder processBuilder = new ProcessBuilder(args);
                Process process = null;
                BufferedReader successResult = null;
                BufferedReader errorResult = null;
                StringBuilder successMsg = new StringBuilder();
                StringBuilder errorMsg = new StringBuilder();
                try {
                    process = processBuilder.start();
                    successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                    String s;
                    while ((s = successResult.readLine()) != null) {
                        successMsg.append(s);
                    }
                    while ((s = errorResult.readLine()) != null) {
                        errorMsg.append(s);
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                } finally {
                    try {
                        if (successResult != null) {
                            successResult.close();
                        }
                        if (errorResult != null) {
                            errorResult.close();
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    if (process != null) {
                        process.destroy();
                    }
                }
      if (successMsg.toString().contains("Success") || successMsg.toString().contains("success")) {
                    e.onNext(2);
                } else {
                    e.onNext(1);
                }
            }
        }).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }
                    @Override
                    public void onNext(Integer value) {
                        if (value==2) {
                             //安装成功
                        } else {
                             //安装错误
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                       //安装错误
                    }

                    @Override
                    public void onComplete() {

                    }
                });
}
2.卸载
    private void uninstall(String packageName) {
        try {
            PackageManager pm = context.getPackageManager();
            Method[] methods = pm!=null?pm.getClass().getDeclaredMethods():null;
            Method mDel = null;
            if (methods != null && methods.length>0) {
                for (Method method : methods) {
                    if (method.getName().toString().equals("deletePackage")) {
                        mDel = method;
                        break;
                    }
                }
            }
            if (mDel != null) {
                mDel.setAccessible(true);
                mDel.invoke(pm,packageName,null,0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3.记得签名和打到system/app里去 前面需要的文件 下面是我们公司的文件名称一般文件都是一样的,对系统编译后是可以获取的。

1. platform.pk8
2. platform.x509.pem
3. signapk.jar

下面是我的工具图

  1. DW9_9VUX1Z$Q~@}$4ILJ)0H.png

4.可能出现的问题

方法一如果使用时如果缺少类就把缺少的类复制进去,如果参数不同记得随机应变,一般原生系统是这 样,一般开发不会改动太大pm.

方法二是比较好的方便快捷而且兼容性好点。

转载请注明:Android开发中文站 » Android 静默安装和卸载


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK