Android 安装APK、更新apk、隐藏(hide)apk、解除隐藏(unhide)apk 所对应的广播log

Android版本:Android R(11)

 

一、用户安装的apk发生更新

 

public void registerReceiver(Context context) {
        Slog.d("PMSdddd", "systemReady1");
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        filter.addDataScheme("package");
        BroadcastReceiver packgeMonitorReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                final String packageName =
intent.getData().getSchemeSpecificPart();
                final boolean replacing =
intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                final boolean dataRemoved =
intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false);

                Slog.d("PMSdddd", "action: " + action + " packageName:"
+ packageName + "  replacing:" + replacing
                        + "  dataRemoved:" + dataRemoved);
            }
        };
        context.registerReceiver(packgeMonitorReceiver, filter);
    }

 

 

adb install apk

Line 52701: 02-01 21:26:23.213  1727  1727 D PMSdddd : action: android.intent.action.PACKAGE_ADDED  packageName:com.adobe.reader  replacing:false  dataRemoved:false

 

adb shell pm hide apk

Line 53895: 02-01 21:28:22.043  1727  1727 D PMSdddd : action: android.intent.action.PACKAGE_REMOVED  packageName:com.adobe.reader  replacing:false  dataRemoved:false

 

 

adb install -r apk

Line 54477: 02-01 21:29:41.550  1727  1727 D PMSdddd : action: android.intent.action.PACKAGE_REMOVED  packageName:com.adobe.reader  replacing:true  dataRemoved:false


Line 54512: 02-01 21:29:41.648  1727  1727 D PMSdddd : action: android.intent.action.PACKAGE_ADDED  packageName:com.adobe.reader  replacing:true  dataRemoved:false

 

 

 adb shell pm unhide apk

Line 55640: 02-01 21:32:25.651  1727  1727 D PMSdddd : action: android.intent.action.PACKAGE_ADDED  packageName:com.adobe.reader  replacing:false  dataRemoved:false

 

 

 

Line 61310: 02-01 21:52:36.395  1727  1727 D PMSdddd : action: android.intent.action.PACKAGE_REMOVED  packageName:com.adobe.reader  replacing:false  dataRemoved:true

 

总结:

  • hide命令:系统会发送广播 android.intent.action.PACKAGE_REMOVED,data数据并不会删除
  • unhide命令:系统会发送广播android.intent.action.PACKAGE_ADDED,data数据不会删除
  • 更新apk时:

系统先发送广播 android.intent.action.PACKAGE_REMOVED,intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) 获取的值为true

系统随后发送广播android.intent.action.PACKAGE_ADDED,intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) 获取的值也为true

 

  • 卸载apk时:

 系统发送广播 android.intent.action.PACKAGE_REMOVED,intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false)获取的值为true

 

二、系统apk(位于:system/app 目录)发生更新

 

 

adb push apk system/app 

再恢复出厂设置

 

 

Line 8118: 02-02 02:55:59.428  1130  1130 D PMSdddd : action: android.intent.action.PACKAGE_REMOVED  packageName:com.example.ddd  replacing:true  dataRemoved:false


Line 8134: 02-02 02:55:59.501  1130  1130 D PMSdddd : action: android.intent.action.PACKAGE_ADDED  packageName:com.example.ddd  replacing:true  dataRemoved:false


Line 8281: 02-02 02:55:59.903  1130  1130 D PMSdddd : action: android.intent.action.PACKAGE_REPLACED  packageName:com.example.ddd  replacing:true  dataRemoved:false

 

