Android intent via notification not keeping extra data - java

I'm trying to pass a String via an intent stored in a notification.
But when I get the String out of the intent in the new fragment, it's a null and it gives me a NullPointerException.
Code to create notification (in method A of fragment A in activity A)
Notification.Builder mBuilder = new Notification.Builder(getActivity().getBaseContext());
mBuilder.setContentTitle("My first notification");
mBuilder.setContentText("Click to see the details...");
mBuilder.setSmallIcon(R.drawable.ic_launcher);
//Intent maken voor notification
Intent intentVoorNotificatie = new Intent(getActivity(), activity_detail_notification.class);
EditText edTekst = (EditText) getActivity().findViewById(R.id.etTekst);
String strTekstNotificatie = edTekst.getText().toString();
intentVoorNotificatie.putExtra("detailNotificatie", strTekstNotificatie);
//Intent naar PendingIntent converteren
PendingIntent pIntentVootNotificatie = PendingIntent.getActivity(getActivity().getBaseContext(),
0, intentVoorNotificatie, PendingIntent.FLAG_ONE_SHOT);
mBuilder.setContentIntent(pIntentVootNotificatie);
//Notificatie tonen
NotificationManager mNotificationManager = (NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1,mBuilder.build());
Method A of fragment B in activity B
//Haal doorgegeven tekst uit intent
Intent intent = getActivity().getIntent();
String strTekst = intent.getStringExtra("detailNotificatie");
TextView tvTekst = (TextView) getActivity().findViewById(R.id.tvDetailVanNotificatie);
tvTekst.setText(strTekst);
I get the nullPointer on the setText() method due to the String being empty when extracting it from the intent.
Did I do something wrong for data to get lost or dismissed?

Try to change this code `
PendingIntent pIntentVootNotificatie = PendingIntent.getActivity(getActivity().getBaseContext(),
0, intentVoorNotificatie, PendingIntent.FLAG_ONE_SHOT);
to this `
PendingIntent pIntentVootNotificatie = PendingIntent.getActivity(getActivity().getBaseContext(),
0, intentVoorNotificatie, PendingIntent.FLAG_UPDATE_CURRENT);

Related

My notification is not retrieving the extras in pending intent

