android 通过action启动Activity拦截,Activity应用组件添加intent-filter priority(优先级)不生效

1. 项目背景
android 通过action启动Activity拦截,Activity应用组件添加intent-filter priority(优先级)不生效。

【前置条件】1.电源模式D1

【操作步骤】1.打开搜狐App的八方电台点击进行麦克风授权

【预期结果】1.正常跳转到车机定制的系统设置

【实际结果】1.跳转到Android原生设置页面

【发生概率】5/5

2. 分析过程

搜狐用的是安卓标准跳转方法
系统的应用程序设置页 ACTION_APPLICATION_DETAILS_SETTINGS = “android.settings.APPLICATION_DETAILS_SETTINGS”;

很明显是车机定制的设置App没有接收这个action,只有原生的设置接收这个action,所以导致跳转错误。

通过命令:adb shell dumpsys package > package.log
可以很清晰的看到,确实接收这个action的只有一个activity。
在这里插入图片描述

在 Activity 的 intent-filter 中,android:priority 主要影响 隐式 Intent 的匹配优先级。
当多个 Activity 声明了相同的 intent-filter 时,优先级 (priority) 较高的 Activity 更有可能被系统选中。

  • android:priority 仅影响隐式 Intent(Implicit Intent),不影响显式 Intent(Explicit Intent)。
  • android:priority 取值范围为 -1000 到 1000。
  • 默认值为 0,即如果未设置 android:priority,默认是 0。

在这里插入图片描述
根据资料,我们进行如下方式修改:
在这里插入图片描述

修改完之后,通过adb install的方式,替换apk之后,发现并不能实现activity跳转拦截,dump如下:
在这里插入图片描述
通过上面的dump可以看出来,adb install替换app的方式,PMS里面的控件已经发生了变化,但是为什么功能却不生效呢?通过跟踪priority的代码可知,intent-filter的priority会通过IntentFilter.setPriority进行修改,详情

    /**
     * Modify priority of this filter.  This only affects receiver filters.
     * The priority of activity filters are set in XML and cannot be changed
     * programmatically. The default priority is 0. Positive values will be
     * before the default, lower values will be after it. Applications should
     * use a value that is larger than {@link #SYSTEM_LOW_PRIORITY} and
     * smaller than {@link #SYSTEM_HIGH_PRIORITY} .
     *
     * @param priority The new priority value.
     *
     * @see #getPriority
     * @see #SYSTEM_LOW_PRIORITY
     * @see #SYSTEM_HIGH_PRIORITY
     */
    public final void setPriority(int priority) {
        Log.w(TAG, "setPriority, this =" + this + ", priority = " + priority);
        for (String action : mActions) {
            Log.w(TAG, "-----setPriority, this =" + this + ", priority = " + priority + ", action = " + action);
            if (action != null && action.contains("APPLICATION_DETAILS_SETTINGS")) {
                Log.w(TAG, "setPriority, this =" + this + ", callstack = ", new Throwable("xxx"));
            }
        }
        mPriority = priority;
    }
01-01 12:32:56.797  1702  1755 W IntentFilter: -----setPriority, this =android.content.IntentFilter@94037f2, priority = 0, action = android.settings.APPLICATION_DETAILS_SETTINGS
01-01 12:32:56.797  1702  1755 W IntentFilter: setPriority, this =android.content.IntentFilter@94037f2, callstack = 
01-01 12:32:56.797  1702  1755 W IntentFilter: java.lang.Throwable: xxx
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at android.content.IntentFilter.setPriority(IntentFilter.java:534)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.resolution.ComponentResolver.adjustPriority(ComponentResolver.java:630)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.resolution.ComponentResolver.addAllComponents(ComponentResolver.java:209)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.InstallPackageHelper.commitPackageSettings(InstallPackageHelper.java:506)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.InstallPackageHelper.commitReconciledScanResultLocked(InstallPackageHelper.java:402)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.InstallPackageHelper.commitPackagesLocked(InstallPackageHelper.java:2020)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.InstallPackageHelper.installPackagesLI(InstallPackageHelper.java:1037)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.InstallPackageHelper.installPackagesTracedLI(InstallPackageHelper.java:921)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.InstallPackageHelper.processInstallRequests(InstallPackageHelper.java:861)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.InstallParams.lambda$processInstallRequestsAsync$0$com-android-server-pm-InstallParams(InstallParams.java:442)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.pm.InstallParams$$ExternalSyntheticLambda0.run(Unknown Source:6)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at android.os.Handler.handleCallback(Handler.java:942)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at android.os.Handler.dispatchMessage(Handler.java:99)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at android.os.Looper.loopOnce(Looper.java:201)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at android.os.Looper.loop(Looper.java:288)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at android.os.HandlerThread.run(HandlerThread.java:67)
01-01 12:32:56.797  1702  1755 W IntentFilter: 	at com.android.server.ServiceThread.run(ServiceThread.java:44)

