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


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值