更新后的apk安装在 data/app目录:

    Line 8550: 02-02 05:12:10.806  1132  1228 I PackageManager: Update system package com.example.ddd code path from /system/operator/app/AndroidDemoV1.0.apk to /data/app/~~IYd549AfrGeHUc-lWfY8kg==/com.example.ddd-o9yTi7O1l3Cm3EhqTvf2Rw==; Retain data and using new
    Line 8550: 02-02 05:12:10.806  1132  1228 I PackageManager: Update system package com.example.ddd code path from /system/operator/app/AndroidDemoV1.0.apk to /data/app/~~IYd549AfrGeHUc-lWfY8kg==/com.example.ddd-o9yTi7O1l3Cm3EhqTvf2Rw==; Retain data and using new
    Line 8551: 02-02 05:12:10.808  1132  1228 I PackageManager: Update system package com.example.ddd resource path from /system/operator/app/AndroidDemoV1.0.apk to /data/app/~~IYd549AfrGeHUc-lWfY8kg==/com.example.ddd-o9yTi7O1l3Cm3EhqTvf2Rw==; Retain data and using new
    Line 8551: 02-02 05:12:10.808  1132  1228 I PackageManager: Update system package com.example.ddd resource path from /system/operator/app/AndroidDemoV1.0.apk to /data/app/~~IYd549AfrGeHUc-lWfY8kg==/com.example.ddd-o9yTi7O1l3Cm3EhqTvf2Rw==; Retain data and using new

 

 

 

 

总结:

系统apk发生更新时,系统依次发送广播:action: android.intent.action.PACKAGE_REMOVED、action: android.intent.action.PACKAGE_ADDED、action: android.intent.action.PACKAGE_REPLACED

且 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false) 获取的值为true

 

 


Android 监听多用户切换,隐藏和禁用指定Apk

IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_USER_SWITCHED);
        filter.addAction(Intent.ACTION_USER_ADDED);
        BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                if (userId == UserHandle.USER_NULL) {
                    Slog.e("PMSdddd", "received an invalid EXTRA_USER_HANDLE");
                    return;
                }
                if (Intent.ACTION_USER_SWITCHED.equals(action) && userId > 0) {
                    Slog.d("PMSdddd", "User switched to userId " + userId);
                    AsyncTask.execute(new Runnable() {
                        @Override
                        public void run() {
                            Slog.d("PMSdddd", "install start11");
                            Sbbbbbbbbbbb.hideOtherBrandAppWhenUserSwitched();
                        }
                    });
                } else if (Intent.ACTION_USER_ADDED.equals(action) && userId > 0) {
                    Slog.d("PMSdddd", "Added User  userId " + userId);
                    AsyncTask.execute(new Runnable() {
                        @Override
                        public void run() {
                            Slog.d("PMSdddd", "install start11");
Sbbbbbbbbbbb
.hideOtherBrandAppWhenUserSwitched(); } }); } } }; mContext.registerReceiver(mUserSwitchedReceiver, filter);

 

是否隐藏和禁用apk