通过堆栈信息,可知在install app的时候,会走进adjustPriority进行优先级的调整,并将priority设置成0,所以出现上述的不生效的情况。

 /**
     * Adjusts the priority of the given intent filter according to policy.
     * <p>
     * <ul>
     * <li>The priority for non privileged applications is capped to '0'</li>
     * <li>The priority for protected actions on privileged applications is capped to '0'</li>
     * <li>The priority for unbundled updates to privileged applications is capped to the
     *      priority defined on the system partition</li>
     * </ul>
     * <p>
     * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
     * allowed to obtain any priority on any action.
     */
    private void adjustPriority(@NonNull Computer computer, List<ParsedActivity> systemActivities,
            ParsedActivity activity, ParsedIntentInfo intentInfo, String setupWizardPackage) {
        // nothing to do; priority is fine as-is
        IntentFilter intentFilter = intentInfo.getIntentFilter();
        if (intentFilter.getPriority() <= 0) {
            return;
        }

        String packageName = activity.getPackageName();
        AndroidPackage pkg = computer.getPackage(packageName);

        final boolean privilegedApp = pkg.isPrivileged();
        String className = activity.getClassName();
        if (!privilegedApp) {
            // non-privileged applications can never define a priority >0
            if (DEBUG_FILTERS) {
                Slog.i(TAG, "Non-privileged app; cap priority to 0;"
                        + " package: " + packageName
                        + " activity: " + className
                        + " origPrio: " + intentFilter.getPriority());
            }
            intentFilter.setPriority(0);
            return;
        }

        if (isProtectedAction(intentFilter)) {
            if (mDeferProtectedFilters) {
                // We can't deal with these just yet. No component should ever obtain a
                // >0 priority for a protected actions, with ONE exception -- the setup
                // wizard. The setup wizard, however, cannot be known until we're able to
                // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
                // until all intent filters have been processed. Chicken, meet egg.
                // Let the filter temporarily have a high priority and rectify the
                // priorities after all system packages have been scanned.
                if (mProtectedFilters == null) {
                    mProtectedFilters = new ArrayList<>();
                }
                mProtectedFilters.add(Pair.create(activity, intentInfo));
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "Protected action; save for later;"
                            + " package: " + packageName
                            + " activity: " + className
                            + " origPrio: " + intentFilter.getPriority());
                }
            } else {
                if (DEBUG_FILTERS && setupWizardPackage == null) {
                    Slog.i(TAG, "No setup wizard;"
                            + " All protected intents capped to priority 0");
                }
                if (packageName.equals(setupWizardPackage)) {
                    if (DEBUG_FILTERS) {
                        Slog.i(TAG, "Found setup wizard;"
                                + " allow priority " + intentFilter.getPriority() + ";"
                                + " package: " + packageName
                                + " activity: " + className
                                + " priority: " + intentFilter.getPriority());
                    }
                    // setup wizard gets whatever it wants
                    return;
                }
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "Protected action; cap priority to 0;"
                            + " package: " + packageName
                            + " activity: " + className
                            + " origPrio: " + intentFilter.getPriority());
                }
                intentFilter.setPriority(0);
            }
            return;
        }

        if (systemActivities == null) {
            // the system package is not disabled; we're parsing the system partition

            // privileged apps on the system image get whatever priority they request
            return;
        }

        // privileged app unbundled update ... try to find the same activity

        ParsedActivity foundActivity = findMatchingActivity(systemActivities, activity);
        if (foundActivity == null) {
            // this is a new activity; it cannot obtain >0 priority
            if (DEBUG_FILTERS) {
                Slog.i(TAG, "New activity; cap priority to 0;"
                        + " package: " + packageName
                        + " activity: " + className
                        + " origPrio: " + intentFilter.getPriority());
            }
            intentFilter.setPriority(0);
            return;
        }

        // found activity, now check for filter equivalence

        // a shallow copy is enough; we modify the list, not its contents
        final List<ParsedIntentInfo> intentListCopy =
                new ArrayList<>(foundActivity.getIntents());

        // find matching action subsets
        final Iterator<String> actionsIterator = intentFilter.actionsIterator();
        if (actionsIterator != null) {
            getIntentListSubset(intentListCopy, IntentFilter::actionsIterator, actionsIterator);
            if (intentListCopy.size() == 0) {
                // no more intents to match; we're not equivalent
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "Mismatched action; cap priority to 0;"
                            + " package: " + packageName
                            + " activity: " + className
                            + " origPrio: " + intentFilter.getPriority());
                }
                intentFilter.setPriority(0);
                return;
            }
        }

        // find matching category subsets
        final Iterator<String> categoriesIterator = intentFilter.categoriesIterator();
        if (categoriesIterator != null) {
            getIntentListSubset(intentListCopy, IntentFilter::categoriesIterator,
                    categoriesIterator);
            if (intentListCopy.size() == 0) {
                // no more intents to match; we're not equivalent
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "Mismatched category; cap priority to 0;"
                            + " package: " + packageName
                            + " activity: " + className
                            + " origPrio: " + intentFilter.getPriority());
                }
                intentFilter.setPriority(0);
                return;
            }
        }

        // find matching schemes subsets
        final Iterator<String> schemesIterator = intentFilter.schemesIterator();
        if (schemesIterator != null) {
            getIntentListSubset(intentListCopy, IntentFilter::schemesIterator, schemesIterator);
            if (intentListCopy.size() == 0) {
                // no more intents to match; we're not equivalent
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
                            + " package: " + packageName
                            + " activity: " + className
                            + " origPrio: " + intentFilter.getPriority());
                }
                intentFilter.setPriority(0);
                return;
            }
        }

        // find matching authorities subsets
        final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator =
                intentFilter.authoritiesIterator();
        if (authoritiesIterator != null) {
            getIntentListSubset(intentListCopy, IntentFilter::authoritiesIterator,
                    authoritiesIterator);
            if (intentListCopy.size() == 0) {
                // no more intents to match; we're not equivalent
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "Mismatched authority; cap priority to 0;"
                            + " package: " + packageName
                            + " activity: " + className
                            + " origPrio: " + intentFilter.getPriority());
                }
                intentFilter.setPriority(0);
                return;
            }
        }

        // we found matching filter(s); app gets the max priority of all intents
        int cappedPriority = 0;
        for (int i = intentListCopy.size() - 1; i >= 0; --i) {
            cappedPriority = Math.max(cappedPriority,
                    intentListCopy.get(i).getIntentFilter().getPriority());
        }
        if (intentFilter.getPriority() > cappedPriority) {
            if (DEBUG_FILTERS) {
                Slog.i(TAG, "Found matching filter(s);"
                        + " cap priority to " + cappedPriority + ";"
                        + " package: " + packageName
                        + " activity: " + className
                        + " origPrio: " + intentFilter.getPriority());
            }
            intentFilter.setPriority(cappedPriority);
            return;
        }
        // all this for nothing; the requested priority was <= what was on the system
    }

通过代码可知,以下几种情况不生效:

  • 内置到/system/app 不生效
  • 手动安装方式新增action的情况不生效

最后通过push的方式替换apk,验证OK,问题解决。

3. 修改方案以及注意事项

测试过的几种上不生效的情况

  • 内置到/system/app 不生效
  • 手动安装方式新增action的情况不生效

notes:
如果app按照如下方式调用:
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
val uri = Uri.fromParts(“package”, context?.packageName, null)
intent.data = uri

还需要加上 data android:scheme=“package” 如下所示:

        <intent-filter android:priority="999">
            <action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" />
            <data android:scheme="package" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值