问题描述:如图:
在Android的开发过程中,我们会遇到如上的这样问题,有多个启动的应用程序,要求用户选择要使用其中的某个应用。在具体的开发环境中,可能客户有特殊需求,要求我们默认启动的就是Android原生的,而不是其他应用程序,也就是不需要弹出上图的选择框给用户选择。
要实现上述功能,首先要跟踪定位下代码,看看是在哪里处理选择多个启动的应用程序。从上次流程的打印代码中,我们可以跟踪到,在frameworks/base/services/java/com/android/server/pm/PackageManagerService.java中,chooseBestActivity()方法是处理选择最好的activity。代码如下:
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
int flags, List<ResolveInfo> query, int userId) {
if (query != null) {
final int N = query.size();
if (N == 1) {
return query.get(0);
} else if (N > 1) {
final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
// If there is more than one activity with the same priority,
// then let the user decide between them.
ResolveInfo r0 = query.get(0);
ResolveInfo r1 = query.get(1);
if (DEBUG_INTENT_MATCHING || debug) {
Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
+ r1.activityInfo.name + "=" + r1.priority);
}
// If the first activity has a higher priority, or a different
// default, then it is always desireable to pick it.
if (r0.priority != r1.priority
|| r0.preferredOrder != r1.preferredOrder
|| r0.isDefault != r1.isDefault) {
return query.get(0);
}
// If we have saved a preference for a preferred activity for
// this Intent, use that.
ResolveInfo ri = findPreferredActivity(intent, resolvedType,
flags, query, r0.priority, true, false, debug, userId);
if (ri != null) {
return ri;
}
if (userId != 0) {
ri = new ResolveInfo(mResolveInfo);
ri.activityInfo = new ActivityInfo(ri.activityInfo);
ri.activityInfo.applicationInfo = new ApplicationInfo(
ri.activityInfo.applicationInfo);
ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
return ri;
}
return mResolveInfo;
}
}
return null;
}
分析代码:我们可以在其中N > 1时,加多块代码处理:如果所有可用的应用程序中,包含我们想要启动默认程序,如Android原生应用,我们就返回该值。增加的代码如下:
for(int i=0;i<N;i++){
if(query.get(i).activityInfo.name.equals("com.android.packageinstaller.PackageInstallerActivity"))
{return query.get(i);}
}
最后代码修改如下,+为新增加的代码:
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
int flags, List<ResolveInfo> query, int userId) {
if (query != null) {
final int N = query.size();
if (N == 1) {
return query.get(0);
} else if (N > 1) {
+ for(int i=0;i<N;i++){
+ if(query.get(i).activityInfo.name.equals("com.android.packageinstaller.PackageInstallerActivity")){
+ return query.get(i);
+ }
+ }
final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
// If there is more than one activity with the same priority,
// then let the user decide between them.
ResolveInfo r0 = query.get(0);
ResolveInfo r1 = query.get(1);
if (DEBUG_INTENT_MATCHING || debug) {
Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
+ r1.activityInfo.name + "=" + r1.priority);
}
// If the first activity has a higher priority, or a different
// default, then it is always desireable to pick it.
if (r0.priority != r1.priority
|| r0.preferredOrder != r1.preferredOrder
|| r0.isDefault != r1.isDefault) {
return query.get(0);
}
// If we have saved a preference for a preferred activity for
// this Intent, use that.
ResolveInfo ri = findPreferredActivity(intent, resolvedType,
flags, query, r0.priority, true, false, debug, userId);
if (ri != null) {
return ri;
}
if (userId != 0) {
ri = new ResolveInfo(mResolveInfo);
ri.activityInfo = new ActivityInfo(ri.activityInfo);
ri.activityInfo.applicationInfo = new ApplicationInfo(
ri.activityInfo.applicationInfo);
ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
return ri;
}
return mResolveInfo;
}
}
return null;
}