Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 279
android developer Avatar asked Sep 08 '19 22:09

android developer


People also ask

Which of the following will force the app chooser to show?

You have to run lab3a_MyBrowser before you run lab3a_IntentsLab , so that the browser gets installed on your phone. Then it will be visible to your chooser.

What is the use of intent createChooser () method?

Most commonly, ACTION_SEND action sends URL of build-in Browser app. While sharing the data, Intent call createChooser() method which takes Intent object and specify the title of the chooser dialog. Intent. createChooser() method allows to display the chooser.

Which method of the Intent class allows you to pass information to the target?

putExtra method is used.

How to make share Intent in Android?

For all types of sharing, create an intent and set its action to Intent. ACTION_SEND . In order to display the Android Sharesheet you need to call Intent. createChooser() , passing it your Intent object.


1 Answers

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)

like image 100
Nicole Borrelli Avatar answered Sep 21 '22 08:09

Nicole Borrelli