i have tried most solution but still i don't get the extras when notification is clicked
i tried
1Why the PendingIntent doesn't send back my custom Extras setup for the Intent?
2 Intent.getExtras() always returns null
String itemID = dataSnapshot.child("itemID").getValue(String.class);
Intent intent = new Intent(UserHomeActivity.this, MapsActivity.class);
intent.putExtra("id", itemID);
intent.setAction(itemID);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
int uniqueInt = (int) (System.currentTimeMillis() & 0xfffffff);
PendingIntent pendingIntent = PendingIntent.getActivity(UserHomeActivity.this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ){
CharSequence name ="001";
NotificationChannel notificationChannel = new NotificationChannel(Channel_ID, name,NotificationManager.IMPORTANCE_HIGH );
notificationChannel.setDescription("This is description");
NotificationManager notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);
Notification.Builder builder = new Notification.Builder(getApplicationContext(),Channel_ID);
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentText(text)
.setContentTitle("New Price Added")
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_DEFAULT);
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());
notificationManagerCompat.notify(001,builder.build());
}else {
Notification.Builder builder = new Notification.Builder(getApplicationContext());
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentText(text)
.setContentTitle("New Price Added")
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_MAX);
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getApplicationContext());
notificationManagerCompat.notify(uniqueInt,builder.build());
Here is my Code For retrieving the extras
if(extras != null){
// extract the extra-data in the Notification
String msg = extras.getString("id");
String sss = getIntent().getParcelableExtra("id");
Toast.makeText(this, sss+" ids "+msg+ " "+extras.toString(), Toast.LENGTH_SHORT).show();
}
imageButton = findViewById(R.id.call);
imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent phoneIntent = new Intent(Intent.ACTION_DIAL);
phoneIntent.setData(Uri.parse("tel:0818283848"));
startActivity(phoneIntent);
}
}); ```
Did you try debugging the extras? try putting break points and see what your are receiving in through the intent. Check if the extra is actually getting passed or not.
If you are not receiving the extra, then your intent is faulty.
If you are receiving the extra, then the logic of how you access extras is wrong.

How to reference a view in a customized notification

In the below posted code i am create a notification with a customized layout. the layout of the notification contains three action buttons.
the problem i have now is, i can not reference any of the buttons in the code so that I can navigate to another activity based on the action button clicked.what i am trying to do is when Action button 1
is clicked then Activity 1 shows up, when Action button 2 is clicked then Activity 2 shows up and so on.
Please let me know how to reference the views in customized layout of the notification?
code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Using RemoteViews to bind custom layouts into Notification
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_notification);
String notification_title = "Notification_Title";
String notification_text = "Notification_Text";
// Open NotificationView Class on Notification Click
Intent intent = new Intent(this, NotificationReply.class);
// Send data to NotificationView Class
intent.putExtra("title", notification_title);
intent.putExtra("text", notification_text);
// Open NotificationView.java Activity
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
// Set Icon
.setSmallIcon(R.mipmap.ic_launcher)
// Set Ticker Message
.setTicker("Ticker")
// Dismiss Notification
.setAutoCancel(true)
// Set PendingIntent into Notification
.setContentIntent(pIntent)
// Set RemoteViews into Notification
.setContent(remoteViews);
Intent intentAction1 = new Intent(this, ActAction1.class);
PendingIntent pendingIntentActAction1 = PendingIntent.getBroadcast(this, 1,intentAction1, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.btn_action1, pendingIntentActAction1);
Intent intentAction2 = new Intent(this, ActAction2.class);
PendingIntent pendingIntentActAction2 = PendingIntent.getBroadcast(this, 2,intentAction2, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.btn_action2, pendingIntentActAction2);
Intent intentAction3 = new Intent(this, ActAction3.class);
PendingIntent pendingIntentActAction3 = PendingIntent.getBroadcast(this, 3,intentAction3, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setPendingIntentTemplate(R.id.btn_action3, pendingIntentActAction3);
// Create Notification Manager
NotificationManager notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Build Notification with Notification Manager
notificationmanager.notify(0, builder.build());
}
}
The key success for navigation is to use proper pending intent and use different values for your requestCode.
You could receive the event in broadcastReceiver building the pending intent (e,g, with params) that way:
private PendingIntent buildPendingIntent(String someurl) {
Intent intent= new Intent(mContext, SomeReceiver.class);
final Uri uri = Uri.parse(someurl);
intent.setData(uri);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(KEY, VALUE)
return PendingIntent.getBroadcast(mContext.getApplicationContext(),
CONSTANT_FOR_THIS_INTENT_TYPE, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
}
Or you could navigate to activity just by pending intent:
private PendingIntent buildPendingIntent2() {
Intent intent = new Intent(mContext, SomeActivity.class);
intent.putExtra(KEY, VALUE);
settingsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
return PendingIntent.getActivity(mContext.getApplicationContext(),
OTHER_CONSTANT_FOR_OTHER_ACTION,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Please notice that CONSTANT_FOR_THIS_INTENT_TYPE and OTHER_CONSTANT_FOR_OTHER_ACTION must have different values
And after you have this pending intents you should attach them to your views:
view.setOnClickPendingIntent(com.app.btn1, buildPendingIntent1());
view.setOnClickPendingIntent(com.app.btn2, buildPendingIntent2());
You have to use RemoteViews#setOnClickPendingIntent() API:
Equivalent to calling setOnClickListener(android.view.View.OnClickListener) to launch the provided PendingIntent.
Intent firstIntent = new Intent(context, FirstActivity.class);
PendingIntent firstPendingIntent = PendingIntent.getBroadcast(this, 0, firstIntent, 0);
RemoteViews notificationView = ...
notificationView.setOnClickPendingIntent(R.id.first_button, firstPendingIntent);
You have to use RemoteViews#setOnClickPendingIntent() API:
I get your mistake you are trying to launch an activity with PendingIntent.getBroadcast() which only send a broadcast message, so ideally a broadcast receiver should be registered with the same intent filter action. In your case it should ideally be PendingIntent.getActivity
Now you can launch with the following pending intent the flag value was incorrect I can assume for everyone else, hence pending intent wasn't fired.
Intent firstIntent = new Intent(context, FirstActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(appContext, 101, firstIntent,
PendingIntent.FLAG_UPDATE_CURRENT); // For opening activity ideally this should work
If this doesn't work you can try sending a broadcast and listen for it to verify that broadcast is also sent or not:-
PendingIntent pendingIntent = PendingIntent.getBroadcast(appContext, 0, firstIntent, PendingIntent.FLAG_ONE_SHOT); // for sending broadcast and listens in broadcast reciever

Notification PendingIntent hard bug (or really simple one)

I'm trying to debug this for ages now and I just can't seem to find the problem:
I have a broadcast receiver, which receives the broadcast successfully.
The notification has two actions ("buttons"):
firstIntent = null;
secondIntent = null;
firstPendingIntent = null; //first "button" to join with the first intent
secondPendingIntent = null; //second "button" to join with the second intent
if(boolean){
//relevant
firstIntent = new Intent(getBaseContext(), NotificationFunctions.class).putExtra("action", "do_this");
secondIntent = new Intent(getBaseContext(), NotificationFunctions.class).putExtra("action", "do_that");
}else{
firstIntent = new Intent(getBaseContext(), NotificationFunctions.class).putExtra("action", "do_another_this");
secondIntent = new Intent(getBaseContext(), NotificationFunctions.class).putExtra("action", "do_another_that");
}
firstPendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, firstIntent, PendingIntent.FLAG_UPDATE_CURRENT);
secondPendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, secondIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle(notification_title)
.setContentText(notification_text)
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
.setDefaults(Notification.DEFAULT_SOUND)
.addAction(R.drawable.abc_cab_background_top_holo_light, first_option, firstPendingIntent)
.addAction(R.drawable.abc_cab_background_top_holo_dark, second_option, secondPendingIntent)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_stat_name)
.build();
Whenever I debug in the broadcastReceiver, for some reason, action from extras always logs "do_that", even if I click the first or second button of the notification. Any reason for this? I cant really seem to understand why.
public class NotificationFunctions extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
boolean feedback;
String action = intent.getExtras().getString("action");
Log.wtf("...", action); //logs do_that
}}
Any reason for this?
Because firstPendingIntent == secondPendingIntent.
If there already is a PendingIntent matching your request, getBroadcast() returns the existing PendingIntent. FLAG_UPDATE_CURRENT says to replace the extras in the Intent wrapped inside the PendingIntent.
In one of your two getBroadcast() calls, replace 0 with some other number, to get distinct PendingIntent objects.
Also, I recommend that you replace getBaseContext() and getApplicationContext() with this. Only use getBaseContext() and getApplicationContext() when you know precisely why you are using them.

Android Multiple Notifications and with multiple intents

I have a fairly simple app that takes the input from a user and then sets it as a notification. The user can create as many notifications as he/she likes. I want the user to click the notification and get taken to a new activity called ResultActivity. ResultActivity in turn reads in the putExtras from the notifications intent and shows it to the user. The code below allows me to do almost everything I wanted, except anytime a notification is pressed, I receive the putExtra of the last created notification.
Intent notificationIntent = new Intent(ctx, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(ctx, i,notificationIntent,PendingIntent.FLAG_CANCEL_CURRENT);
NotificationManager nm = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = ctx.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(res,R.drawable.ic_launcher))
.setTicker("Remember to " + text.getText())
.setWhen(System.currentTimeMillis()).setAutoCancel(true)
.setContentTitle(text.getText());
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);
String pass = text.getText().toString();
resultIntent.putExtra("title", pass);
resultIntent.putExtra("uid", i);
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);
new Uri.Builder().scheme("data").appendQueryParameter("text", "my text").build();
builder.setContentIntent(resultPendingIntent);
Notification n = builder.build();
n.flags = Notification.FLAG_NO_CLEAR;
nm.notify(i++, n);
text.setText(null);
Open the application
Type in "One"
Hit ok
Notification is sent
Open the application
Type in "Two"
Hit ok
Notification is sent
Now you have two notifications. One that says "One" and one that says "Two". If you click on the notification "Two" it takes you to a screen that says "Two". Perfect!
If you click on the notification "One" it takes you to a screen that says "Two". BROKEN!
ResultActivity.java
public class ResultActivity extends Activity {
String title = null;
TextView text;
int i=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
text = (TextView) findViewById(R.id.textView1);
title = getIntent().getStringExtra("title");
i = getIntent().getIntExtra("uid", 0);
text.setText(title);
}
I know this was a lot time ago but i feel that the answers have not said anything about the problem in your code.
So the problem is pretty much here
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
So you create a pendingIntent from the stackbuilder whith the flag of update_current. If you look at FLAG_UPDATE_CURRENT it says
/**
* Flag indicating that if the described PendingIntent already exists,
* then keep it but replace its extra data with what is in this new
* Intent. For use with {#link #getActivity}, {#link #getBroadcast}, and
* {#link #getService}. <p>This can be used if you are creating intents where only the
* extras change, and don't care that any entities that received your
* previous PendingIntent will be able to launch it with your new
* extras even if they are not explicitly given to it.
*/
public static final int FLAG_UPDATE_CURRENT = 1<<27;
So what happens in your use case is that you create two identical pendingintents from the stackbuilder and the second intent overrides the first one . Actually you never create a second you just update the extras of the first one.
So unfortunately there is no available flag for your use case , but there is a good hack around it. What you can do is use the setAction of your resultIntent and place a random string or a string that makes sense to your app.
eg. resultIntent.setAction("dummy_action_" + notification.id);
This will make your resultIntent unique enough , so that the pendingIntent will create it rather than updating a previous one.
Set different requestCode helps me create and update current intent.
val pendingIntent = PendingIntent.getActivity(
this,
notificationID,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
You create multiple intents that are mixed. I cleaned up the code (but did not test it)
NotificationManager nm = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = ctx.getResources();
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, ResultActivity.class);
String pass = text.getText().toString();
resultIntent.setData(new Uri.Builder().scheme("data")
.appendQueryParameter("text", "my text").build());
resultIntent.putExtra("title", pass);
resultIntent.putExtra("uid", i);
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);
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
builder.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(
BitmapFactory.decodeResource(res,
R.drawable.ic_launcher))
.setTicker("Remember to " + text.getText())
.setWhen(System.currentTimeMillis()).setAutoCancel(true)
.setContentTitle(text.getText())
.setContentIntent(resultPendingIntent);
Notification n = builder.build();
n.flags = Notification.FLAG_NO_CLEAR;
nm.notify(i++, n);
text.setText(null);
Use some random requestCode to seperate two notifications
PendingIntent pendingIntent = PendingIntent.getActivity(context, CommonTools.getRandomNumber(1, 100),
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
public int getRandomNumber(int min, int max) {
// min (inclusive) and max (exclusive)
Random r = new Random();
return r.nextInt(max - min) + min;
}
Just set your pending request code to System.currentTimeMillis().toInt(). It worked.
val pendingNotificationIntent: PendingIntent = PendingIntent.getBroadcast(
this,
System.currentTimeMillis().toInt(),
notificationIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

Android - Why Activity is Open after click notification?

I have a function to display a notification, which I call from various activities.
public static void CrearNotificacion(Context pContexto, String pTituloBarra, String pTitulo, String pTexto){
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) pContexto.getSystemService(ns);
Notification notification = new Notification(R.drawable.icono, pTituloBarra, System.currentTimeMillis());
notification.defaults |= Notification.DEFAULT_SOUND;
Intent notificationIntent = new Intent(pContexto, pContexto.getClass());
PendingIntent contentIntent = PendingIntent.getActivity(pContexto, 0, notificationIntent, 0);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.setLatestEventInfo(pContexto, pTitulo, pTexto, contentIntent);
mNotificationManager.notify(1, notification);
}
works perfect, the problem is that pressing on the notification opens the activity that created the notification and that's wrong, I think the notiifcacion activity should not open when I select the notification.
Why? there any way to fix this?
I do not want to open any activity when I select the notification.
thanks from now.
In order to have no action taken when clicking the notification, you may set an empty Intent as follows:
Intent notificationIntent = new Intent() ;
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.contentIntent = contentIntent;
Intent notificationIntent = new Intent(pContexto, pContexto.getClass());
i guess this is the line you have to change with
Intent notificationIntent = new Intent(pContexto, yourClass.class);

Categories