在手机使用中,经常需要设置默认打开方式,比如安装了好几个浏览器的时候,在打开网页链接的时候,在第一次会弹框让用户进行应用的选择。
这里以浏览器为例进行说明。
如果之前设置了默认浏览器,再安装另外一个浏览器后,再次打开链接,会重新弹框要求用户选择打开方式,这样设计的目的是让新安装的应用有机会得到用户的选择使用。
在之前的文章中,已经知道了存储偏好设置的文件是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, 查看是否有默认打开方式
如果有,直接打开
如果没有,
里match的来源
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" />
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为负数的不会显示出来。
了解了这些,就可以去分析这个问题
<intent-filter android:priority="3" >
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="http" />
接着打开网络链接,会弹出选择界面,
在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>
这个查看过程非常复杂,
这里直接说下结果,是
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