/**
     * only hide app but don't delete user data
     *
     * @param pkgName
     */
    private void hide(String pkgName) {
        final PackageManager pm = mContext.getPackageManager();
        int userId = ActivityManager.getCurrentUser();
        pm.setApplicationHiddenSettingAsUser(pkgName, true, new UserHandle(userId));
        disableApplication(pkgName);
    }

    private void unhide(String pkgName) {
        final PackageManager pm = mContext.getPackageManager();
        int userId = ActivityManager.getCurrentUser();
        pm.setApplicationHiddenSettingAsUser(pkgName, false, new UserHandle(userId));
        enableApplication(pkgName);
    }

    private void disableApplication(String pkgName) {
        final PackageManager pm = mContext.getPackageManager();
        try {
            int state = pm.getApplicationEnabledSetting(pkgName);
            Slog.d(TAG, "disableApplication state: " + state + " pkgName:" + pkgName);
            if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED)
                return;
            pm.setApplicationEnabledSetting(pkgName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
        } catch (IllegalArgumentException exeption) {
            Slog.w(TAG, "disableApplication error:" + exeption.getMessage());
        }
    }

    private void enableApplication(String pkgName) {
        final PackageManager pm = mContext.getPackageManager();
        try {
            int state = pm.getApplicationEnabledSetting(pkgName);
            Slog.d(TAG, "enableApplication state: " + state + " pkgName:" + pkgName);
            if (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
                return;
            pm.setApplicationEnabledSetting(pkgName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
        } catch (IllegalArgumentException exeption) {
            Slog.w(TAG, "enableApplication error:" + exeption.getMessage());
        }
    }


隐藏的apk或disable的apk,信息保存在 /data/system/users/0/package-restrictions.xml 文件内

 

<pkg name="com.google.android.apps.maps" ceDataInode="4439" enabled="3" enabledCaller="com.android.settings" domainVerificationStatus="2" app-link-generation="4">

<pkg name="com.google.android.apps.maps" ceDataInode="4439" enabled="2" enabledCaller="android" domainVerificationStatus="2" app-link-generation="4">

 

 

<pkg name="com.amazon.appmanager" ceDataInode="4472" hidden="true" enabled="2" enabledCaller="android" />

<pkg name="com.google.android.apps.maps" ceDataInode="4439" enabled="3" enabledCaller="com.android.settings" domainVerificationStatus="2" app-link-generation="4">

apk被hide后,保存的信息:hidden="true"

apk被disable后,根据 setApplicationEnabledSetting 传入的常量参数不同,enabled= 的值就会不同,如下介绍:

public static final int COMPONENT_ENABLED_STATE_DISABLED = 2;  // disable应用时,若传入此参数,则应用在桌面没有图标,且在设置界面、应用程序列表里面也没有图标 (应用完全隐藏了)

public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; // disable应用时,若传入此参数,则应用在桌面没有图标,但是在设置界面、应用程序列表里面有图标 (只是桌面图标隐藏了,设置里面仍可以看到图标,用户可以再次enable此应用)

 

另外:adb shell pm disable-user  应用包名: 相当于传入的参数是 COMPONENT_ENABLED_STATE_DISABLED。

 

查看手机有哪些应用处于disable状态的方法:

方法1:adb shell pm list packages -d

C:\Users\zzz>adb shell pm list packages -d
package:com.facebook.services
package:com.google.android.videos
package:com.facebook.appmanager

 

方法2:adb shell pm dump packages > Desktop/log2.txt

enabled=2  ---->表示应用处于disable状态,对应的值:COMPONENT_ENABLED_STATE_DISABLED

 

Package [com.facebook.appmanager] (a926214):
    userId=10098
    pkg=Package{9ae0abd com.facebook.appmanager}
    codePath=/system/app/appmanager
    resourcePath=/system/app/appmanager
    legacyNativeLibraryDir=/system/app/appmanager/lib
    primaryCpuAbi=arm64-v8a
    secondaryCpuAbi=null
    versionCode=277606887 minSdk=21 targetSdk=30
    versionName=67.3.0
    splits=[base]
    apkSigningVersion=2
    applicationInfo=ApplicationInfo{9ae0abd com.facebook.appmanager}
    flags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ]
    privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ALLOW_AUDIO_PLAYBACK_CAPTURE HAS_DOMAIN_URLS PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ]
    forceQueryable=false
    queriesIntents=[Intent { act=com.facebook.secure.packagefinder.intent.ACTION_QUERY_PACKAGES }]
    dataDir=/data/user/0/com.facebook.appmanager
    supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
    timeStamp=2021-07-12 23:30:37
    firstInstallTime=2021-07-12 23:30:37
    lastUpdateTime=2021-07-12 23:30:37
    signatures=PackageSignatures{18e58b2 version:2, signatures:[c4e416cc], past signatures:[]}
    installPermissionsFixed=true
    pkgFlags=[ SYSTEM HAS_CODE ALLOW_CLEAR_USER_DATA ]
    declared permissions:
      com.facebook.appmanager.ACCESS: prot=signature, INSTALLED
      com.facebook.appmanager.API_ACCESS: prot=normal, INSTALLED
    install permissions:
      android.permission.DOWNLOAD_WITHOUT_NOTIFICATION: granted=true
      android.permission.FOREGROUND_SERVICE: granted=true
      android.permission.RECEIVE_BOOT_COMPLETED: granted=true
      android.permission.INTERNET: granted=true
      android.permission.GET_PACKAGE_SIZE: granted=true
      com.facebook.appmanager.ACCESS: granted=true
      android.permission.ACCESS_NETWORK_STATE: granted=true
      android.permission.ACCESS_WIFI_STATE: granted=true
      android.permission.WAKE_LOCK: granted=true
    User 0: ceDataInode=4785 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=2 instant=false virtual=false
    overlay paths:
      /product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk
      lastDisabledCaller: android
      gids=[3003]

 

