Pending Intent from Broadcast Receiver to Activity - old data received - android

I found similar questions, but none of the solutions helped me.
I have a broadcast receiver intercepting sms and forwarding the sms text to another activity. The other activity should display the latest received text.
But the other activity is ALWAYS displaying the first text received after the app was started for the first time. New sms-texts are not displayed.
What I tried:
Played around with the parameters of Pending Intent (unique random int and all 4 update options) - didnt help so far.
PendingIntent contentIntent = PendingIntent.getActivity(context, **rand.nextInt(50) + 1**, intent, **FLAG_UPDATE_CURRENT**);
Here's the relevant code from the Broadcast Receiver, the notification which is also triggered shows the new and correct text each time.
private void showNotification(Context context) {
Intent intent = new Intent(context, DisplayMSG.class);
intent.putExtra(EXTRA_MESSAGE, str);
Random rand = new Random();
PendingIntent contentIntent = PendingIntent.getActivity(context, rand.nextInt(50) + 1, intent, FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("RPT Notification")
.setContentText(str + Integer.toString(n));
mBuilder.setContentIntent(contentIntent);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
And here's the part from the receiving activity:
Intent intent = getIntent();
String message = intent.getStringExtra(SmsReceiver.EXTRA_MESSAGE);
TextView textView = (TextView) findViewById(R.id.tView);
textView.setText(message);
Let me know if you need more code. But I hope this should be sufficient, since it's basically working, it's just not transferring the new texts.
EDIT:
Thanks to CommonsWare here is the solution, I just added this method to the receiving activity:
#Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
TextView textView = (TextView) findViewById(R.id.tView);
textView.setText(intent.getStringExtra(SmsReceiver.EXTRA_MESSAGE));
}

And here's the part from the receiving activity
If the activity is already running, that is the wrong Intent. Override onNewIntent() and use the Intent that is passed in to it. getIntent() always returns the Intent used to create the activity, not any subsequent ones that brought an existing instance back to the foreground.

Related

How to process GCM notifications, launching activity per alert without erasing other alerts

I guess it is hard to explain just by reading the title of this question. I am coding an app that gets ambient factors alerts (temperature, etc) sent by a known server to GCM, and then GCM sends it back to the phone. The whole GCM works well. The problem is when notifications arrive. It is thought to send notifications to the phone when an alert happens (a trigger). Then clicking on the alert launches the activity to display the alert. That is OK, but if there is 2 or more alerts on waiting to be clicked, it will only process one, ignoring the rest ("mensaje"). This is how my notification inside a class that extends extends GcmListenerService looks like.
public static void showAlerts(Context context, String mensaje)
{
Intent notificationIntent = new Intent(context.getApplicationContext(), MainActivity.class);
notificationIntent.putExtra("mensaje", mensaje);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
Random r = new Random();
PendingIntent pendingIntent = PendingIntent.getActivity(context, r.nextInt(),
notificationIntent, 0);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(context)
.setContentTitle(context.getString(R.string.app_name))
.setContentText("Nueva alerta recibida")
.setSmallIcon(R.drawable.termometrorojo)
.setNumber(UtilidadesGCM.num_notificaciones++)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setDefaults(Notification.DEFAULT_LIGHTS)
.setAutoCancel(true).build();
notificationManager.notify(0, notification);
}
Then in MainActivity, I have the code to process this, and open the activity to display the alert
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String nuevaAlerta = intent.getExtras().getString("mensaje");
procesaAlerta(nuevaAlerta);
//mDisplay.append(nuevaAlerta + "\n");
}
};
public void procesaAlerta (String alerta)
{
Intent intent = new Intent(this, Alertas.class);
intent.putExtra("mensaje" , alerta);
startActivity(intent);
}
The Alertas class will parse the message fine and display it in its activity, but will only do that once. If there are more than 2 alerts stacked to be read, it only process one. If there is one, it works ok. Sorry if I odn't explain better, but it hard not showing all the code.
Thanks!
Try with writing this line
notificationManager.notify( new Random().nextInt(), notification);
instead of
notificationManager.notify(0, notification);
Your notification id is every time same so your last notification only work. Every new notification id is replaced by id 0. So i use random id instead of fixed id 0. I think above code will work for you

