Android偏好设置及findPreferredActivity分析

在手机使用中,经常需要设置默认打开方式,比如安装了好几个浏览器的时候,在打开网页链接的时候,在第一次会弹框让用户进行应用的选择。

这里以浏览器为例进行说明。
如果之前设置了默认浏览器,再安装另外一个浏览器后,再次打开链接,会重新弹框要求用户选择打开方式,这样设计的目的是让新安装的应用有机会得到用户的选择使用。

在之前的文章中,已经知道了存储偏好设置的文件是package-restrictions.xml
现在来查看下package-restrictions.xml,把UC设置为默认浏览器
package-restrictions.xml
        <item name="com.UCMobile/.main.UCMobile" match="200000" always="true" set="2">
            <set name="com.UCMobile/.main.UCMobile" />
            <set name="com.android.browser/.BrowserActivity" />
            <filter>
                <action name="android.intent.action.VIEW" />
                <cat name="android.intent.category.DEFAULT" />
                <scheme name="http" />
            </filter>
        </item>

安装另外一个浏览器后,调用到 findPreferredActivity
                            if (always && !pa.mPref.sameSet(query)) {

                                Slog.d(TAG, "===== pa.mPref.Set =" + pa.mPref.mSetPackages);
                                for (String astr : pa.mPref.mSetPackages)
                                {
                                        Slog.d(TAG, "set[]=" + astr);
                                }

                                 Slog.i(TAG, "Result set changed, dropping preferred activity for "
                                        + intent + " type " + resolvedType);
                                if (DEBUG_PREFERRED) {
                                    Slog.v(TAG, "Removing preferred activity since set changed "
                                            + pa.mPref.mComponent);
                                }

pa.mPref.mSetPackages 为 package-restrictions.xml里set的内容,如
            <set name="com.UCMobile/.main.UCMobile" />
            <set name="com.android.browser/.BrowserActivity" />

query为实时从pms里查询得到的满足条件的activity相关信息
当发现两个数据不一致的时候,就认为系统里的ap发生了变化,走到
Slog.i(TAG, "Result set changed, dropping preferred activity for "
                                        + intent + " type " + resolvedType);
删除掉之前的默认设置。然后由
ResolverActivity去处理,显示选择界面

基本处理流程是
点击url网络连接 ->  findPreferredActivity, 查看是否有默认打开方式
如果有,直接打开
如果没有,
 pm.addPreferredActivity(filter, bestMatch, set, intent.getComponent());
去重新设置偏好。

可参考下图




值得注意的是,
ResolverActivity里对activity的
priority进行了处理,如果一个ap注册的时候,把
intent-filter里的
priority写为了负数,如下所示
<intent-filter android:priority="-1" > 
 <category android:name="android.intent.category.DEFAULT" />
 <action android:name="android.intent.action.VIEW" /> 
 <data android:scheme="http" />


那么,在选择默认浏览器的时候,就不会显示出这个应用。
因为在
private void rebuildList() 里
有这样的处理
        for (int i=1; i<N; i++) {
                    ResolveInfo ri = currentResolveList.get(i);
                    if (DEBUG) Log.v(
                        TAG,
                        r0.activityInfo.name + "=" +
                        r0.priority + "/" + r0.isDefault + " vs " +
                        ri.activityInfo.name + "=" +
                        ri.priority + "/" + ri.isDefault);
                    if (r0.priority != ri.priority ||
                        r0.isDefault != ri.isDefault) {
                        while (i < N) {
                            if (mOrigResolveList == currentResolveList) {
                                mOrigResolveList = new ArrayList<ResolveInfo>(mOrigResolveList);
                            }
                            currentResolveList.remove(i);

导致
priority为负数的不会显示出来。

了解了这些,就可以去分析这个问题

在6.0的版本上,对
priority
的处理有些变化,比如对于自定义的ap  Test,
priority
设置为大于0的数
<intent-filter android:priority="3" > 
 <category android:name="android.intent.category.DEFAULT" />
 <action android:name="android.intent.action.VIEW" /> 
 <data android:scheme="http" />

之前手机上安装了3个浏览器(
priority都为0的
),其中UC设置为了默认浏览器,再安装Test,
接着打开网络链接,会弹出选择界面,
在L版本上会列出所有的浏览器,M上呢?

答案是只显示出UC和Test
因为M里的做了些修改,查看 PackageManagerService.java的
queryIntentActivities可以很容易的找到


package-restrictions.xml
        <item name="com.UCMobile/.main.UCMobile" match="200000" always="true" set="2">
            <set name="com.UCMobile/.main.UCMobile" />
            <set name="com.android.browser/.BrowserActivity" />
            <filter>
                <action name="android.intent.action.VIEW" />
                <cat name="android.intent.category.DEFAULT" />
                <scheme name="http" />
            </filter>
        </item>
里match的来源
这个查看过程非常复杂,
这里直接说下结果,是 IntentFilter.java里的 matchData方法


附相关log,注意,pms里的DEBUG_PREFERRED开关需要打开

05-01 08:53:56.290: D/PackageManager(918): ===== findPreferredActivity called
05-01 08:53:56.290: D/PackageManager(918): ===== begin =====
05-01 08:53:56.290: D/PackageManager(918): com.android.server.pm.PackageManagerService.findPreferredActivity(PackageManagerService.java:3575)
05-01 08:53:56.290: D/PackageManager(918): com.android.server.pm.PackageManagerService.chooseBestActivity(PackageManagerService.java:3494)
05-01 08:53:56.290: D/PackageManager(918): com.android.server.pm.PackageManagerService.resolveIntent(PackageManagerService.java:3432)
05-01 08:53:56.290: D/PackageManager(918): android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:507)
05-01 08:53:56.290: D/PackageManager(918): com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:2264)
05-01 08:53:56.290: D/PackageManager(918): android.os.Binder.execTransact(Binder.java:451)
05-01 08:53:56.290: V/PackageManager(918): Looking for presistent preferred activities...
05-01 08:53:56.290: V/PackageManager(918): Looking for preferred activities...
05-01 08:53:56.290: D/IntentResolver(918): ===== queryIntent called
05-01 08:53:56.290: V/IntentResolver(918): Resolving type=null scheme=http defaultOnly=true userId=0 of Intent { act=android.intent.action.VIEW dat= http://wap.uc.cn flg=0x8 }
05-01 08:53:56.290: V/IntentResolver(918): Scheme list: [PreferredActivity{0x43bb27d com.UCMobile/.main.UCMobile}, null]
05-01 08:53:56.290: D/IntentResolver(918): ===== buildResolveList called
05-01 08:53:56.291: D/IntentResolver(918): ===== begin =====
05-01 08:53:56.291: D/IntentResolver(918): com.android.server.IntentResolver.buildResolveList(IntentResolver.java:677)
05-01 08:53:56.291: D/IntentResolver(918): com.android.server.IntentResolver.queryIntent(IntentResolver.java:458)
05-01 08:53:56.291: D/IntentResolver(918): com.android.server.pm.PackageManagerService.findPreferredActivity(PackageManagerService.java:3597)
05-01 08:53:56.291: D/IntentResolver(918): com.android.server.pm.PackageManagerService.chooseBestActivity(PackageManagerService.java:3494)
05-01 08:53:56.291: D/IntentResolver(918): com.android.server.pm.PackageManagerService.resolveIntent(PackageManagerService.java:3432)
05-01 08:53:56.291: D/IntentResolver(918): android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:507)
05-01 08:53:56.291: D/IntentResolver(918): com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:2264)
05-01 08:53:56.291: D/IntentResolver(918): android.os.Binder.execTransact(Binder.java:451)
05-01 08:53:56.291: V/IntentResolver(918): Matching against filter PreferredActivity{0x43bb27d com.UCMobile/.main.UCMobile}
05-01 08:53:56.291: D/IntentFilter(918): ===== matchData called
05-01 08:53:56.291: D/IntentFilter(918): ===== match=200000
05-01 08:53:56.291: V/IntentResolver(918):   Filter matched!  match=0x208000 hasDefault=true
05-01 08:53:56.291: V/IntentResolver(918):     43bb27d com.UCMobile/.main.UCMobile
05-01 08:53:56.292: V/IntentResolver(918):      mMatch=0x200000 mAlways=true
05-01 08:53:56.292: V/IntentResolver(918):       Selected from:
05-01 08:53:56.292: V/IntentResolver(918):         com.UCMobile/.main.UCMobile
05-01 08:53:56.292: V/IntentResolver(918):         com.android.browser/.BrowserActivity
05-01 08:53:56.292: V/IntentResolver(918):     Action: "android.intent.action.VIEW"
05-01 08:53:56.292: V/IntentResolver(918):     Category: "android.intent.category.DEFAULT"
05-01 08:53:56.292: V/IntentResolver(918):     Scheme: "http"
05-01 08:53:56.292: V/IntentResolver(918): Final result list:
05-01 08:53:56.292: V/IntentResolver(918):   PreferredActivity{0x43bb27d com.UCMobile/.main.UCMobile}
05-01 08:53:56.292: V/PackageManager(918): Figuring out best match...
05-01 08:53:56.292: V/PackageManager(918): Match for ActivityInfo{21f95286 com.android.browser.BrowserActivity}: 0x0
05-01 08:53:56.292: V/PackageManager(918): Match for ActivityInfo{7f12747 com.UCMobile.main.UCMobile}: 0x208000
05-01 08:53:56.292: V/PackageManager(918): Match for ActivityInfo{38f8b74 com.taobao.browser.BrowserActivity}: 0x208000
05-01 08:53:56.292: D/PackageManager(918): ===== query list is:
05-01 08:53:56.292: D/PackageManager(918): ===== ResolveInfo{2e13ff6b com.android.browser/.BrowserActivity m=0x208000}
05-01 08:53:56.292: D/PackageManager(918): ===== ResolveInfo{2e188ac8 com.UCMobile/.main.UCMobile m=0x208000}
05-01 08:53:56.292: D/ResolveInfo(918): tos ===== priority=-1
05-01 08:53:56.292: D/PackageManager(918): ===== ResolveInfo{396c3761 com.taobao.taobao/com.taobao.browser.BrowserActivity p=-1 m=0x208000}
05-01 08:53:56.292: V/PackageManager(918): Best match: 0x208000
05-01 08:53:56.292: V/PackageManager(918): Checking PreferredActivity ds=http
05-01 08:53:56.292: V/PackageManager(918):   component=ComponentInfo{com.UCMobile/com.UCMobile.main.UCMobile}
05-01 08:53:56.292: V/PackageManager(918):   Action: "android.intent.action.VIEW"
05-01 08:53:56.292: V/PackageManager(918):   Category: "android.intent.category.DEFAULT"
05-01 08:53:56.292: V/PackageManager(918):   Scheme: "http"
05-01 08:53:56.292: V/PackageManager(918): Found preferred activity:
05-01 08:53:56.292: V/PackageManager(918):   name=com.UCMobile.main.UCMobile
05-01 08:53:56.292: V/PackageManager(918):   packageName=com.UCMobile
05-01 08:53:56.292: V/PackageManager(918):   labelRes=0x7f070004 nonLocalizedLabel=null icon=0x0 banner=0x0
05-01 08:53:56.292: V/PackageManager(918):   enabled=true exported=true processName=com.UCMobile
05-01 08:53:56.292: V/PackageManager(918):   taskAffinity=com.UCMobile targetActivity=null persistableMode=PERSIST_ROOT_ONLY
05-01 08:53:56.292: V/PackageManager(918):   launchMode=2 flags=0x8a theme=0x103000f
05-01 08:53:56.292: V/PackageManager(918):   screenOrientation=-1 configChanges=0x400004a3 softInputMode=0x20
05-01 08:53:56.292: V/PackageManager(918):   ApplicationInfo:
05-01 08:53:56.292: V/PackageManager(918):     packageName=com.UCMobile
05-01 08:53:56.292: V/PackageManager(918):     labelRes=0x7f070004 nonLocalizedLabel=null icon=0x7f020089 banner=0x0
05-01 08:53:56.292: V/PackageManager(918):     className=com.uc.browser.UCMobileApp
05-01 08:53:56.292: V/PackageManager(918):     processName=com.UCMobile
05-01 08:53:56.292: V/PackageManager(918):     taskAffinity=com.UCMobile
05-01 08:53:56.292: V/PackageManager(918):     uid=10073 flags=0x883e44 theme=0x0 flagsEx=0x0
05-01 08:53:56.292: V/PackageManager(918):     requiresSmallestWidthDp=0 compatibleWidthLimitDp=0 largestWidthLimitDp=0
05-01 08:53:56.292: V/PackageManager(918):     sourceDir=/data/app/com.UCMobile-1/base.apk
05-01 08:53:56.292: V/PackageManager(918):     seinfo=default
05-01 08:53:56.292: V/PackageManager(918):     dataDir=/data/data/com.UCMobile
05-01 08:53:56.292: V/PackageManager(918):     enabled=true targetSdkVersion=23 versionCode=648
05-01 08:53:56.292: V/PackageManager(918):     manageSpaceActivityName=com.uc.application.cleaner.SystemManageData.ManageDataActivity
05-01 08:53:56.292: V/PackageManager(918):     supportsRtl=false
05-01 08:53:56.292: D/PackageManager(918): ===== pa.mPref.Set =[Ljava.lang.String;@1053e89d, always=true
05-01 08:53:56.292: D/PackageManager(918): set[]=com.UCMobile
05-01 08:53:56.292: D/PackageManager(918): set[]=com.android.browser
05-01 08:53:56.292: D/PackageManager(918): ===== pa.mPref.Set =[Ljava.lang.String;@1053e89d
05-01 08:53:56.292: D/PackageManager(918): set[]=com.UCMobile
05-01 08:53:56.293: D/PackageManager(918): set[]=com.android.browser
05-01 08:53:56.293: I/PackageManager(918): Result set changed, dropping preferred activity for Intent { act=android.intent.action.VIEW dat= http://wap.uc.cn flg=0x8 } type null
05-01 08:53:56.293: V/PackageManager(918): Removing preferred activity since set changed ComponentInfo{com.UCMobile/com.UCMobile.main.UCMobile}
05-01 08:53:56.293: V/IntentResolver(918): Removing filter: PreferredActivity{0x43bb27d com.UCMobile/.main.UCMobile}
05-01 08:53:56.293: V/IntentResolver(918):       Action: "android.intent.action.VIEW"
05-01 08:53:56.293: V/IntentResolver(918):       Category: "android.intent.category.DEFAULT"
05-01 08:53:56.293: V/IntentResolver(918):       Scheme: "http"
05-01 08:53:56.293: V/IntentResolver(918):     Cleaning Lookup Maps:
05-01 08:53:56.293: V/IntentResolver(918):       Scheme: http
05-01 08:53:56.293: V/IntentResolver(918): Adding filter: PreferredActivity{0xb081112 com.UCMobile/.main.UCMobile}
05-01 08:53:56.293: V/IntentResolver(918):       Action: "android.intent.action.VIEW"
05-01 08:53:56.293: V/IntentResolver(918):       Category: "android.intent.category.DEFAULT"
05-01 08:53:56.293: V/IntentResolver(918):       Scheme: "http"
05-01 08:53:56.293: V/IntentResolver(918):     Building Lookup Maps:
05-01 08:53:56.293: V/IntentResolver(918):       Scheme: http
05-01 08:53:56.293: V/PackageManager(918): Preferred activity bookkeeping changed; writing restrictions


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值