查看哪些应用属于系统签名?

方法:adb shell pm dump packages > Desktop/log2.txt

包名为"android"的apk属于平台apk,肯定是系统签名,首先看一下包名为"android"的apk的签名信息:

 Package [android] (ad28bfa):
    userId=1000
    sharedUser=SharedUserSetting{769a3df android.uid.system/1000}
    pkg=Package{6103b22 android}
    codePath=/system/framework/framework-res.apk
    resourcePath=/system/framework/framework-res.apk
    legacyNativeLibraryDir=/system/lib64/framework-res
    primaryCpuAbi=arm64-v8a
    secondaryCpuAbi=null
    versionCode=30 minSdk=30 targetSdk=30
    versionName=11
    splits=[base]
    apkSigningVersion=3
    applicationInfo=ApplicationInfo{6103b22 android}
    flags=[ SYSTEM PERSISTENT ALLOW_BACKUP ]
    privateFlags=[ PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION ALLOW_AUDIO_PLAYBACK_CAPTURE DEFAULT_TO_DEVICE_PROTECTED_STORAGE DIRECT_BOOT_AWARE PRIVILEGED PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING ]
    forceQueryable=true
    queriesPackages=[]
    dataDir=/data/system
    supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
    timeStamp=2021-07-12 23:27:41
    firstInstallTime=2021-07-12 23:27:41
    lastUpdateTime=2021-07-12 23:27:41
    signatures=PackageSignatures{539b9b3 version:3, signatures:[a0521abc], past signatures:[]}
    installPermissionsFixed=true
    pkgFlags=[ SYSTEM PERSISTENT ALLOW_BACKUP ]
    declared permissions:
      android.permission.READ_CONTACTS: prot=dangerous, INSTALLED
      android.permission.WRITE_CONTACTS: prot=dangerous, INSTALLED
      ........

    User 0: ceDataInode=4316 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
    overlay paths:
      /product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk
      

 

从上面信息可以看到,签名信息:signatures:[a0521abc]  ,然后在 log2.txt 文件全局搜索“a0521abc”,可以列出所有系统签名的应用

 