Send Notification ID through to activity for each notfication

I am seriously confused now, I have been reading several SE examples and they all seem to be doing slightly different things.
What i want to do: Is have a single Activity called NotificationActivity, when I click on a notification it must open that activity and provide the activity with a DeviceId. I don't want to override or update any pending activities. Each activity should be its own intent.
There should only be once instance of NotificationActivity.
here is the code I have so far:
MyGcmListenerService:
Intent intent = new Intent(this, NotificationActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
//ADD My Extras
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_ID, content.DeviceId);
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_TYPE_ID, content.DeviceTypeId);
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_NAME, content.DeviceName);
//
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(content.DeviceName)
.setContentText("Notification")
.setAutoCancel(true)
.setSound(ingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setGroup("Mi:" + content.DeviceId)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NotificationID++, notificationBuilder.build());
and my NotificationActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification);
deviceId = getIntent().getExtras().getLong(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_ID, -1);
deviceName = getIntent().getExtras().getString(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_NAME, "");
deviceTypeId = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_DEVICE_TYPE_ID, 0);
What am I missing here/ I think I am getting mixed up with all the different flags and launcher types.
If there is already an NotificationActivty in memory, I want to close it and open a new one with the latest intent. If there are 3 notifications on the users phones, and they click on all three. it must open the NotificationActivty for the last clicked Notification.
There must be an issue with my pending intent?
In NotificationActivity, you collect int or long value using following code i.e.
notificationID = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, 0);
then please pass a proper value with putExtra() i.e. if collect int then pass Integer.parseInt(content.DeviceId) or collect long then pass Long.parseLong(content.DeviceId)
hope it's helpful to you
In Notification class add this line
intent.putExtra(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, NotificationID);
In NotificationActivity
notificationID = getIntent().getExtras().getInt(CommonBundleAttributes.CONNECTING_ACTIVITY_NOTIFICATIONID, 0);

Android - Having trouble with calling a service from an action button of a notification

