ResolveInfo - 检查是否是默认启动意图
ResolveInfo - check if is default launch intent or not
我做什么
我正在检索所有已安装应用的列表,如下所示(对于像应用这样的启动器):
PackageManager pm = context.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null)
.addCategory(Intent.CATEGORY_LAUNCHER);
// flag PackageManager.GET_RESOLVED_FILTER will set ResolveInfo.filter (not documented, but tested)
// many examples use flag == 0, but then the filter is always null
List<ResolveInfo> ril = pm.queryIntentActivities(mainIntent, PackageManager.GET_RESOLVED_FILTER);
if (ril != null) {
for (ResolveInfo ri : ril) {
// I need this info!
// ri.isDefault is always false...
boolean isDefault = ri.isDefault || ril.filter.hasCategory(Intent.CATEGORY_DEFAULT);
}
}
到目前为止,这有效。但是一些应用程序,如三星 phone 应用程序,不尊重它们应该只用 Intent.CATEGORY_DEFAULT
标记一个 activity。以下是三星应用中两项活动的类别:
ActivityInfo{cd007eb com.android.contacts.activities.PeopleActivity}
filter:
0 = "android.intent.category.DEFAULT"
1 = "android.intent.category.LAUNCHER"
2 = "android.intent.category.BROWSABLE"
3 = "android.intent.category.APP_CONTACTS"
ActivityInfo{3e9ba8d com.android.dialer.DialtactsActivity}
filter:
0 = "android.intent.category.DEFAULT"
1 = "android.intent.category.LAUNCHER"
2 = "android.intent.category.BROWSABLE"
要求
- 我需要一个像我这样的应用程序可以启动的所有活动的列表
- 我需要信息,如果
ResolveInfo
是启动的那个,如果我只使用应用程序包名称,就像我使用通过以下命令检索的意图一样:pm.getLaunchIntentForPackage(packageName)
。这就是我在此 post 中所说的默认启动意图
问题
如何可靠地确定 ResolveInfo
是否属于默认启动意图?
解决方案
只要您假设只有一些应用程序注册多个默认活动,此解决方案就可用。
- 得到我问题中的所有
ResolveInfos
- 创建一个
HashMap
并在列表中插入包名称和条目数
- 使用
HashMap
来确定您是否甚至需要检查 ResolveInfo
是否属于默认 activity 或不
- 如果需要检查,请对这个进行慢速检查
ResolveInfo
代码
List<ResolveInfo> ril = ...;
HashMap<String, Integer> packageCountMap = getPackageCountMap(uniqueRil);
for (ResolveInfo ri :: ril) {
boolean isDefault = isDefaultIntentForPhoneApp(packageCountMap, ri);
// use this info...
}
辅助函数:
public static HashMap<String, Integer> getPackageCountMap(List<ResolveInfo> ril) {
HashMap<String, Integer> map = new HashMap<>();
ResolveInfo ri;
Integer count;
if (ril != null) {
for (int i = 0; i < ril.size(); i++) {
ri = ril.get(i);
count = map.get(ri.activityInfo.packageName);
if (count == null) {
count = 1;
} else {
count++;
}
map.put(ri.activityInfo.packageName, count);
}
}
return map;
}
public static boolean isDefaultIntentForPhoneApp(PackageManager pm, HashMap<String, Integer> packageCountMap, ResolveInfo ri) {
boolean isDefault;
// count how often the package name exists => 1x => then the activity must be the default one, no need to do any check
Integer count = packageCountMap.get(ri.activityInfo.packageName);
if (count == null || count <= 1) {
isDefault = true;
}
// otherwise get default activity and compare it
else {
Intent i = pm.getLaunchIntentForPackage(packageName);
ComponentName cn = i.resolveActivity(pm);
isDefault = cn != null && cn.getClassName().equals(ri.activityInfo.name);
}
return isDefault;
}
您可以按如下方式使用queryIntentActivities
:
PackageManager pm = context.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null)
.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> ril = pm.queryIntentActivities(mainIntent, PackageManager.MATCH_DEFAULT_ONLY);
基于 MATCH_DEFAULT_ONLY 的文档:
Resolution and querying flag: if set, only filters that support the
CATEGORY_DEFAULT will be considered for matching. This is a synonym
for including the CATEGORY_DEFAULT in your supplied Intent.
我做什么
我正在检索所有已安装应用的列表,如下所示(对于像应用这样的启动器):
PackageManager pm = context.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null)
.addCategory(Intent.CATEGORY_LAUNCHER);
// flag PackageManager.GET_RESOLVED_FILTER will set ResolveInfo.filter (not documented, but tested)
// many examples use flag == 0, but then the filter is always null
List<ResolveInfo> ril = pm.queryIntentActivities(mainIntent, PackageManager.GET_RESOLVED_FILTER);
if (ril != null) {
for (ResolveInfo ri : ril) {
// I need this info!
// ri.isDefault is always false...
boolean isDefault = ri.isDefault || ril.filter.hasCategory(Intent.CATEGORY_DEFAULT);
}
}
到目前为止,这有效。但是一些应用程序,如三星 phone 应用程序,不尊重它们应该只用 Intent.CATEGORY_DEFAULT
标记一个 activity。以下是三星应用中两项活动的类别:
ActivityInfo{cd007eb com.android.contacts.activities.PeopleActivity}
filter:
0 = "android.intent.category.DEFAULT"
1 = "android.intent.category.LAUNCHER"
2 = "android.intent.category.BROWSABLE"
3 = "android.intent.category.APP_CONTACTS"
ActivityInfo{3e9ba8d com.android.dialer.DialtactsActivity}
filter:
0 = "android.intent.category.DEFAULT"
1 = "android.intent.category.LAUNCHER"
2 = "android.intent.category.BROWSABLE"
要求
- 我需要一个像我这样的应用程序可以启动的所有活动的列表
- 我需要信息,如果
ResolveInfo
是启动的那个,如果我只使用应用程序包名称,就像我使用通过以下命令检索的意图一样:pm.getLaunchIntentForPackage(packageName)
。这就是我在此 post 中所说的默认启动意图
问题
如何可靠地确定 ResolveInfo
是否属于默认启动意图?
解决方案
只要您假设只有一些应用程序注册多个默认活动,此解决方案就可用。
- 得到我问题中的所有
ResolveInfos
- 创建一个
HashMap
并在列表中插入包名称和条目数 - 使用
HashMap
来确定您是否甚至需要检查ResolveInfo
是否属于默认 activity 或不 - 如果需要检查,请对这个进行慢速检查
ResolveInfo
代码
List<ResolveInfo> ril = ...;
HashMap<String, Integer> packageCountMap = getPackageCountMap(uniqueRil);
for (ResolveInfo ri :: ril) {
boolean isDefault = isDefaultIntentForPhoneApp(packageCountMap, ri);
// use this info...
}
辅助函数:
public static HashMap<String, Integer> getPackageCountMap(List<ResolveInfo> ril) {
HashMap<String, Integer> map = new HashMap<>();
ResolveInfo ri;
Integer count;
if (ril != null) {
for (int i = 0; i < ril.size(); i++) {
ri = ril.get(i);
count = map.get(ri.activityInfo.packageName);
if (count == null) {
count = 1;
} else {
count++;
}
map.put(ri.activityInfo.packageName, count);
}
}
return map;
}
public static boolean isDefaultIntentForPhoneApp(PackageManager pm, HashMap<String, Integer> packageCountMap, ResolveInfo ri) {
boolean isDefault;
// count how often the package name exists => 1x => then the activity must be the default one, no need to do any check
Integer count = packageCountMap.get(ri.activityInfo.packageName);
if (count == null || count <= 1) {
isDefault = true;
}
// otherwise get default activity and compare it
else {
Intent i = pm.getLaunchIntentForPackage(packageName);
ComponentName cn = i.resolveActivity(pm);
isDefault = cn != null && cn.getClassName().equals(ri.activityInfo.name);
}
return isDefault;
}
您可以按如下方式使用queryIntentActivities
:
PackageManager pm = context.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null)
.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> ril = pm.queryIntentActivities(mainIntent, PackageManager.MATCH_DEFAULT_ONLY);
基于 MATCH_DEFAULT_ONLY 的文档:
Resolution and querying flag: if set, only filters that support the CATEGORY_DEFAULT will be considered for matching. This is a synonym for including the CATEGORY_DEFAULT in your supplied Intent.