Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Intent.createChooser() need a BroadcastReceiver and how to implement?

The following snippet, called from my implementation of onOptionsItemSelected(), works nicely to carry the user from my app to a mail client with email address, subject and body pre-filled. I'm using this as a simple way to let the user give me feedback.

String uriText =
    "mailto:" + emailAddress +
    "?subject=" + subject +
    "&body=" + body;

Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse(uriText));
startActivity(Intent.createChooser(emailIntent, "Pick an email app:"));

When the mail app opens (on my Nexus S with Android 4.0.4), LogCat outputs the following, and I can't figure out why; Google and SO searches for createChooser unregisterReceiver seem fruitless, and I can't find many examples of createChooser() that also call unregisterReceiver() in a way that helps this situation.

04-08 21:26:19.094: E/ActivityThread(27894): Activity com.android.internal.app.ChooserActivity has leaked IntentReceiver com.android.internal.app.ResolverActivity$1@4150aac8 that was originally registered here. Are you missing a call to unregisterReceiver()?

04-08 21:26:19.094: E/ActivityThread(27894): android.app.IntentReceiverLeaked: Activity com.android.internal.app.ChooserActivity has leaked IntentReceiver com.android.internal.app.ResolverActivity$1@4150aac8 that was originally registered here. Are you missing a call to unregisterReceiver()?

04-08 21:26:19.094: E/ActivityThread(27894): at android.app.LoadedApk$ReceiverDispatcher.(LoadedApk.java:763)

This feels like an Android bug because my own code doesn't call registerReceiver(), so why is Android complaining that I need to call unregisterReceiver()?

like image 714
Jacob Marble Avatar asked Apr 09 '12 04:04

Jacob Marble


People also ask

What is the use of intent createChooser () method?

The system will always present the chooser dialog even if the user has chosen a default one. If your intent created by Intent. createChooser doesn't match any activity, the system will still present a dialog with the specified title and an error message No application can perform this action .

What is the use of BroadcastReceiver?

Android BroadcastReceiver is a dormant component of android that listens to system-wide broadcast events or intents. When any of these events occur it brings the application into action by either creating a status bar notification or performing a task.

How do I send data from BroadcastReceiver to activity?

Intent intent = getIntent(); String message = intent. getStringExtra("message"); And then you will use message as you need. If you simply want the ReceiveText activity to show the message as a dialog, declare <activity android:theme="@android:style/Theme.

What is the difference between a broadcast receiver and an intent filter?

An IntentFilter specifies the types of intents to which an activity, service, or broadcast receiver can respond to by declaring the capabilities of a component. BroadcastReceiver does not allows an app to receive video streams from live media sources.


1 Answers

I see this as well on my Galaxy Nexus with 4.0.4, but only if there's only one option and the chooser doesn't appear.

This is a bug in Android source - not much you can do about it. Their ResolverActivity registers a BroadcastReceiver, but doesn't always unregister it.

More detail:

Intent.createChooser() will start a ResolverActivity. In onCreate(), the activity calls

mPackageMonitor.register(this, false);

mPackageMonitor is a BroadcastReceiver and within register() it registers itself on the activity. Normally, the receiver is unregistered in onStop(). However, later in onCreate() the code checks how many options the user can choose from. If there's only one it calls finish(). Since finish() is called in onCreate() the other lifecycle methods are never called and it jumps straight to onDestroy() - leaking the receiver.

I didn't see a bug for this in the Android issues database, so I created one.

For more info you can see this in code:

  • ResolverActivity
  • PackageMonitor

As a side note, Google uses email as an example of when you wouldn't want to use a chooser so you may consider just launching the intent normally. See the javadocs for Intent#ACTION_CHOOSER.

like image 183
blazeroni Avatar answered Sep 20 '22 06:09

blazeroni