I'm trying to dismiss a notification from an .addAction() without having to open the app. The problem is when the button is pressed nothing happens, the onReceive() method doesn't trigger.
Here is the code on the MainActivity:
Intent notificationIntent = new Intent(mContext, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.putExtra("id", SOMENUMBER);
PendingIntent pIntent = PendingIntent.getBroadcast(mContext, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notification = new NotificationCompat.Builder(mContext);
notification.setContentTitle("");
notification.setContentText(t);
notification.setSmallIcon(R.mipmap.ic_launcher);
notification.setOngoing(true);
notification.addAction(R.mipmap.ic_launcher, "Dismiss", pIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(SOMENUMBER, notification.build());
And on other class I have the reciever:
public class Notification extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(intent.getIntExtra("id", 0));
}
}
And the reciever on the AndroidManifest.xml file:
<receiver android:name=".MainActivity">
<intent-filter>
<action android:name="io.github.seik.Notification" />
</intent-filter>
</receiver>
Your naming conventions are confusing. Android already has a class called Notification, so you probably shouldn't call your receiver Notification :-(
If MainActivity extends Activity then you need to have a manifest entry for it that looks like this:
<activity android:name=".MainActivity"/>
For your BroadcastReceiver, you need a manifest entry like this:
<receiver android:name=".Notification"
android:exported="true"/>
Since you are using an explicit Intent to launch your BroadcastReceiver, you don't need to provide an <intent-filter> for it. Since the BroadcastReceiver will be started by the NotificationManager, you need to make sure that it is exported.
You then need to create the PendingIntent so that it actually launches your BroadcastReceiver, so change this:
Intent notificationIntent = new Intent(mContext, MainActivity.class);
to this:
Intent notificationIntent = new Intent(mContext, Notification.class);
Related
I have the following code:
public void sendNotification() {
try {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(android.R.drawable.ic_dialog_alert);
final Intent intent = new Intent(this, NotifyBroadcastReceiver.class);
//Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.journaldev.com/"));
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
builder.setContentIntent(pendingIntent);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.logo));
builder.setContentTitle("Notifications Title");
builder.setContentText("Your notification content here.");
builder.setSubText("Tap to view the website.");
builder.setAutoCancel(true);
final Intent noted = new Intent(this, NotifyBroadcastReceiver.class);
noted.setAction("com.mawaeed.common.LaunchActivity");
PendingIntent notedpendingIntent = PendingIntent.getBroadcast(this, 0, noted, 0);// PendingIntent.FLAG_UPDATE_CURRENT ) ;
builder.addAction(0, "Noted", notedpendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Will display the notification in the notification bar
notificationManager.notify(1, builder.build());
}catch(Exception exo) {
Toast.makeText(this, exo.toString(),Toast.LENGTH_LONG).show();
}
}
Also I have my BroadcastReceiver
public class NotifyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"ddd",Toast.LENGTH_LONG).show();
Toast.makeText(context,"app",Toast.LENGTH_LONG).show();
}}
I am calling sendNotification from FirebaseMessagingService, Notification appears normally.
public void onMessageReceived(RemoteMessage remoteMessage) {
sendNotification();
}
When clicking on the notification or Noted action, BroadcastReceiver onReceive not calling,
I already registered my BroadcastReceiver in mainafist
<receiver android:name=".NotifyBroadcastReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
</intent-filter>
</receiver>
The strange thing is I created a new application and copied all the code above to it, and I called the sendNotification from onCreate(), and when clicking on the notification it calls onReceive without problem.
I also tried same with my Application and called sendNotification from onCreate of my main activity, Notification appears but clicking on notification or Noted action not calling onReceive
Why it is not working from my application
I had to uninstall the app first then install it again, and now it works.
I am using the FirebaseMessagingService for getting notifications and opening the app upon clickng the notification. But everytime i click the notification the app opens the MainActivity instead of the intended ResultActivity. I also followed docs from the PendingIntent docs and still does the same.
private void createNotification( String messageBody) {
Intent intent = new Intent( this , ResultActivity.class );
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent resultIntent = PendingIntent.getActivity( this , 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
// PendingIntent resultPending = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
Uri notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder( this)
.setContentTitle("VERA")
.setContentText(messageBody)
.setAutoCancel( true )
.setSound(notificationSoundURI)
.setContentIntent(resultIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, mNotificationBuilder.build());
}
Here is my Manifest.
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ResultActivity"
android:launchMode="singleTask"
android:excludeFromRecents="true"
android:taskAffinity=""></activity>
EDIT: I tried to pass some extra strings, but the main activity is not even receiving anything. Is it possible that the notif is only triggering its default method to launch the app?
Create an Intent that starts the Activity.
Set the Activity to start in a new, empty task by calling setFlags() with the flags FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TASK.
Create a PendingIntent by calling getActivity().
Like,
Intent notifyIntent = new Intent(this, ResultActivity.class);
// Set the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Create the PendingIntent
PendingIntent notifyPendingIntent = PendingIntent.getActivity(this, 0,
notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Then you can pass the PendingIntent to the notification as usual:
NotificationCompat.Builder mNotificationBuilder= new NotificationCompat.Builder(this, "CHANNEL_ID");
builder.setContentIntent(notifyPendingIntent);
...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(0, mNotificationBuilder.build());
Apparently there is no way to trigger the onMessageReceived by using the FCM console only. It will only be triggered if i use other ways to send data messages.
Creating notification:
PendingIntent pIntent = PendingIntent.getActivity(context, (int) taskId, intent, 0);
intent.setAction(Utils.MARK_AS_DONE);
PendingIntent pIntentMarkAsDone = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setTicker(ticker)
.setContentTitle(title)
.setContentText(description)
.setSmallIcon(getAlarmIcon(type))
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),R.mipmap.ic_launcher))
.setContentIntent(pIntent)
.addAction(0, context.getString(R.string.mark_as_done), pIntentMarkAsDone);
Notification notification = builder.build();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int) taskId, notification);
I added the adding using a pending intent with getBroadcast.
Receiver:
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Log to check
}
}
This class should "receive" the action. I also add on Manifest
Manifest:
<receiver android:name=".NotificationReceiver">
<intent-filter>
<action android:name="<package_name>.MARK_AS_DONE"/>
</intent-filter>
</receiver>
Well, onReceive is not receiving. What am I doing wrong?
TL;DR: Create a fresh Intent, rather than reusing the one in intent, and get rid of the <intent-filter> from the <receiver>.
Your first line is:
PendingIntent pIntent = PendingIntent.getActivity(context, (int) taskId, intent, 0);
This implies that intent identifies some activity. If you created this via new Intent(context, YourActivityClass.class), then it has a ComponentName set inside of it, identifying your activity.
Then, you call setAction() on intent and use it with getBroadcast(). However, other than setting (or replacing) the action, everything else in intent is the same as it was. In particular, the ComponentName identifying the activity is still there. So, when the broadcast is sent, Android cannot deliver it, as the component is invalid (an activity cannot directly receive a broadcast), and the action string is ignored (as once a ComponentName is set on an Intent, things like actions and categories no longer count for routing).
So, I recommend that you create two Intent objects, one for the activity, one for the receiver.
Note that you do not need an action string for the receiver. You can use the explicit Intent constructor (new Intent(context, NotificationReceiver.class)). In fact, having the action string on the receiver is bad for security, as now any app can send you that broadcast. So, I recommend removing the <intent-filter> and using an explicit Intent to create your broadcast PendingIntent.
I want to open an Activity when I click on the notification from the Status bar. I have seen this answered on StackOverflow but none of these answers work for me. This is my code:
notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setProgress(100, 0, false);
notificationBuilder.setAutoCancel(true);
notificationBuilder.setSmallIcon(R.drawable.ic_action_file_cloud_upload);
notificationBuilder.setContentTitle(getString(R.string.notification_upload_title));
//when this notification is clicked and the upload is running, open the upload fragment
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// set intent so it does not start a new activity
PendingIntent intent = PendingIntent.getActivity(this, 1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
notificationBuilder.setContentIntent(intent);
this.startForeground(NOTIFICATION_ID_UPLOADING_PROGRESS, notificationBuilder.build());
Manifest.xml
<activity
android:name="com.android.app.MainActivity_"
android:label="#string/app_short_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Finally I have realized that I have to write this:
Intent notificationIntent = new Intent(this, MainActivity_.class);
instead of
Intent notificationIntent = new Intent(this, MainActivity.class);
Thanks a lot for all your answers!
I don't think that you need all this flags and configurations just to open an activity from the PendingIntent. You certainly don't need
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent.FLAG_ONE_SHOT
Remove them and try again.
Furthermore: is the package name of the MainActivity as intended (com.android.app.MainActivity)?
try below solution hope it works for you
Intent intent = new Intent(this,YourActivity....class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent blogIntent = PendingIntent.getActivity(this, INT CONSTANTS, intent,
PendingIntent.FLAG_ONE_SHOT);
From Notification
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
.
.
.
notificationBuilder.setContentIntent(blogIntent);
Notification notification = notificationBuilder.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(Constants.NOTIFICATION_NEW_BLOG, notification);
You have to add custom receiver in manifest
<receiver
android:name=".IntentReceiver"
android:exported="false">
<intent-filter>
<!-- add notification action here -->
</intent-filter>
</receiver>
In Intent receiver class override on recieve method
public class IntentReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//call your activity here
}
}
Use this code
/* Invoking the default notification service */
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Test");
mBuilder.setContentText(text2);
mBuilder.setSmallIcon(R.drawable.icon);
/* Creates an explicit intent for an Activity in your app */
Intent resultIntent = new Intent(this, NotificationListActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(NotificationListActivity.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);
/* notificationID allows you to update the notification later on. */
mNotificationManager.notify(9999, mBuilder.build());
I have a question related to creating notifications in Android with an attached action. My goal is to have an action that won't re-open my app but will simply perform some logic as specified by a class in my app. Here is my code to create said notification.
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(context, RetryReceiver.class);
final PendingIntent retryIntent = PendingIntent.getBroadcast(context, notificationId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
final NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(context)
.setContentTitle(title)
.setTicker(ticker)
.setContentText(message)
.setSmallIcon(R.drawable.notifcation_sprout_leaf)
.setLargeIcon(largeIcon)
.setAutoCancel(true);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
mNotifyBuilder.addAction(R.drawable.refresh_action_bar, "Retry", retryIntent);
}
// Creates an explicit intent for an Activity in your app
Intent mainIntent = new Intent(context, MainActivity.class);
// The TaskStackBuilder needs multiple intents in case there are multiple failures in succession
// Thus default it to have a MainActivity intent it can fall back on
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(mainIntent);
stackBuilder.addNextIntent(composeIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(notificationId, PendingIntent.FLAG_UPDATE_CURRENT);
mNotifyBuilder.setContentIntent(resultPendingIntent);
// Because the ID remains unchanged, the existing notification is updated.
notificationManager.notify(notificationId, mNotifyBuilder.build());
Here is my class to receive the broadcast:
public class RetryReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final Bundle bundle = intent.getExtras();
// do shit
}
}
I have also registered the receiver in the AndroidManifest.xml as such:
<receiver
android:name=".RetryReceiver"
android:enabled="true"
android:exported="true" >
</receiver>
For some reason, the code in my receiver is never being fired, anyone have any suggestions?
You need to call setContentIntent(retryIntent) on your mNotifyBuilder - it is not set automatically.
Attribute android:exported="true" is to alow the broadcast receiver receive messages from sources outside its application.
The absence of any filters means that it can be invoked only by Intent objects that specify its exact class name. This implies that the receiver is intended only for application internal use.
So android:exported should be declared as android:exported="false" or not declared because it defaults to false in that case.
As I can't see no other problem with your code. Please try with android:exported="false"
See Receiver Android documentation