I am using GCMBaseIntentService in my service class which extends GCMBaseIntentService I override the method onMessage(Context,Intent).
The code goes here :
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
//String message = getString(R.string.gcm_message);
String id=intent.getExtras().getString("event_id");
String message=intent.getExtras().getString("title");
String eventname=intent.getExtras().getString("event_name");
generateNotification(getApplicationContext(), id, message, eventname);
}
private static void generateNotification(Context context, String id, String message, String eventname)
{
int icon = R.drawable.ic_stat_gcm;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
//new intent
Intent notificationIntent = new Intent(context, EventDescription.class);
notificationIntent.putExtra("event_id", id);//need this id in the eventdescription activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, eventname, message, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
}
The problem is that, while I click this notification and in the Eventdescription activity and extract the extras from intent and print the ID. It shows the correct value only the first time, after that for every notification it just shows the 1st value all the time. Please help!
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.notificationsfinal);
start=1;
end=15;
next=(Button)findViewById(R.id.nextbtn);
prev=(Button)findViewById(R.id.prevbtn);
statusview=(TextView)findViewById(R.id.status);
notification_list_view=(ListView)findViewById(R.id.not_listview);
updatestatus();
getNotifications();
}
private void getNotifications()
{
eventnotifierapp app=(eventnotifierapp)getApplication();
id=getIntent().getExtras().getString("event_id");
db=new MyDB(this);
}
This is my EventDescription activity where i am retreiving this event_id
Try this
PendingIntent intent = PendingIntent.getActivity(context, **uniqueKey**, notificationIntent, 0);
Please note requestCode of the getActivity of Pending intent should be unique.So just pass
unique value for every notification.You can put time stamp or even the id which you receive
from the server. I have tried this and this works.Do share your feedback
Your subsequent Intents aren't different enough, so they're being recycled. Specifically, changing the extras doesn't make a distinct Intent from the perspective of the system.
The docs for Intent.filterEquals explain that you will need to change one or more of: action, data, type, class, and categories. One approach, therefore, is to stick some distinguishing information (in your case the event_id) into the data URI; you don't have to use this URI for anything but it ensures that your intents will be distinct.
There's more info in this related question.
Related
I'm delivering a notification which has 2 action buttons namely "Accept" and "Reject".
I'm following this Github repo.
When user clicks "Accept", certain conditions are checked and the logic is performed accordingly.
UPDATE 2.0 - The problem is that upon clicking "Accept" button, operation is happening successfully but the notification isn't disappearing from the status bar because the id generating here: m = (new Random()).nextInt(10000); is different from here: actionIntent.putExtra("id", NotificationARBroadcastReceiver.m); every single time!
Here's the code for notification:
Intent notificationIntent = new Intent(getBaseContext(), NotificationARBroadcastReceiver.class);
notificationIntent.putExtra(NotificationARBroadcastReceiver.NOTIFICATION, getNotificationNewRequestService());
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), m, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, pendingIntent);
Here's getNotificationNewRequestService():
private Notification getNotificationNewRequestService() {
mBuilder =
new NotificationCompat.Builder(getBaseContext())
.setSmallIcon(R.mipmap.app_icon_1)
.setContentTitle("Title")
.setContentText("text...");
Intent resultIntent = new Intent(getBaseContext(), Profile.class);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
getBaseContext(),
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// for action button
Intent actionIntent = new Intent(getBaseContext(), MyBroadcastSender.class);
actionIntent.putExtra("id", NotificationARBroadcastReceiver.m);
PendingIntent actionPendingIntent = PendingIntent
.getBroadcast(getBaseContext(),
0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setAutoCancel(true);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.addAction(R.drawable.ic_accepted_request_black_24dp, "Accept", actionPendingIntent);
mBuilder.addAction(R.drawable.ic_close_black_24dp, "Reject", null);
return mBuilder.build();
}
Here's NotificationARBroadcastReceiver.java file:
public class NotificationARBroadcastReceiver extends BroadcastReceiver {
public static String NOTIFICATION = "notification";
public static NotificationManager mNotifyMgr;
public static int m;
#Override
public void onReceive(Context context, Intent intent) {
m = (new Random()).nextInt(10000);
Log.d("mMain", String.valueOf(m));
mNotifyMgr =
(NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
Notification notification = intent.getParcelableExtra(NOTIFICATION);
notification.defaults |= Notification.DEFAULT_SOUND;
notification.defaults |= Notification.DEFAULT_VIBRATE;
mNotifyMgr.notify(m, notification);
}
}
Here's MyBroadcastSender.java file:
public class MyBroadcastSender extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Broadcast Received by MyBroadcastSender.", Toast.LENGTH_SHORT).show();
int id = intent.getIntExtra("id", 1);
// send back to your class
Intent newIntent = new Intent();
newIntent.setAction(context.getString(R.string.broadcast_id));
newIntent.putExtra("id1", id);
context.sendBroadcast(newIntent);
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
Toast.makeText(context, "Broadcast sent back.", Toast.LENGTH_SHORT).show();
}
}
and here's MyBroadcastReceiver.java file:
// BroadcastReceiver
public class MyBroadcastReceiver extends BroadcastReceiver {
public MyBroadcastReceiver(){
super();
}
#Override public void onReceive(Context context, Intent intent) {
int id2 = intent.getIntExtra("id1", 1);
if (intent.getAction() != null && intent.getAction().equals(getString(R.string.broadcast_id))) {
NotificationARBroadcastReceiver.mNotifyMgr.cancel(id2);
Intent intent1 = new Intent(MyService.this, MainActivity.class);
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent1);
Toast.makeText(context, "Broadcast received by MyBroadcastReceiver. Now, you can perform actions.",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "Intent is null.", Toast.LENGTH_SHORT).show();
}
}
}
In getNotificationNewRequestService(), I'm putting notification id as an extra in "id", then in MyBroadcastSender.java, I'm getting this extra as int id = intent.getIntExtra("id", 1); and then putting again as newIntent.putExtra("id1", id); and then finally getting it in MyBroadcastReceiver.java as int id2 = intent.getIntExtra("id1", 1); and trying to remove the notification using it as NotificationARBroadcastReceiver.mNotifyMgr.cancel(id2);.
Sorry for this much code, I've to upload it all as they all are necessary.
What I want is to know how to deliver the same notification id from NotificationARBroadcastReceiver.java (which is a separate java file) to MyBroadcastReceiver(which is an inner class in MyService.java)?
Update 1.0- this is what happened when I printed out the values of m, mMain, id, id1:
D/m: 0
D/mMain: 9994
D/id: 0
D/id1: 0
Assuming getNotificationService() == getNotificationNewRequestService() Looks like the NotificationARBroadcastReceiver isn't called before the notfication is built and displayed.
You would do better to generate the notification id where you create the notification and just add it to the intent there as well you don't need to make.
So call getNotificationNewRequestService() from NotificationARBroadcastReceiver.recieve() and make sure the notification ids match up.
Edit:
move:
m = (new Random()).nextInt(10000);
before:
actionIntent.putExtra("id", NotificationARBroadcastReceiver.m); // this will be 'm'
Result:
int m = (new Random()).nextInt(10000);
Intent actionIntent = new Intent(getBaseContext(), MyBroadcastSender.class);
actionIntent.putExtra("id", m);
Log.d(getClass().getSimpleName(), "Notification Id is : " + m);
then, you can check what values are in id, id1 and id2. Don't forget to call .notify() with same Id you got from m.
You can, also, create getRandomNotificationId() and getLastGeneratedNotificationId() methods. Whenever you generate an Id, store it in public static integer variable, so that you can access it throughout the class.
Problem might be that you are accessing m from NotificationARBroadcastReceiver before initializing it. So, it will definitely be 0. And, you mentioned something about println error, are you using System.out.println()?
Before Edit:
As seen on your new edit, try closing notification before starting it:
m = (...);
// some code here
mNotifyMgr.cancel(m);
mNotifyMgr.notify(m, notification);
and see if your issue gets resolved.
I'm trying to implement a GCM client & server architecture. Everything works fine so far.
Except: When my activity is closed and I get a new notification by GCM, the notification is displayed in the notification bar. So far, so good. But when I click on the notification, my activity is opened but the onReceive event of my BroadcastReceiver is not triggered. :(
If the Activity is open, the onReceive is triggered perfectly.
Do you know, what's wrong here?
Cheers
Chris
So this is my service:
package xy;
import ...;
public class GcmIntentService extends IntentService
{
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
public GcmIntentService()
{
super("GcmIntentService");
}
#Override
protected void onHandleIntent(Intent intent)
{
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
final int notificationID = (int) (Math.random() * 100000000);
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("GCM notification: Send error", extras.toString(), notificationID);
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
sendNotification("Deleted messages on server", extras.toString(), notificationID);
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
sendNotification(extras.getString(Utils.TICKER_TITLE_MESSAGE_KEY), extras
.getString(Utils.TICKER_TEXT_MESSAGE_KEY), notificationID);
Intent intentToBroadCast = new Intent(Utils.DISPLAY_MESSAGE_ACTION);
intentToBroadCast.putExtra(Utils.MESSAGE_EXTRA_BUNDLE_KEY, extras);
intentToBroadCast.putExtra(Utils.NOTIFICATION_ID_KEY, notificationID);
sendBroadcast(intentToBroadCast);
}
}
// Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(final String aTitle, final String aText, final int aNotificationID)
{
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this,
DemoActivity.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(
R.drawable.ic_stat_gcm).setContentTitle(aTitle).setStyle(
new NotificationCompat.BigTextStyle().bigText(aText)).setContentText(aText);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(aNotificationID, mBuilder.build());
}
}
And here's the Receiver in my activity, which is to display the incoming message:
public class GcmResultReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extras = intent.getBundleExtra(Utils.MESSAGE_EXTRA_BUNDLE_KEY);
String s = extras.getString(Utils.CONTENT_TITLE_MESSAGE_KEY) + "\n"
+ extras.getString(Utils.CONTENT_TEXT_MESSAGE_KEY);
mDisplay.setText(s);
int notificationID = intent.getIntExtra(Utils.NOTIFICATION_ID_KEY, -1);
if (-1 != notificationID) m_SentNotificationIDs.add(notificationID);
if (m_IsVisible) {
clearNotifications();
}
}
};
Everything was copied and adapted from the GCM example from the Google Android tutorial.
The BroadcastReceiver is triggered before the notification is displayed in the notification bar. It contains the code that displays the notification and opens the activity when it is tapped (unless it is starting an intent service that does that work).
Therefore, if you see the notification, it means the BroadcastReceiver was triggered.
You don't need an additional BroadcastReceiver for passing the notification data from the first receiver to your app. If you wish to pass the notification data to the Activity that is being launched when the notification is tapped, you can pass it to the intent used to launch that activity.
Suppose you change your sendNotification call to:
sendNotification(extras, notificationID);
Then you can implement it like this:
private void sendNotification(Bundle extras, final int aNotificationID)
{
mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Intent demoIntent = new Intent(this, DemoActivity.class);
demoIntent.putExtras (extras);
demoIntent.putExtra (Utils.NOTIFICATION_ID_KEY, notificationID);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, demoIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(
R.drawable.ic_stat_gcm).setContentTitle(extras.getString(Utils.TICKER_TITLE_MESSAGE_KEY)).setStyle(
new NotificationCompat.BigTextStyle().bigText(extras.getString(Utils.TICKER_TEXT_MESSAGE_KEY))).setContentText(extras.getString(Utils.TICKER_TEXT_MESSAGE_KEY));
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(aNotificationID, mBuilder.build());
}
This way your DemoActivity will get the notification id and all the extras holding the data of the notification.
You can access them in your activity's onCreate (or perhaps it would be better to do it in onResume, in case your Activity is already started).
I'm using Intents to save data and recover them in others places of my application. I have used them in others places, but now, it's not working as I hope.
public class GCMIntentService extends GCMBaseIntentService {
public GCMIntentService() {
super(ConstantsGCM.GCM_SENDER_ID);
}
#Override
protected void onMessage(Context context, Intent intent) {
...
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager notManager = (NotificationManager) context.getSystemService(ns);
String room = intent.getExtras().getString(ConstantsGCM.GCM_ROOM);
Intent notIntent;
PendingIntent contIntent;
Notification notif;
notif = new Notification(icon, textStatus, time);
notIntent = new Intent(contexto,RoomsActivity2.class);
Bundle b2 = new Bundle();
b2.putString(ConstantsRooms.ROOM, room);
notIntent.putExtras(b2);
contIntent = PendingIntent.getActivity(contexto, 0, notIntent, 0);
notif.setLatestEventInfo(contexto, tittle, description, contIntent);
notif.flags |= Notification.FLAG_AUTO_CANCEL;
notManager.notify((int)(Math.random()*1000), notif);
This code is executed when a notification is coming. When I click this notification, it's executed the Activity RoomsActivities2.class. Here, I just call this code:
public String getMessageString(String cod){
String result = "";
bundle = getIntent().getExtras();
if (bundle != null){
result = bundle.getString(cod);
}
return result;
}
But, I didn't get the last data saved in the Intent. What's it wrong? I guess that I'm not using it correctly. Why can't I get the data from the activity?
What I think that it's happening it's:
The application gets a lot of notifications, the first one works right. But, if I keep getting more notifications, the data isn't override and I always get the first one although when I debug the code, I'm setting the another data.
OK, it's been a while since I've worked with pending intents, but I remember two things:
replace:
contIntent = PendingIntent.getActivity(contexto, 0, notIntent, 0);
with:
contIntent = PendingIntent.getActivity(contexto, 0, notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
That will keep the bundle around.
BUT that flag will override any existing pending intents with the newest one, you might not want that.
If you have multiple pending intents from the same context with the same intent (but different bundles!), you can use the 2nd parameter.
contIntent = PendingIntent.getActivity(contexto, requestCode, notIntent, PendingIntent.FLAG_UPDATE_CURRENT);
as long as every pending intent has a unique requestCode, and even though the google dev's docs say the parameter isn't used, it actually does serve a purpose for identifying pending intent and allows duplicates with different bundles.
I'm trying to run an activity through a notification and event onCreate I would like to "redirect". To this add a thought on information in the Intent class. An important feature is that the class that generates the notification is performed through a service. I retrieve the context from getApplicationContext method provided by the class android.app.Application. Whenever I call method getExtras() is returning null. What am I doing wrong?
public class OXAppUpdateHandler {
private void addNotification(Context context, int iconID,
CharSequence tickerText, CharSequence title, CharSequence content) {
CharSequence notificationTicket = tickerText;
CharSequence notificationTitle = title;
CharSequence notificationContent = content;
long when = System.currentTimeMillis();
Intent intent = new Intent(context, MainActivity_.class);
intent.setFlags(
Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(OPEN_UPDATE_ACTIVITY_KEY, 1);
PendingIntent pendingIntent =
PendingIntent.getActivity(context, 0, intent, 0);
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
Notification notification =
new Notification(iconID, notificationTicket, when);
notification.setLatestEventInfo(context, notificationTitle,
notificationContent, pendingIntent);
notificationManager.notify(NOTIFICATION_ID, notification);
}
public static boolean isUpdateStart(Intent intent) {
Bundle bundle = intent.getExtras();
boolean result = bundle != null &&
bundle.containsKey(OPEN_UPDATE_ACTIVITY_KEY);
if (result) {
bundle.remove(OPEN_UPDATE_ACTIVITY_KEY);
}
return result;
}
}
#EActivity(R.layout.activity_main)
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (OXAppUpdateHandler.isUpdateStart(getIntent())) {
startActivity(new Intent(this, UpdateActivity_.class));
}
}
}
I'm going to lean out the window and guess that your problem is here:
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
You are passing intent to getActivity() and expecting that you will get back a PendingIntent that matches your Intent and includes your extras. Unfortunately, if there is already a PendingIntent floating around in the system that matches your Intent (without taking into consideration your Intent extras) then getActivity() will return you that PendingIntent instead.
To see if this is the problem, try this:
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
This says that if there is already a PendingIntent that matches your Intent somewhere in the system that it should replace the extras with the ones in your intent parameter.
(1) Check here to make sure you are using the put/get extras correctly as I don't see the code where you are adding data the intent.
(2) It looks like you are not calling get intent and get extra and, as a result, not actually getting anything from the bundle (assuming that information extists). If you are checking for a boolean value you should get the data you place in the bundle as follows:
Bundle bundle = getIntent().getExtras();
if (bundle.getBooleanExtra("WHATEVER"){
//whatever you want to do in here
}
My target: download files in parallel, and when file downloads complete, I get notifications.
Those notifications are suppose to launch an activity when you click on it which gets unique parameters through putExtra.
The problem is that I can't have different values in each launch of that activity.
Each time the activity, which is being launched through the notification bar, launches it destroys the extra of the ones which haven't been launched yet (the ones that still appear on the notification bar).
How do I keep all my notifications with their own parameters?
Here is my code:
if (messagesManager == null)
{
messagesManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
notification = new Notification(R.drawable.icon, message, System.currentTimeMillis());
// for launch activity
Intent intent = new Intent(context, DialogActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("fileName", fileName); //- this is where i put my extra's!!
intent.putExtra("onSdcard", onSdcard);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(context, "DownloadManager", message, contentIntent);
notification.flags = notification.FLAG_AUTO_CANCEL;
int noticeId = generateNotificationId(requestId);
messagesManager.notify(noticeId, notification);
Now this is the dialog activity:
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Intent i = getIntent();
boolean onSdcard = i.getBooleanExtra("onSdcard", true);
String fileName = i.getStringExtra("fileName");
...
}
I tried to use this technique as it was written in another post here, but it didn't work.
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Please check the linked duplicate,
you need two things
you need to add an action string
the action string must be unique, probably a timestamp added to it would be good