3

I am trying to handle the IntentSender of Intent.createChooser() to do something when a user selects an app to share an image on. Most the examples I've found here (posted below), require using a BroadcastReceiver as follows:

Intent receiver = new Intent(context, MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, receiver, PendingIntent.FLAG_UPDATE_CURRENT);
String type = "image/*";
Intent share = new Intent(Intent.ACTION_SEND);
share.setType(type);
share.putExtra(Intent.EXTRA_STREAM, awesome_photo_uri);
startActivity(Intent.createChooser(share, "some_title", pendingIntent.getIntentSender()));

My problem with this solution, is located in this line:

Intent receiver = new Intent(context, MyReceiver.class);

The Intent constructor used in these examples require me to make a static MyReceiver class, so I have a class to pass into the second argument of the constructor. But, this causes an issue because I'd like the BroadcastReceiver's onReceive to do stuff in my Fragment. Therefore, I would prefer to create a BroadcastReceiver dynamically in my Fragment.

To no avail, I attempted the following work-around:

Inside MyFragment.kt:

private val receiver: BroadcastReceiver = getBroadcastReceiver()
private val intentFilter = IntentFilter("com.my.app.CHOOSER_ACTION")

override fun onResume() {
    requireContext().registerReceiver(receiver, intentFilter)
    super.onResume()
}

override fun onPause() {
    requireContext().unregisterReceiver(receiver)
    super.onPause()
}

private fun shareImage(imageFile: File) {
    Intent().apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK
        action = Intent.ACTION_SEND
        type = "image/*"
        putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(
            requireContext(),
            "${myPackageName}.fileprovider",
            imageFile
        ))

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            val receiver = Intent("com.my.app.CHOOSER_ACTION")
            val pendingIntent = PendingIntent.getBroadcast(requireContext(), 0, receiver, PendingIntent.FLAG_CANCEL_CURRENT)
            startActivity(Intent.createChooser(this, "Share image using", pendingIntent.intentSender))
        } else {
            startActivity(Intent.createChooser(this, "Share image using"))
        }
    }
}

private fun getBroadcastReceiver() : BroadcastReceiver {
    return object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            intent?.extras?.keySet()?.forEach {
                Log.v("MyTest", "$it: ${intent.extras?.get(it)}")
            }
            doSomethingInMyFragment()
        }
    }
}

Inside AndroidManifest.xml:

<activity android:name="MyActivityThatHasMyFragment" />
    <intent-filter>
        <action android:name="com.my.app.CHOOSER_ACTION" />
    </intent-filter>
</activity>

Unfortunately, the dynamic BroadcastReceiver's onReceive() function is never called after the user presses on a selection. A few questions:

  1. Why does this not work? What am I missing? Am I somehow setting the Intent or IntentFilter incorrectly?
  2. Is it even possible to use a dynamic BroadcastReceiver for handling the IntentSender of createChooser? If not, how can I create a static BroadcastReceiver that triggers something to happen in MyFragment?

Resources:

JHowzer
  • 3,684
  • 4
  • 30
  • 36
  • 3
    On Android 8.0+, implicit broadcasts like yours are banned -- try also calling `setPackage()` on the `Intent` to see if you can get past this, or switch to `createPendingResult()` on your `Activity` (which gives you a `PendingIntent` that triggers `onActivityResult()` on the same activity). You might also see if there are interesting messages in Logcat at the point you interact with the chooser. BTW, the `` element does not belong on the activity. – CommonsWare Jan 16 '19 at 19:20
  • 1
    @CommonsWare Thank you for the createPendingResult() idea. In my fragment, I put `val pendingIntent = requireActivity().createPendingResult(1234, Intent(), PendingIntent.FLAG_CANCEL_CURRENT)` and I'm excited to see that I'm getting the result from my activity's `onActivityResult`. Is there there a way to get it to work with Fragments? In other words, my fragment's `onActivityResult` would handle it instead. Or will I just have to manually call my fragment's `onActivityResult` from my Activity? – JHowzer Jan 21 '19 at 23:08
  • 2
    "Or will I just have to manually call my fragment's onActivityResult from my Activity?" -- yes, sorry. – CommonsWare Jan 21 '19 at 23:34

0 Answers0