2

背景

我希望展示本机意图选择器,同时能够对其进行一些自定义。

为此,我找到了下一个 StackOverflow 线程:

如何在 Android 中自定义分享意图?

问题

问题是,当我在 Android 5.x 及更低版本上使用建议的代码时,一切似乎都很好,但是当我在 Android 6.0.1 上使用它时(在 Nexus 5 和模拟器上测试,当有多个应用程序共享内容时) ,我得到空单元格,有时甚至是空的应用程序名称,例如:

在此处输入图像描述

使用非自定义意图选择器时不会出现这种情况:

startActivity(Intent.createChooser(intent, "default chooser"));

在此处输入图像描述

编码

看到解决方案,我创建了下一个代码:

private void test(Intent shareIntent) {
    List<Intent> targetedShareIntents = new ArrayList<>();
    final List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(shareIntent, 0);
    if (!resInfo.isEmpty()) {
        for (ResolveInfo resolveInfo : resInfo) {
            Intent targetedShareIntent = new Intent(shareIntent);
            targetedShareIntent.setClassName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
            targetedShareIntents.add(targetedShareIntent);
        }
        Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(targetedShareIntents.size() - 1), "Select app to share");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
        startActivity(chooserIntent);
    }
}

private void prepareIntentToShare(Intent intent) {
    intent.setAction(android.content.Intent.ACTION_SEND);
    intent.setType("image/*");
    intent.putExtra(Intent.EXTRA_STREAM, mUri);
    intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "title");
    intent.putExtra(android.content.Intent.EXTRA_TEXT, "body");
}

以及测试它的方法:

Intent intent = new Intent();
prepareIntentToShare(intent);
test(intent);

我试过的

我试图改变意图中的各种东西,但没有任何运气。我还试图找出意图的顺序应该是什么(因为它可能很重要),但我没有找到。

最后,我决定将它发布到 Google,假设这是一个错误:

https://code.google.com/p/android/issues/detail?id=202693

问题

  1. 为什么会发生?我可以以某种方式修复它,同时仍然使用本机意图选择器吗?为什么它只发生在 Android 6 及更高版本上?

  2. 例如,我如何将每个项目的正确名称放在那里,例如,我两次看到“twitter”,而其他应用程序确实显示了正确的名称(例如 qr-code-scanner 的名称)?

  3. 是否可以保持应用程序排序的本机行为,如使用显示意图选择器的简单方式所示?也许以应该订购的方式获取应用程序列表?

4

1 回答 1

2

我花一些时间阅读ChooserActivityResolverActivity解决这些问题。

    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setType("text/plain");
    List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, 0);

    if (resolveInfos != null && !resolveInfos.isEmpty()) {
        List<Intent> targetIntents = new ArrayList<>();
        for (ResolveInfo resolveInfo : resolveInfos) {
            ActivityInfo activityInfo = resolveInfo.activityInfo;
            // remove activities which packageName contains 'ttt' for example
            if (activityInfo.packageName.contains("ttt")) {
                continue;
            }
            Intent targetIntent = new Intent(Intent.ACTION_SEND);
            targetIntent.setType("text/plain");
            targetIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.setting_share_app_subject));
            targetIntent.putExtra(Intent.EXTRA_TEXT, context.getString(R.string.setting_share_app_body));
            targetIntent.setPackage(activityInfo.packageName);
            targetIntent.setComponent(new ComponentName(activityInfo.packageName, activityInfo.name));

            // wrap with LabeledIntent to show correct name and icon

            LabeledIntent labeledIntent = new LabeledIntent(targetIntent, activityInfo.packageName, resolveInfo.labelRes, resolveInfo.icon);

            // add filtered intent to a list
            targetIntents.add(labeledIntent);
        }
        Intent chooserIntent;
        // deal with M list seperate problem
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // create chooser with empty intent in M could fix the empty cells problem
            chooserIntent = Intent.createChooser(new Intent(), context.getString(R.string.setting_share_app_title));
        } else {
            // create chooser with one target intent below M
            chooserIntent = Intent.createChooser(targetIntents.remove(0), context.getString(R.string.setting_share_app_title));
        }
        if (chooserIntent == null) {
            return;
        }
        // add initial intents
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[targetIntents.size()]));
        try {
            context.startActivity(chooserIntent);
        } catch (ActivityNotFoundException e) {
            Logger.e(TAG, e, e);
        }
    }

编辑:似乎在 Android Q (10 - API 29) 上这已损坏,并且最多只显示 2 个项目而不是所有项目。在这里再次询问这个问题。

编辑:在此处制作了一个选择要从共享中排除的项目的示例,这应该适用于所有 Android 版本。

于 2016-12-14T10:39:25.200 回答