2

From the examples this looked straightforward. Maybe you can show me what I did wrong. I can't get an activity to receive a broadcast sent from a local service.

I have Activity1 that start Service1:

startService(new Intent(Activity1.this, Service1.class));

Activity1 then starts Activity2:

startActivity(new Intent(Activity1.this, Activity2.class));

Service1, a local service, listens for downloads:

protected final BroadcastReceiver service2DownloadBroadcastReceiver = new BroadcastReceiver()
{
    public void onReceive(final Context context, final Intent intent)
    {
        ...
        broadcastDownloadFinished(Uri.fromFile(downloadedFile));

The broadcast receiver of Service1 then broadcasts its own message:

protected Intent broadcastDownloadFinished(final Uri uri)
{
    final Intent intent = new Intent(ACTION_DOWNLOAD_FINISHED).setData(checkNotNull(uri));
    sendBroadcast(intent);

Activity2, which is in the foreground at the time, listens for the ACTION_DOWNLOAD_FINISHED intent using its own broadcast receiver:

private final BroadcastReceiver activity2DownloadBroadcastReceiver = new BroadcastReceiver()
{
    public void onReceive(final Context context, final Intent intent)
    {
        Log.i(Activity2.class.getSimpleName(), "Received download event: " + intent.getAction() + " " + intent.getData());

Activity2 of course registers the receiver:

protected void onResume()
{
    super.onResume();
    final IntentFilter downloadIntentFilter = new IntentFilter();
    downloadIntentFilter.addAction(ACTION_DOWNLOAD_FINISHED);
    registerReceiver(activity2DownloadBroadcastReceiver, downloadIntentFilter);

In case it matters, ACTION_DOWNLOAD_FINISHED is something like "com.example.intent.action.DOWNLOAD_FINISHED".

Service1 receives the download manager event in its receiver and apparently broadcasts its own custom event, but Activity2 never seems to receive it. What did I do wrong? Is it a problem to broadcast an intent in the middle of processing another one? (I wouldn't think so---this is asynchronous, right?)

Update: Just to make sure there is no problem sending a broadcast in the middle of receiving a broadcast, I changed my broadcast code to actually perform the broadcast three seconds later on the main thread:

    Log.i(getClass().getSimpleName(), "...ready to broadcast");     
    final Intent intent = new Intent(ACTION_DOWNLOAD_FINISHED).setData(checkNotNull(uri));
    mainThreadHandler.postDelayed(new Runnable()
    {
        public void run()
        {
            Log.i(getClass().getSimpleName(), "...broadcasting");
            sendBroadcast(intent);
            Log.i(getClass().getSimpleName(), "...broadcasted");                
        }
    }, 3000);
    Log.i(getClass().getSimpleName(), "...scheduled to broadcast");

As expected, the log says:

...ready to broadcast
...scheduled to broadcast
...broadcasting
...broadcasted

Yet nothing is received in the activity. Please help.

2 Answers 2

3

Eureka! I found it! The problem is that I supplied a data URI in my broadcast intent. The Android intent matching rules get a little complicated. If you supply a data URI, then your intent filter must specify a matching MIME type.

Unfortunately, although the Android documentation says that the data type can be inferred from the data URI, apparently Android doesn't know that a file://.../example.jpg is an image. So this doesn't work:

intentFilter.addDataType("image/*");

However, instead of specifying a type, I can specify a scheme that I accept:

intentFilter.addDataScheme("file");

That works! It's a little rough---and a little artificial to restrict my broadcasts to file: URIs, but as that's all I'm using for the moment, it works.

Note that apparently I could manually specify the MIME type in the intent when I broadcast it, but that's too much trouble for now, as I'm downloading images from Picasa so I already know that they are images (and don't care the specific MIME type). And if it gets too much trouble, I could ditch the whole setData() thing altogether and set an extra---but of course I want to do things the Right Way.

Sign up to request clarification or add additional context in comments.

2 Comments

You beat me to it. I hadn't spotted this self-answer and have just been looking at your code. I was going to suggest leaving the setData(...) out of the code just to see what happened - obviously (from your answer) it would have worked. Sorry I couldn't get on to it earlier - I had a late shift at work today. Glad you've got the solution.
Thanks so much for taking the time to look at this, MisterSquonk. This was driving me batty. I hope this winds up helping someone. Good night.
0

have you included your receiver in your activity's manifest?

<receiver
  android:name=".YourReceiver">
  <intent-filter>
    <action
      android:name="intent_name"></action>
  </intent-filter>
</receiver>

4 Comments

No. It is my understanding that this is not needed for a manually-registered receiver. Furthermore, the receiver is an inner class and cannot be registered in the manner you describe.
sure it can. set android:name=".ParentClass$ReceiverName"
Maybe I'm off-base here, but 1) I'm using an anonymous inner class, so you'd have to guess at the generated ...$Name, 2) the whole point of the <receiver> element is to have Android automatically instantiate the receiver on an as-needed basis, and Android can't automatically instantiate my non-static, anonymous inner class, 3) my receiver class is already instantiated and registered, so the <receiver> element is not needed. Trying to get back on-topic: is <receiver> required for manually-registered receivers or not? I believe they are not.
Just to follow up: when manually registering a broadcast receiver, a static definition in the manifest is not needed; see developer.android.com/reference/android/content/… .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.