Android App的卸载与安装,你了解吗?

前段时间由于项目的需要,研究了下Android App的卸载与安装,这段时间整理了下,写成博客,方便以后查看。

一个手机App,经下载、安装、更新、卸载。

下载就不说了,本篇博客主要研究 安装、更新和卸载。

一个apk经过下载下来,有几种安装方式?

1.内置APP随着系统启动PMS而安装。(刷机后一般第一步操作就是这个)

2.使用adb install命令安装。(开发人员常用方式)

3.通过系统内置的PackageInstaller应用安装。(一般应用通过浏览器下载后就会调用系统安装器弹出界面进行安装)

4.在一些手机厂商内置的应用商店下载,然后静默安装。(手机厂商使用系统级权限进行应用安装)

5.Root的手机使用root权限进行静默安装。(第三方应用市场一般会对root手机采取此类安装方式)

从源码上看:一般分两类 1. 扫描应用程序的存放文件夹进行安装 2. 通过packagemanager进行安装。

这里只研究常用的安装方式 第2、3点

adb命令安装如下

安装前查看设备是否存在

adb devices

有设备是这个样子的

Android App的卸载与安装,你了解吗?

adb install 路径

成功后是这个样子的

Android App的卸载与安装,你了解吗?

adb 命令 一般是开发人员常用

我们来看看系统内置的安装方法

public static void installApp(Context context, String filePath) {
    File apkFile = new File(filePath);
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        Uri contentUri = FileProvider.getUriForFile(
                context
                , BuildConfig.APPLICATION_ID + ".fileProvider"
                , apkFile);
        intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
    } else {
        intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
    }
    context.startActivity(intent);

这种安装在Android 8.0 手机以下没什么问题,但是前几天有个同事手机是8.0的,由于8.0的手机对未知来源的apk安装做了限制,所以只写以上的代码就不行了,处理代码如下。

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
    boolean b =getPackageManager().canRequestPackageInstalls();
    if (b) {
        //调用安装方法
    } else {
        //请求安装未知应用来源的权限
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, REQUEST_INSTALL_PACKAGES);
    }
}else {
    //8.0以下调用安装方法
}

请求一下同意未知来源安装的权限

权限结果如下

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == REQUEST_INSTALL_PACKAGES){
    if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
       //调用安装方法
    } else {
    //做未获取到安装权限的提示
}

}

app 的更新

APP的更新一般是后台控制的,根据后台返回的数据,判断当前的APP是否需要更新,更新执行下载操作,下载完了就回到了安装上面,所以更新没什么需要讨论的。

Android 系统中,有apk的安装、更新、卸载。系统都会发出广播,我们就能收到这个广播。来看看这些广播

首先先把这些广播都给注册上,咦,注册广播用静态注册好呢还是动态注册好呢? 这个就要看你应用的业务需求了,选择适合你应用的注册方法,这里我选择静态注册,AndroidManifest中注册如下。

<receiver android:name=".AppInstallReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_ADDED" />
        <action android:name="android.intent.action.PACKAGE_REPLACED" />
        <action android:name="android.intent.action.PACKAGE_REMOVED" />
        <action android:name="android.intent.action.USER_PRESENT" />
        <data android:scheme="package" />
    </intent-filter>
</receiver>

然后看看广播接收器

public class AppInstallReceiver extends BroadcastReceiver {
    
    private final static String TAG="AppInstallReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        String packageName = intent.getData().getSchemeSpecificPart();
        switch (intent.getAction()){
            case Intent.ACTION_PACKAGE_REMOVED:
                Log.i(TAG,"收到卸载广播,包名为 "+packageName);
                break;
            case Intent.ACTION_MY_PACKAGE_REPLACED:
                Log.i(TAG,"收到App更新广播,包名为 "+packageName);
                break;
            case Intent.ACTION_PACKAGE_ADDED:
                Log.i(TAG,"收到App安装广播,包名为 "+packageName);
                break;
        }
        
    }
}

这些广播有什么用呢?通过监听这些广播客监听到我们目标程序的安装、更新、卸载状态,之后拿到这些状态后做相应的工作,插件化的程序使用居多。

app的卸载

对于用户来说,卸载一个APP,直接长按拖去垃圾筐即可卸载。但是对于我们Android 开发人员来说,其他卸载方法也是要会的。

卸载的方式

1.手机桌面长按应用图标至抖动,然后拖去垃圾筐。

2.调用系统卸载服务进行卸载

3.通过adb 命令卸载

调用系统服务卸载,如下

public static void unstallApp(Context context,String packageName){
    Intent uninstall_intent = new Intent();
    uninstall_intent.setAction(Intent.ACTION_DELETE);
    uninstall_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    uninstall_intent.setData(Uri.parse("package:"+packageName));
    context.startActivity(uninstall_intent);
}

传入 context和包名即可

通过adb命令卸载

同样,卸载前通过命令 adb devices 来查看设备是否连接上

命令  adb shell pm list packages 来查看当前设备安装的应用

是这个样子的

Android App的卸载与安装,你了解吗?

卸载命令

adb uninstall 包名

比如

Android App的卸载与安装,你了解吗?

APP的安装、更新、卸载差不多就讲完了,下面说一说获取已安装APP的相关信息。

不多说,直接上代码,如下。

public static List<AppInfo> getAllAppInfos(PackageManager packageManager) {

    List<AppInfo> list = new ArrayList<AppInfo>();
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    List<ResolveInfo> ResolveInfos = packageManager.queryIntentActivities(intent, 0);
    // 遍历
    for (ResolveInfo ri : ResolveInfos) {
        String packageName = ri.activityInfo.packageName;
        Drawable icon = ri.loadIcon(packageManager);
        String appName = ri.loadLabel(packageManager).toString();
        AppInfo appInfo = new AppInfo(icon, appName, packageName);
        list.add(appInfo);
    }
    return list;
}

AppInfo 是我自己创建的实体类。

好了,到这里了,喜欢或对您有用麻烦点赞哦,谢谢大家。