Problem with Receiver which receives Intents from Notification - java

I have a code that send a broadcast to a broadcast receiver.
Intent intentPrev = new Intent(ACTION_PREV);
PendingIntent pendingIntentPrev = PendingIntent.getBroadcast(this, 0, intentPrev, PendingIntent.FLAG_UPDATE_CURRENT);
LocalBroadcastManager.getInstance(this).sendBroadcast(intentPrev);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);
In another class I have a Receiver:
private BroadcastReceiver NotificationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("PREVIOUS")){
playPrev();
}
}
};
And in onCreate method I register this receiver:
LocalBroadcastManager.getInstance(this).registerReceiver(NotificationReceiver, new IntentFilter("PREVIOUS"));
The main aim was to reach the following result: when user clicks on button Previous in notification, the previous song will play. But when I run the app and choose the music I can't listen to music, as always the previous plays. So, it seems that there's a perpetual loop somewhere. What's the matter? How to solve this problem if I want to play only one previous song but not all previous songs?

There are two types of broadcasts: system broadcasts and local broadcasts.
Local broadcasts work through LocalBroadcastManager exclusively. If you see anything else tied to "broadcast", 99.99% of the time, that is referring to system broadcasts.
In particular, PendingIntent.getBroadcast() gives you a PendingIntent that will send a system broadcast. That, in turn, means that your receiver needs to be set up to receive a system broadcast, either because:
It is registered in the manifest with a <receiver> element, or
It is registered dynamically by calling registerReceiver() on a Context (not on LocalBroadcastManager)
Note that on Android 8.0+, implicit broadcasts (ones with just an action string) are banned, in effect. If you elect to register your receiver in the manifest, use an Intent that identifies the specific receiver (e.g., new Intent(this, MyReceiverClass.class)). If you elect to register your receiver via registerReceiver()... I think there is a recipe for how to handle that, but I forget the details.

Related

Android Notification Click to Broadcast Receiver getting same intent string

