您的位置:首页 > 移动开发 > Android开发

android apk静默安装和卸载

2016-01-08 16:48 423 查看
转自:http://blog.csdn.net/gchk125/article/details/8553805

静默安装:

在某个触发点自动后台安装指定apk.没有安装界面.新软件自动安装,有旧版本的默默卸载,然后再安装,并且在不受系统设置中的第三方软件安装开关的限制.

 

自己跟踪记录的源码流程

Filemanager中点击apk包之后发送了一个intent出去

/*

* uri = file:///storage/sdcard0/download/%E7%99%BE%E9%98%85.apk

* mimeType = application/vnd.android.package-archive

*/

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setDataAndType(uri, mimeType);

startActivity(intent);

 
 

Android会去系统中的packagemanager中查询哪个apk能响应这个操作.

找到PackageInstaller这个apk.文件路劲位于packages\apps\PackageInstaller

<activity android:name=".PackageInstallerActivity" …..>

<intent-filter>……

<data android:mimeType="application/vnd.android.package-archive" />

 
 

系统会启动这个Activity来进行安装操作

本文档只贴出具体安装的过程,舍弃ui操作,并加以简单说明

mPackageURI = intent.getData();   //获取安装包路劲

mPm = getPackageManager();     //获取packagemanager

checkFileInvaild //检测给定的文件是否为一个apk.如果自己确定的东西,省略吧

final File sourceFile = new File(mPackageURI.getPath()); //把路劲转成file类型

PackageParser.Package  mPkgInfo = PackageUtil.getPackageInfo(sourceFile); //解析apk

getIconandTitle //根据mPkgInfo获取apk的icon和title.并存起来,对本题无用

if (!isInstallingUnknownAppsAllowed())//此处判断是否允许第三方软件安装.在设置里.

initiateInstall(); //开始初始化安装

 
String pkgName = mPkgInfo.packageName; //得到包名

String[] oldName = mPm.canonicalToCurrentPackageNames(new String[] { pkgName });

if (oldName != null && oldName.length > 0 && oldName[0] != null) {

pkgName = oldName[0];  

mPkgInfo.setPackageName(pkgName);

}//以上是检测是否存在该包名.但是其已经被改变成别的神马了.*我不知道是神马意思

mPm.getApplicationInfo(pkgName,PackageManager.GET_UNINSTALLED_PACKAGES);

//检测是否有已经安装并未卸载的同名apk,有则弹出替代框(略过),无则安装

startInstallConfirm(); //弹出安装确认,点击ok

newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,mPkgInfo.applicationInfo);

newIntent.setData(mPackageURI);

newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName);

newIntent.setClass(this, InstallAppProgress.class); //把apk的info传入新的Activity安装

…..

 
mAppInfo = intent.getParcelableExtra(XXX);

mPackageURI = intent.getData(); //从上面得到这些东西

String installerPackageName = getIntent().getStringExtra(xxxxPACKAGE_NAME);

PackageInstallObserver observer = new PackageInstallObserver();

pm.installPackage(mPackageURI, observer, installFlags(0), installerPackageName);

//安装过程就交个packagemanager去吧.我们不用管了.

 
//如果你要等待此apk安装完了之后还要处理一些东东的话.看下面

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);

intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);

intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);

intentFilter.addDataScheme("package");

registerReceiver(new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

if (Intent.ACTION_PACKAGE_REMOVED) {}

else if (Intent.ACTION_PACKAGE_ADDED || Intent.ACTION_PACKAGE_REPLACED) {}}

}, intentFilter);

//上面主要就是监听三个事件并在receive中去处理.

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

好了.回归主题.静默安装的关键代码已经出来了.只有一行

pm.installPackage(mPackageURI,observer, installFlags(0), installerPackageName);

看源码中该函数说明必须要加上android.Manifest.permission#INSTALL_PACKAGES才行,此权限只有system应用才能使用.所以此应用必须放入system/app下,才能保证其有效.方法就是反射

 

静默安装的第一种方法:

[java] view
plaincopyprint?

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函数替换下面代码

[java] view
plaincopyprint?

  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方式

[java] view
plaincopyprint?

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();  

            }  

        }  

    }  

卸载方式二:反射调用系统函数

[java] view
plaincopyprint?

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);  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: