欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 静默方式实现批量安装卸载应用程序的深入分析

程序员文章站 2023-10-19 13:36:18
前段时间做了一个批量安装卸载应用程序的小应用,由于安装卸载应用程序的部分api是隐藏的,所以必须在ubuntu下下载android系统源码,并编译之后使用mm命令编译生成a...
前段时间做了一个批量安装卸载应用程序的小应用,由于安装卸载应用程序的部分api是隐藏的,所以必须在ubuntu下下载android系统源码,并编译之后使用mm命令编译生成apk文件,其实也难。

思路是这样的,在xx/packages/apps目录下有一个packageinstaller的应用程序,android机器中安装卸载都是由这个应用程序完成的。但是它没有批量安装和卸载的功能,如果要在自己的应用程序中添加批量安装和卸载的功能,其实很简单,只需要参考pakcageinstaller里面的安装卸载代码加个循环就可以了。但值得注意的是在编译的过程中必须复制packageinstaller里面的android.mk文件,修改文件为工程目录名。
好了,废话不再多说,下面是关键代码
1、 android.mk文件
复制代码 代码如下:

local_path:= $(call my-dir)
include $(clear_vars)

local_module_tags := optional

local_src_files := $(call all-subdir-java-files)

local_package_name := packageinstaller
local_certificate := platform

include $(build_package)

复制代码 代码如下:

    local_path:= $(call my-dir) 
    include $(clear_vars) 

    local_module_tags := optional 

    local_src_files := $(call all-subdir-java-files) 

    local_package_name := packageinstaller 
    local_certificate := platform 

    include $(build_package) 

2、pakcageinstaller.java文件(关键代码)
复制代码 代码如下:

    package cn.ceadic.apkmgr;

    import java.io.file;
    import java.io.filenotfoundexception;
    import java.io.fileoutputstream;
    import java.io.ioexception;

    import android.content.context;
    import android.content.intent;
    import android.content.pm.packageinfo;
    import android.content.pm.packagemanager;
    import android.content.pm.packagemanager.namenotfoundexception;
    import android.net.uri;
    import android.util.log;

    import android.content.pm.ipackageinstallobserver;
    import android.content.pm.ipackagedeleteobserver;
    import android.os.fileutils;

    
    public class packageinstaller {

        private file mtmpfile;
        private final string tmp_file_name = "tmpcopy.apk";

        private final static string tag = "packinstaller";
        private context mcontext;

        public packageinstaller(context context) {
            mcontext = context;
        }

        
        public void install(string path,string packagename){
             intent intent = new intent(intent.action_view);
             intent.setdataandtype(uri.fromfile(new file(path)),
             "application/vnd.android.package-archive");
             mcontext.startactivity(intent);
        }

        public void instatllbatch(string path, string packagename) {

            log.i(tag, "path=" + path);
            int installflags = 0;
            packagemanager pm = mcontext.getpackagemanager();
            try {
                packageinfo pi = pm.getpackageinfo(packagename,
                        packagemanager.get_uninstalled_packages);
                if (pi != null) {
                    installflags |= packagemanager.install_replace_existing;
                }
            } catch (namenotfoundexception e) {
            }
            if ((installflags & packagemanager.install_replace_existing) != 0) {
                log.w(tag, "replacing package:" + packagename);
            }

            // create temp file before invoking install api
            mtmpfile = createtemppackagefile(path);
            if (mtmpfile == null) {
                // message msg = mhandler.obtainmessage(install_complete);
                // msg.arg1 = packagemanager.install_failed_insufficient_storage;
                // mhandler.sendmessage(msg);
                return;
            }
            uri mpackageuri = uri.parse("file://" + mtmpfile.getpath());
            string installerpackagename = mcontext.getintent().getstringextra(
                    intent.extra_installer_package_name);

            packageinstallobserver observer = new packageinstallobserver();
            pm.installpackage(mpackageuri, observer, installflags,
                    installerpackagename);
        }

        private file createtemppackagefile(string filepath) {
            file tmppackagefile = mcontext.getfilestreampath(tmp_file_name);
            if (tmppackagefile == null) {
                log.w(tag, "failed to create temp file");
                return null;
            }
            if (tmppackagefile.exists()) {
                tmppackagefile.delete();
            }
            // open file to make it world readable
            fileoutputstream fos;
            try {
                fos = openfileoutput(tmp_file_name, mode_world_readable);
            } catch (filenotfoundexception e1) {
                log.e(tag, "error opening file " + tmp_file_name);
                return null;
            }
            try {
                fos.close();
            } catch (ioexception e) {
                log.e(tag, "error opening file " + tmp_file_name);
                return null;
            }

            file srcpackagefile = new file(filepath);
            if (!fileutils.copyfile(srcpackagefile, tmppackagefile)) {
                log.w(tag, "failed to make copy of file: " + srcpackagefile);
                return null;
            }
            return tmppackagefile;
        }

        private class packageinstallobserver extends ipackageinstallobserver.stub {
            public void packageinstalled(string packagename, int returncode) {
                // message msg = mhandler.obtainmessage(install_complete);
                // msg.arg1 = returncode;
                // mhandler.sendmessage(msg);
                log.i(tag, "====install_complete");
            }
        }

        private class packagedeleteobserver extends ipackagedeleteobserver.stub {
            public void packagedeleted(boolean succeeded) {
    //            message msg = mhandler.obtainmessage(uninstall_complete);
    //            msg.arg1 = succeeded?succeeded:failed;
    //            mhandler.sendmessage(msg);
                log.i(tag, "====uninstall_complete");
            }
        }

        public void uninstall(string packagename){
            uri packageuri = uri.parse("package:" + packagename);
            intent uninstallintent = new intent(intent.action_delete,
            packageuri);
            mcontext.startactivity(uninstallintent);
        }

        public void uninstallbatch(string packagename) {
            packagedeleteobserver observer = new packagedeleteobserver();
            mcontext.getpackagemanager().deletepackage(packagename, observer, 0);

        }
    } 

