【问题标题】:ResolveInfo - check if is default launch intent or notResolveInfo - 检查是否是默认启动意图
【发布时间】:2018-03-12 07:34:50
【问题描述】:

我的工作

我正在检索所有已安装应用的列表,如下所示(对于类似应用的启动器):

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

    }
}

到目前为止,这是可行的。但是像三星手机应用程序这样的一些应用程序不尊重他们应该只用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 是否属于默认启动意图?

【问题讨论】:

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


    【解决方案1】:

    您可以按如下方式使用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。

    【讨论】:

    • 这和我已经做的一样。我添加了类别,因此添加您建议的标志不会改变任何内容。问题是,可能存在注册多个默认活动的应用程序,如果我仅使用应用程序的包名称启动默认活动(例如具有以下意图:pm.getLaunchIntentForPackage(packageName);)
    • @prom85 查看您的要求,您似乎正在寻找CATEGORY_LAUNCHER 而不是CATEGORY_DEFAULT 的活动。对吗?
    • 对三星的应用程序没有影响(两个活动都有启动器和默认标志)。我在我的问题中添加了一个需求区域,以更清楚地说明我想要什么
    【解决方案2】:

    解决方案

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

    • 像我的问题一样获取所有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;
    }
    

    【讨论】:

      猜你喜欢
      • 2014-11-01
      • 1970-01-01
      • 2019-01-07
      • 2012-01-08
      • 2019-04-06
      • 2018-10-10
      • 1970-01-01
      • 1970-01-01
      • 2011-10-26
      相关资源
      最近更新 更多