Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
376 views
in Technique[技术] by (71.8m points)

android - For the Intent Chooser, is it possible to set which sharing items to show, and in which order?

Background

Before Android Q, it was always possible to set which items to show on the sharing dialog, and in which order. I even wrote about it here.

For example, if you wanted to prioritize some apps over others, you could use:

fun getChooserIntent(context: Context, intent: Intent, chooserTitle: String?, vararg preferredOrderOfApps: String): Intent? {
    val resolveInfos = context.packageManager.queryIntentActivities(intent, 0)
    if (resolveInfos.isNullOrEmpty())
        return null
    val packageNameToOrderMap = HashMap<String, Int>()
    for ((index, packageName) in preferredOrderOfApps.withIndex())
        packageNameToOrderMap[packageName] = preferredOrderOfApps.size - index
    val targetIntents = ArrayList<Intent>()
    for (resolveInfo in resolveInfos) {
        val activityInfo = resolveInfo.activityInfo
        val targetIntent = intent.clone() as Intent
        targetIntent.setPackage(activityInfo.packageName)
        targetIntent.component = ComponentName(activityInfo.packageName, activityInfo.name)
        targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        val labeledIntent = LabeledIntent(targetIntent, activityInfo.packageName, resolveInfo.labelRes, resolveInfo.icon)
        targetIntents.add(labeledIntent)
    }
    targetIntents.sortWith(Comparator<Intent> { lhs, rhs ->
        val lhsPackageName = lhs.`package`!!
        val lhsPriority = packageNameToOrderMap[lhsPackageName] ?: -1
        val rhsPackageName = rhs.`package`!!
        val rhsPriority = packageNameToOrderMap[rhsPackageName] ?: -1
        return@Comparator when {
            lhsPriority > rhsPriority -> -1
            lhsPriority < rhsPriority -> 1
            else -> 0
        }
    })
    val chooserIntent = Intent.createChooser(
            when {
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> Intent()
                else -> targetIntents.removeAt(0)
            }, chooserTitle)
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toTypedArray<Parcelable>())
    return chooserIntent
}

Usage:

        val intent = getShareFileIntent(this@MainActivity, file.absolutePath)
        val chooserIntent = getChooserIntent(this@MainActivity, intent, "look at the results...", "com.ghisler.android.TotalCommander", "com.google.android.gm")
        startActivity(chooserIntent)

This should put "Total Commander" and "Gmail" as the top items. Sample project can be found here.

If you add "com.whatsapp", you could have WhatsApp as the third one.

The problem

It seems EXTRA_INITIAL_INTENTS got very restricted on Q, letting me put only up to 2 items. This means that instead of seeing all items as on previous versions, you would see only the 2 apps I've mentioned.

What I've tried

I've looked at the docs (here for example) , and I've checked some candidates:

  • EXTRA_EXCLUDE_COMPONENTS - used to exclude stuff. Didn't try, but it's not what I need anyway. I want to specify what to show and in which order.
  • EXTRA_INTENT - for some reason when I try to use it, it just opens it directly, without showing the sharing dialog.
  • EXTRA_ALTERNATE_INTENTS - Doesn't seem to do anything
  • EXTRA_CHOOSER_TARGETS - seems to be related to the direct share items, but even then it's restricted.

Looking at the docs, and on Android's source code for it (here), I can see that by writing that it's limited, it's very very limited: Just up to 2 items that I can put:

private static final int MAX_EXTRA_INITIAL_INTENTS = 2;
private static final int MAX_EXTRA_CHOOSER_TARGETS = 2; 

I might be wrong, but I think EXTRA_ALTERNATE_INTENTS isn't limited as such. It's just that I've failed to use it.

When I've found about these problems, I tried to report it on the issue tracker, but I didn't get any response.

The questions

  1. On the native share UI, Is there any way to set which items to show, each with its own Intent, and in which order?

  2. How do you use EXTRA_ALTERNATE_INTENTS ? Should it be used with EXTRA_INTENT ? How come when I tried to use EXTRA_INTENT, it just opened it? What's the use of these extras? Isn't it what I actually ask about?

  3. Seeing that there is EXTRA_CHOOSER_TARGETS, does it mean I can get the direct-share items myself? Maybe it's possible to create a completely customized sharing UI, which looks very similar to the original one, and even has direct-share items?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Let me see if I can answer some of your questions.

On the native share UI, Is there any way to set which items to show, each with its own Intent, and in which order?

You can use what you're using now, but, as you discovered, it's only possible to provide 2 intents to specifically promote to the top. That said, the change to get the system to populate the rest of the list in alpha order is small:

    val chooserIntent = Intent.createChooser(
        when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> intent
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> Intent()
            else -> targetIntents.removeAt(0)
        }, chooserTitle
    )

This actually looks like what you were doing according to the bug report.

Unfortunately, it's not possible to change the title from "Share" when using Intent.ACTION_SEND or Intent.ACTION_SEND_MULTIPLE.

Seeing that there is EXTRA_CHOOSER_TARGETS, does it mean I can get the direct-share items myself?

No. It's provided so that your app can surface its own direct share targets that are appropriate for the action being taken. (source)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...