复制代码 代码如下:

    package cn.ceadic.apkmgr; 

    import java.io.file; 
    import java.io.filenotfoundexception; 
    import java.io.fileoutputstream; 
    import java.io.ioexception; 

    import android.content.context; 
    import android.content.intent; 
    import android.content.pm.packageinfo; 
    import android.content.pm.packagemanager; 
    import android.content.pm.packagemanager.namenotfoundexception; 
    import android.net.uri; 
    import android.util.log; 

    import android.content.pm.ipackageinstallobserver; 
    import android.content.pm.ipackagedeleteobserver; 
    import android.os.fileutils; 

     
    public class packageinstaller { 

        private file mtmpfile; 
        private final string tmp_file_name = "tmpcopy.apk"; 

        private final static string tag = "packinstaller"; 
        private context mcontext; 

        public packageinstaller(context context) { 
            mcontext = context; 
        } 

         
        public void install(string path,string packagename){ 
             intent intent = new intent(intent.action_view); 
             intent.setdataandtype(uri.fromfile(new file(path)), 
             "application/vnd.android.package-archive"); 
             mcontext.startactivity(intent); 
        } 

        public void instatllbatch(string path, string packagename) { 

            log.i(tag, "path=" + path); 
            int installflags = 0; 
            packagemanager pm = mcontext.getpackagemanager(); 
            try { 
                packageinfo pi = pm.getpackageinfo(packagename, 
                        packagemanager.get_uninstalled_packages); 
                if (pi != null) { 
                    installflags |= packagemanager.install_replace_existing; 
                } 
            } catch (namenotfoundexception e) { 
            } 
            if ((installflags & packagemanager.install_replace_existing) != 0) { 
                log.w(tag, "replacing package:" + packagename); 
            } 

            // create temp file before invoking install api 
            mtmpfile = createtemppackagefile(path); 
            if (mtmpfile == null) { 
                // message msg = mhandler.obtainmessage(install_complete); 
                // msg.arg1 = packagemanager.install_failed_insufficient_storage; 
                // mhandler.sendmessage(msg); 
                return; 
            } 
            uri mpackageuri = uri.parse("file://" + mtmpfile.getpath()); 
            string installerpackagename = mcontext.getintent().getstringextra( 
                    intent.extra_installer_package_name); 

            packageinstallobserver observer = new packageinstallobserver(); 
            pm.installpackage(mpackageuri, observer, installflags, 
                    installerpackagename); 
        } 

        private file createtemppackagefile(string filepath) { 
            file tmppackagefile = mcontext.getfilestreampath(tmp_file_name); 
            if (tmppackagefile == null) { 
                log.w(tag, "failed to create temp file"); 
                return null; 
            } 
            if (tmppackagefile.exists()) { 
                tmppackagefile.delete(); 
            } 
            // open file to make it world readable 
            fileoutputstream fos; 
            try { 
                fos = openfileoutput(tmp_file_name, mode_world_readable); 
            } catch (filenotfoundexception e1) { 
                log.e(tag, "error opening file " + tmp_file_name); 
                return null; 
            } 
            try { 
                fos.close(); 
            } catch (ioexception e) { 
                log.e(tag, "error opening file " + tmp_file_name); 
                return null; 
            } 

            file srcpackagefile = new file(filepath); 
            if (!fileutils.copyfile(srcpackagefile, tmppackagefile)) { 
                log.w(tag, "failed to make copy of file: " + srcpackagefile); 
                return null; 
            } 
            return tmppackagefile; 
        } 

        private class packageinstallobserver extends ipackageinstallobserver.stub { 
            public void packageinstalled(string packagename, int returncode) { 
                // message msg = mhandler.obtainmessage(install_complete); 
                // msg.arg1 = returncode; 
                // mhandler.sendmessage(msg); 
                log.i(tag, "====install_complete"); 
            } 
        } 

        private class packagedeleteobserver extends ipackagedeleteobserver.stub { 
            public void packagedeleted(boolean succeeded) { 
    //            message msg = mhandler.obtainmessage(uninstall_complete); 
    //            msg.arg1 = succeeded?succeeded:failed; 
    //            mhandler.sendmessage(msg); 
                log.i(tag, "====uninstall_complete"); 
            } 
        } 

        public void uninstall(string packagename){ 
            uri packageuri = uri.parse("package:" + packagename); 
            intent uninstallintent = new intent(intent.action_delete, 
            packageuri); 
            mcontext.startactivity(uninstallintent); 
        } 

        public void uninstallbatch(string packagename) { 
            packagedeleteobserver observer = new packagedeleteobserver(); 
            mcontext.getpackagemanager().deletepackage(packagename, observer, 0); 

        } 
    } 

3、别忘记添加权限
复制代码 代码如下:

    <uses-permission android:name="android.permission.write_external_storage"/>
        <uses-permission android:name="android.permission.install_packages" />
        <uses-permission android:name="android.permission.delete_packages" />
        <uses-permission android:name="android.permission.clear_app_cache" />
        <uses-permission android:name="android.permission.read_phone_state" />
        <uses-permission android:name="android.permission.clear_app_user_data" /> 

复制代码 代码如下:

    <uses-permission android:name="android.permission.write_external_storage"/> 
        <uses-permission android:name="android.permission.install_packages" /> 
        <uses-permission android:name="android.permission.delete_packages" /> 
        <uses-permission android:name="android.permission.clear_app_cache" /> 
        <uses-permission android:name="android.permission.read_phone_state" /> 
        <uses-permission android:name="android.permission.clear_app_user_data" /> 

以上代码在android2.1的sdk中编译通过,并正确批量安装卸载应用程序