Android Notification Action is not fired (PendingI

2020-02-25 01:16发布

问题:

I am trying to add an Notification action item in my app which is a music player. When a stream is started a notification should be triggered and an stop button for the stream should be displayed in the notfication. The notification working fine so far, I am having trouble with the stop action item. Here is how it is declared in the service starting the stream:

Intent stopIntent = new Intent(this, MusicPlayerNew.class);
stopIntent.putExtra("STOP", "STOP");
PendingIntent stopPendingIntent = PendingIntent.getActivity(this, 0,
                stopIntent, PendingIntent.FLAG_UPDATE_CURRENT, null);
mBuilder.addAction(R.drawable.ic_stat_stop, "Stop", stopPendingIntent);

Now in the onResume()-method of my activity I check with getIntent().getStringExtra() for the "STOP" extra, but the intent I retrieved via getIntent() has no extras set :(

I also tried to check to send an broadcast (i have a broadcast receiver working to communicate from the service to the activity)

Intent stopIntent2 = new Intent(MusicPlayerNew.STOP_MEDIAPLAYER);
PendingIntent stopPendingIntent2 = PendingIntent.getBroadcast(this, 0,
                stopIntent2, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.addAction(R.drawable.ic_stat_stop, "Stop", stopPendingIntent2); 

Now this works if the activity is currently in the foreground. If the activity is in the background the stop button does nothing :(

EDIT: I have the BroadcastReceiver in my Activity as a private class

private class DataUpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
..
}}

In the onResume() register my app for this receiver:

intentFilter = new IntentFilter(STOP_MEDIAPLAYER);
registerReceiver(dataUpdateReceiver, intentFilter);

onPause()

unregisterReceiver(dataUpdateReceiver);

Now if I remove the unregistering from the onPause()-method the broadcast is received even if the app/activity is not in the foreground anymore. But is this the right way to do it? I got this register/unregister-stuff from a tutorial on the web i think..

回答1:

I find solution in this thread on google code https://code.google.com/p/android/issues/detail?id=61850

To fix it you must add PendingIntent.FLAG_CANCEL_CURRENT flag to your PendingIntent.

PendingIntent stopPendingIntent2 = PendingIntent.getBroadcast(this, 0,
            stopIntent2, PendingIntent.FLAG_CANCEL_CURRENT);


回答2:

This is very late answer but it may help someone:

You should choose the right kind of Pending intent based on the intent you want to run. Here are some Examples:

For Activity use below:

Intent i = new Intent(this, YourActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);

For Service use below:

Intent i = new Intent(this, YourService.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);

For Broadcast Receiver use below:

Intent i = new Intent(this, YourReciver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);

You may need to change the request code and Flags if required



回答3:

I ran into this problem today and it was caused by the activity not being registered or added to AndroidManifest.xml. I thought I had it in there but it wasn't. Also, no errors were being logged by trying to invoke the action with its intent.

I figured this out by creating an intent and then calling startAcitivty(intent) without using a notification. It then gave me an error stating the activity was likely missing from the manifest.

If none of the other answers solve your problem then hopefully this will. Usually tricky problems are the result of something simple and silly.



回答4:

I ran into this problem today. In my case it was using cached intent extras from a previous instance of the intent as all the parameters for the pendingIntent constructors was same. I found two solutions for this...

  1. Using FLAG_CANCEL_CURRENT as mentioned by Nik.
  2. Passing an unique requestCode to the pendingIntent as follows

    PendingIntent pi = PendingIntent.getService(this, UNIQUE_ID, pi, 0);
    

In my case, the second method solved the problem as I need to keep the previous notifications alive. May be this will help someone with similar issue.



回答5:

More than using broadcast receiver, you should use a service and declare a new action in your service this way:

public final String ACTION_STOP = "yourpackagename.ACTION_STOP";

And then create your intents like this:

Intent stopIntent = new Intent(this, YourService.class).setAction(YourService.ACTION_STOP);
PendingIntent stopPendingIntent = PendingIntent.getService(this, 0, stopIntent, 0);

Of course, stop playback in your service's function startCommand, if the intent's action equals ACTION_STOP.

This should do the trick ;)



回答6:

You do not receive the broadcast when it is in the background because you are unregistering in onPause. Move the unregisterReceiver code to onDestroy function. This will be called only when the activity is destroyed. Or you can unregister once the expected event has occurred.



回答7:

There are multiple questions here:

Part 1: Why is your intent not receiving the "STOP" extra? Though it is not seen in the code you have provided, I wanted to confirm if you are using the flag FLAG_ACTIVITY_SINGLE_TOP for the notification intent ? If so, the intent you receive in your activity would be the intent that started the activity and hence the "STOP" extra will not be available. You will need to extend the onNewIntent() is this case (where the new intent is sent). More info here.
If you have not used FLAG_ACTIVITY_SINGLE_TOP, then it means that a new activity is created when notification is tapped, in which case the Intent must have the "STOP" parameter. If you can provide me all relevant code, I can help you better.

Part 2: Using Broadcast Receiver This is not straight forward, as you already discovered. You would need to unregister in onDestroy and if your activity is closed by the user, the onDestroy may be called and your broadcast receiver may not active at the time the notification is tapped by the user. If you dont unregister at all, it may seem to be working, but this is a memory leak, GC may clean up anytime which could lead to a crash in your program, ie., you MUST unregister. If you need to go with broadcast receiver approach, you need to have a service to do this and service comes with its own pitfalls -> restart by system, battery drain etc. I would strongly recommend you go with your first approach.



回答8:

I had a very similar issue but a very different solution. Pending intent is also not fired if you have declared <service android:enabled="false"></service> in your manifest.xml file.

Replace from android:enabled="false" to android:enabled="true"

This might not be a direct issue of the problem. But if you create the service in android studio using default template it automatically adds these properties to the service.



回答9:

For me, the solution was to set the flags of the intent :

resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                Intent.FLAG_ACTIVITY_CLEAR_TASK);