ResolveInfo - 检查是否是默认启动意图

时间:2018-03-12 07:34:50

标签: android package-managers android-package-managers

我做什么

我正在检索所有已安装应用的列表,例如以下内容(适用于类似应用的启动器):

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);

    }
}

到目前为止,这是有效的。但是像samsungs手机应用程序这样的应用程序不尊重他们应该只用Intent.CATEGORY_DEFAULT标记一个活动。以下是三星应用程序中两项活动的类别:

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)。这就是我在本文中称之为默认启动意图的内容

问题

如果ResolveInfo属于默认启动意图?如何可靠地找出?

2 个答案:

答案 0 :(得分:0)

<强>解

只要您假设只有一些应用注册了多个默认活动,此解决方案就可以使用。

  • 在我的问题中得到所有ResolveInfos
  • 创建HashMap并在列表
  • 中插入包名和条目数
  • 使用HashMap确定您是否需要检查ResolveInfo是否属于默认活动
  • 如果您需要检查,请对此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;
}

答案 1 :(得分:0)

您可以按如下方式使用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 的文档:

  

分辨率和查询标志:如果设置,只有支持的过滤器   CATEGORY_DEFAULT将被考虑进行匹配。这是一个同义词   在您提供的Intent中包含CATEGORY_DEFAULT。