I want to be able to have a button that copies the text from a notification to the clipboard. The notification is sent through the google's GCM service.
The first time the notification arrives when I press the "copy" button everything is fine and the text goes into the clipboard by the service that the button sends an intent to. The second time a notification arrives with different text when I press the "copy" button the content of the first notification goes into the clipboard instead of the new one. When I debug the code, it seems that the intent that's calling the service has the new content, but the service that puts it into the clipboard runs with the parameters of the old notification, as if the same session of the service is awaken with the old intent.
Any clue why this is happening?
// Called by the GCM notification handler
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,new Intent(this, MainActivity.class), 0);
Intent notificationIntent = new Intent(this, clipboardService.class);
notificationIntent.putExtra("tool",msg);
PendingIntent serviceIntent = PendingIntent.getService(this, 0, notificationIntent, 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_gcm)
.setContentTitle("Here's your text!")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg)
.addAction(R.drawable.ic_stat_gcm, "Copy", serviceIntent); // <--- The intent will have the right (new) value on the second run
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
This is the service that the notification actions calls to:
public class clipboardService extends IntentService {
public clipboardService() {
super("clipboardService");
}
#Override
protected void onHandleIntent(Intent intent) { //This intent will have the values of the first intent to fire, instead of the updated one.
String msg = (String) intent.getExtras().get("tool");
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("2android",msg);
clipboard.setPrimaryClip(clip);
}
Although it is very late to answer your question, but recently I faced the same issue and Google led to me this unanswered question. So here is my understanding if in future someone dig this up.
This is because PendingIntent uses cached intent extras from previous instance of the intent unless you explicitly tell it not to. There are two ways to do that...
Use FLAG_CANCEL_CURRENT or FLAG_UPDATE_CURRENT (best in your case) as flag while constructing the PendingIntent. The first flag will automatically dismiss the previous PendingIntent and create a completely new one and the second one will only update the extras for the PendingIntent and save the overhead of creating a completely new one.
PendingIntent.getService(this, 0, notificationIntent,
FLAG_CANCEL_CURRENT | FLAG_UPDATE_CURRENT);
Pass an unique requestCode to the PendingIntent constructor everytime. This will generate unique pending intents for everytime so that you can access the extras associated with a particular intent later. I believe this is not required in your case.
PendingIntent.getService(this, UNIQUE_ID, pi, 0);

onclicklistener for notification [duplicate]

This question already has answers here:
How to set click listener for notification?
(3 answers)
Closed 9 years ago.
I had set a notification in my app. Its working fine. If i click the notification in statusbar it takes to my app.
Now i need to set some work if the notification is clicked where can i set this?
Is there any method that implicitly got invoked when a notification is clicked?
Also i want to remove that notification if it is clicked,how to do so?
this is my code
notifManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Intent inty=getIntent();
note = new Notification(R.drawable.icon, "New E-mail", System.currentTimeMillis());
PendingIntent intent = PendingIntent.getActivity(MainActivity.this, 0, inty, 0);
note.setLatestEventInfo(MainActivity.this, "New E-mail", "You have one unread message.", intent);
notifManager.notify(R.string.search_hint, note);
You could add some extra data to the intent and then in your activity look for it in the onCreate and onNewIntent methods.
For example:
inty.putExtra("came from notification", true);
You can then read that out via the intent passed to onNewIntent or in onCreate by using getIntent().
intent.getBooleanExtra("came from notification", false);
Try to call broadcastReceiver it may helpful for your requirement,
Intent notificationIntent = new Intent(this, dummy_activity.class);
notificationIntent.setAction("android.intent.action.MAIN");
notificationIntent.addCategory("android.intent.category.LAUNCHER");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT |
Notification.FLAG_AUTO_CANCEL);
// Now, once this dummy activity starts send a broad cast to your parent activity and finish the pending activity
//remember you need to register your broadcast action here to receive.
BroadcastReceiver call_method = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action_name = intent.getAction();
if (action_name.equals("call_method")) {
// call your method here and do what ever you want.
}
}
};
registerReceiver(call_method, new IntentFilter("call_method"));

Window already focused, ignoring focus gain of: com.android.internal.view

Unfortunately, I was unable to find a resolution to this issue in other StackOverflow posts so I apologize in advance for re-posting this question. Essentially, I have an AppWidget that creates a Notification. I want the user to click the Notification to launch an Activity. The AppWidget and Activity are in the same APK.
The following code is all in the AppWidget. Clicking on the Notification broadcasts a custom Intent which is received by the AppWidget.
The problem is that the Activity does not appear to launch, even though logcat demonstrates that the custom Intent has indeed been broadcast. The only clue is the logcat message reiterated in the post title.
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Constants.BROWSER_INTENT)) {
launchActivity(context, R.layout.appwidget, R.id.launch_button, Activity.class);
}
super.onReceive(context, intent);
}
private void displayNotification(Context context, String ticker, String title, String msg) {
Intent intent = new Intent(context, ThisWidget.class);
intent.setAction(Constants.BROWSER_INTENT);
PendingIntent pending = PendingIntent.getActivity(context, 0, intent, 0);
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.icon, ticker, System.currentTimeMillis());
notification.setLatestEventInfo(context, title, msg, pending);
notificationManager.notify(1, notification);
}
Some notes:
Pressing a button to execute launchActivity() works (it launches the
Activity)
launchActivity uses Intent.FLAG_ACTIVITY_NEW_TASK as
recommended by Android lifecycle documentation
Has anyone solved this issue when launching an Activity from a Notification press?
er, figures, I answered my own question just minutes after posting it. I guess I was over-complicating the implementation by using an Intent action. I changed these lines:
Intent intent = new Intent(context, ThisWidget.class);
intent.setAction(Constants.BROWSER_INTENT);
PendingIntent pending = PendingIntent.getActivity(context, 0, intent, 0);
to this:
Intent intent = new Intent(context, Activity.class);
PendingIntent pending = PendingIntent.getActivity(context, 0, intent, 0);
and it worked.
Sorry for the bogus post.

Categories

Resources