I have a broadcast receiver which is triggered on a notification click. I'm passing a string in the intent of notification for the broadcast receiver. The values of the string differs everytime however when I am testing my app, I can only see the value I received the first time I clicked the notification. Now every value I'm getting from my notification to the broadcast receiver is same despite passing new values.
My code:
//Creating notification
Intent snoozeIntent = new Intent(getApplicationContext(), ServiceLauncherBroadcast.class);
snoozeIntent.putExtra("order_id", orderId);
//In the broadcast receiver
startWorkManager(intent.getStringExtra("order_id")
//Manifest
<receiver android:name = ".utils.ServiceLauncherBroadcast" />
In your PendingIntent please use this flag:
PendingIntent.FLAG_CANCEL_CURRENT

How do I restart rather than recreate an Activity after a notification click in Android?

I have some code that sends out a notification that a download is completed, when this notification is clicked, I want it to restart my activity.
Currently, the notification is created in a BroadcastReceiver. This is the section where I added the Intents to the notification.
NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Intent resultIntent = new Intent(context, CurrentActivity.class);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK );
PendingIntent resultPendingIntent = PendingIntent.getActivity(
context,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Notification.Builder builder = new Notification.Builder(getApplicationContext());
builder.setContentIntent(resultPendingIntent);
Right now what this does is destroy my CurrentActivity by calling the onDestroy() method, then calls onCreate() to create a new instance. This is an issue for me as my onDestroy() unbinds my BoundService from my activity. I would much rather have my Activity just restart (onStop() then onRestart() then onStart()) so my onCreate() and onDestroy() methods can handle the binding and unbinding and my onStart() method handles the changes to the UI.
Is there a way to do this?
I think you might consider setting the intent flags differently to achieve the behavior that you want.
resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Handle your UI changes in your onResume activity if required. Hope that helps.
Try to set your activity flag to be
resultIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
See the flag official document from here: https://developer.android.com/reference/android/content/Intent#FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.

Android notification returns to the wrong activity

Hi all,
I am implementing a notification in a service which when clicking on the notification once it appears - It opens an activity.
I have this code in my service class inside a runnable that runs nonstop every few seconds:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(android.R.drawable.ic_dialog_email)
.setContentTitle(notificationTitle)
.setContentText(notificationMessage);
NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();
builder.setStyle(bigText);
Intent resultIntent = new Intent(this, openemailactivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
Notification notification = builder.build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(0, notification);
In my notification activity named "openemailactivity" I have a button which has a code in it to return the user to the home activity called "MainActivity":
btnReturnToMainScreen.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
Everything works fine until I restart my Android phone, the service loads on boot (as intended) and then generates a notification and then I click on it.
Then, when I click on it, the "openemailactivity" activity opens well also as intended, and then I click the button that opens the "MainActivity" (The above code) and it does that O.k.
And now the problem starts !
After this other activity was opened ("MainActivity"), and then the notification pops up again by the service (Notification timer\checking runs in a timed Handler\Runnable that runs nonstop) - and then I click on the notification itself that was created -
the activity that it should call ("openemailactivity") is not called anymore ! instead - the last called activity pops up ("MainActivity"), which is wrong !
The problem starts only when I restart my phone, the service loads on boot, notification is generated, I click on it, It opens the right activity, and then I call the code from the button (OnClickListener).
I don't have a clue on how to solve this problem.
What do you think can be the problem ?
What am I doing wrong and how can I solve it ?
Thanks for any reply.
Strange but it looks like I found an answer (Hopefully - It needs to get more comprehensive testing since Surprises always exist in this environment).
I tried to set:
resultIntent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
in the notification code that exists in the service, right after declaring this variable (resultIntent).
As for now it looks like it works !
By looking at the Android documentation for this flag, it looks like it may explain the problem that I had:
https://developer.android.com/reference/android/content/Intent.html
(Search for the explanation of: "FLAG_ACTIVITY_CLEAR_TOP").

Starting an Android notification at startup

This question is based off of this previous question of mine: Android - Set notification to never go away
I now realize that I need something to be triggered at startup to trigger the notification.
From my previous question, it looks like I can take two routes. Either start a service, or use a BroadcastReceiver. I think that starting a service is a little overkill (but what do I know). I am stuck while going with the BroadcastReceiver route. It works in general, but when I take my code for a notification I get a bunch of errors.
This is my code:
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("My notification")
.setContentText("Hello World!");
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);
//Intent.putExtra("My Notification");
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(i, mBuilder.build());
My errors:
Any ideas on this?
Summary:
Is a service or broadcast receiver better (in this situation)?
How do I solve these errors in my code (when you hover they say they are undefined)?
Replace all instances of this on error lines with context.
BroadcastReciever does not implement a context unlike Activity and Service. All methods in which you have error require an instance of context

AlertDialog not shown after clicking Notification

I am triying to do the following:
My app has an AsyncTask that eventually creates an AlertDialog to request the user to isert a code. This can happend when the app is in the foreground, so I launch a notification to inform the user and my idea is that once he clicks the notification, the main activity with the AlertDialog is shown.
Nevertheless what is happening is that once the user clicks on the notification, just the activity where the AlertDialog is supposed to be is shown and I get a WindowLeaked exception probably caused by the Dialog.
There is the code that I am using to launch the notification (from the method onProgressUpdate of the AsyncTask):
public void launch_notification(){
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(context.getString(R.string.opening_request_notification_title))
.setContentText(context.getString(R.string.opening_request_notification_text));
/* The intent must be created with an specific content and then frozen to be used
later using a pending intent.
*/
Intent notificationIntent = new Intent(context, Main.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notificationBuilder.setContentIntent(pendingIntent);
notificationBuilder.setAutoCancel(true);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
}
Any idea will be welcome.
Thanks a lot :)
Better to create a separate Activity(example DialogActivity) and in your manifest set for DialogActivity.
Your notification creation seems fine and you invoke the method from onProgressUpdate which is also fine.
So there must be something wrong with your activity and the way it handles the dialog.
If you could provide your Main class we could know for sure, but what I guess is happening that in your AsyncTask you show some sort of dialog, perhaps a progress dialog.
If that is the case then when you get the notification (on progress update) and you click it you start Main activity again, so you end up creating another instance of main activity, and hence the leaking window.
Try adding the flag FLAG_ACTIVITY_CLEAR_TOP.
As the API states:
If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.
Hope that this will help you out.

Categories