xref: /frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java

 

                case "enable":
                    return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
                case "disable":
                    return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
                case "disable-user":
                    return runSetEnabledSetting(
                            PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
                case "disable-until-used":
                    return runSetEnabledSetting(
                            PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
                case "default-state":
                    return runSetEnabledSetting(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
                case "hide":
                    return runSetHiddenSetting(true);
                case "unhide":
                    return runSetHiddenSetting(false);

 

 

xref: /frameworks/base/core/java/android/content/pm/PackageManager.java

   /** @hide */
    @IntDef(prefix = { "COMPONENT_ENABLED_STATE_" }, value = {
            COMPONENT_ENABLED_STATE_DEFAULT,
            COMPONENT_ENABLED_STATE_ENABLED,
            COMPONENT_ENABLED_STATE_DISABLED,
            COMPONENT_ENABLED_STATE_DISABLED_USER,
            COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface EnabledState {}

    /**
     * Flag for {@link #setApplicationEnabledSetting(String, int, int)} and
     * {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
     * component or application is in its default enabled state (as specified in
     * its manifest).
     * <p>
     * Explicitly setting the component state to this value restores it's
     * enabled state to whatever is set in the manifest.
     */
    public static final int COMPONENT_ENABLED_STATE_DEFAULT = 0;

    /**
     * Flag for {@link #setApplicationEnabledSetting(String, int, int)}
     * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
     * component or application has been explictily enabled, regardless of
     * what it has specified in its manifest.
     */
    public static final int COMPONENT_ENABLED_STATE_ENABLED = 1;

    /**
     * Flag for {@link #setApplicationEnabledSetting(String, int, int)}
     * and {@link #setComponentEnabledSetting(ComponentName, int, int)}: This
     * component or application has been explicitly disabled, regardless of
     * what it has specified in its manifest.
     */
    public static final int COMPONENT_ENABLED_STATE_DISABLED = 2;

    /**
     * Flag for {@link #setApplicationEnabledSetting(String, int, int)} only: The
     * user has explicitly disabled the application, regardless of what it has
     * specified in its manifest.  Because this is due to the user's request,
     * they may re-enable it if desired through the appropriate system UI.  This
     * option currently <strong>cannot</strong> be used with
     * {@link #setComponentEnabledSetting(ComponentName, int, int)}.
     */
    public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;

    /**
     * Flag for {@link #setApplicationEnabledSetting(String, int, int)} only: This
     * application should be considered, until the point where the user actually
     * wants to use it.  This means that it will not normally show up to the user
     * (such as in the launcher), but various parts of the user interface can
     * use {@link #GET_DISABLED_UNTIL_USED_COMPONENTS} to still see it and allow
     * the user to select it (as for example an IME, device admin, etc).  Such code,
     * once the user has selected the app, should at that point also make it enabled.
     * This option currently <strong>can not</strong> be used with
     * {@link #setComponentEnabledSetting(ComponentName, int, int)}.
     */
    public static final int COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED = 4;

 

 

开机默认禁用某个应用

1、pms的systemReady()方法内延迟2秒调用

    // avoid issue: "java.lang.IllegalStateException: Cannot broadcast before boot completed" when hide or unhide app
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            // isFirstBoot() 首次开机;  isDeviceUpgrading() OTA升级首次开机
            // 打印log
            if(isFirstBoot() && 其他判断条件){
                //打印log
                disableApplication("目标应用包名",true);
            }
            
        }
    }, 2 * 1000);

2. 禁用和启用方法

    private void disableApplication(String pkgName, boolean userDisable) {
        final PackageManager pm = mContext.getPackageManager();
        try {
            int state = pm.getApplicationEnabledSetting(pkgName);
            Slog.d(TAG, "disableApplication state: " + state + " pkgName:" + pkgName + " defaultDisable:" + userDisable);
            if (userDisable) {
                int userId = ActivityManager.getCurrentUser();
                pm.setApplicationHiddenSettingAsUser(pkgName, false, new UserHandle(userId)); // unhide apk
 
                if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
                    return;
                pm.setApplicationEnabledSetting(pkgName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0); // fake user disable
            } else {
                int userId = ActivityManager.getCurrentUser();
                pm.setApplicationHiddenSettingAsUser(pkgName, true, new UserHandle(userId)); // hide apk
 
                if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED)
                    return;
                pm.setApplicationEnabledSetting(pkgName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0); // disable apk
            }
        } catch (IllegalArgumentException exeption) {
            Slog.w(TAG, "disableApplication error:" + exeption.getMessage());
        }
    }
 
    private void enableApplication(String pkgName) {
        final PackageManager pm = mContext.getPackageManager();
        try {
            int state = pm.getApplicationEnabledSetting(pkgName);
            Slog.d(TAG, "enableApplication state: " + state + " pkgName:" + pkgName);
            if (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
                return;
            pm.setApplicationEnabledSetting(pkgName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
        } catch (IllegalArgumentException exeption) {
            Slog.w(TAG, "enableApplication error:" + exeption.getMessage());
        }
    }

 

 

 

卸载apk但保留user data数据

调用平台自带的 setApplicationHiddenSettingAsUser 接口

    private void hide(String pkgName) {

        final PackageManager pm = mContext.getPackageManager();

        pm.setApplicationHiddenSettingAsUser(pkgName, true,

UserHandle.SYSTEM);

    }

 

    private void unhide(String pkgName) {

        final PackageManager pm = mContext.getPackageManager();

        pm.setApplicationHiddenSettingAsUser(pkgName, false,

UserHandle.SYSTEM);

    }

     /**

     * Puts the package in a hidden state, which is almost like an

uninstalled state,

     * making the package unavailable, but it doesn't remove the data

or the actual

     * package file. Application can be unhidden by either resetting

the hidden state

     * or by installing it, such as with {@link

#installExistingPackage(String)}

     * @hide

     */

    @UnsupportedAppUsage

    public abstract boolean setApplicationHiddenSettingAsUser(@NonNull String packageName,

            boolean hidden, @NonNull UserHandle userHandle);

 

 

posted @ 2021-02-01 21:48  行走的思想  阅读(3019)  评论(0编辑  收藏  举报