I have an application which is basically a webview and GCM notifications. I want to achieve the following thing: If the user is in the app and receives a notification, when he clicks the notification I want the webview to load the url provided in the notification.
I'm trying to accomplish this by using broadcast receiver but it doesn't work.
I dynamically register the receiver in the MainActivity:
private void registerNotificationReceiver() {
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_LOAD_URL_FROM_NOTIFICATION);
Log.i(TAG, "registerNotificationReceiver()");
this.receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "notification received");
}
};
super.registerReceiver(this.receiver, filter);
}
And in the GCM Listener I'm using PendingIntent.getBroadast():
final Intent broadcastIntent = new Intent(MainActivity.ACTION_LOAD_URL_FROM_NOTIFICATION);
PendingIntent intent = PendingIntent.getBroadcast(getApplicationContext(), 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(intent);
notification = notificationBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, notification);
I don't understand why onReceive in the MainActivity class is not called. The message "notification received" is not displayed.
Can you help me? Thank you :)
I cannot find right now the reason but there's a security reason. Latest Android versions won't allow you to trigger a listener from "kind-of" remote process without it being explicit.
The intent you broadcast MUST be explicit for it to work. Explicit means that you have to explicitly call the component that will handle the intent (the receiver). So this receiver must be declared in its own class and in the manifest as a <receiver>.
Follow this guy's example in the section Explicit Broadcast Intents http://codetheory.in/android-broadcast-receivers/
and thy will be done.
Related
Using Xamarin.Android.
I have a BroadcastReceiver:
public class MyBroadcastReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
try
{
string someExtra = intent.Extras.GetString("someExtra", string.Empty);
}
catch (Exception)
{
}
}
}
I use a Google Cloud Messaging Service and create a notification when receive some message. Using a notification builder's SetContentIntent I export some extras to the activity that will operate this notification if user opens it. And it works. But when I initialize my notification builder with SetDeleteIntent inside the GCM Service, the notification does not trigger OnReceive in the BroadcastReceiver if user swipe to dismiss the notification.
When I do all the same inside my activity (not inside the GCM service) OnReceive is triggered on every notification's swipe-to-dismiss event. But it does not work inside the service.
I have even implemented the same CreateNotification method in my activity as in the service. When I call it (to create the notification) from my activity - all works perfect. When I call it from the service using a static pointer to the current instance of the activity - MyActivity.CurrentInstance.CreateNotification(...) - my notification does not react on swipe-to-dismiss event. I even tried to put the CreateNotification's code in RunOnUiThread - no result.
Therefore, notification's swipe-to-dismiss event is triggered only in case if that notification has been created in my activity. But I create notifications when receive messages from GCM. It actually creates notifications even when application is not running.
public void CreateNotification(........) {
//RunOnUiThread(() => {
var notificationBuilder = new Notification.Builder(this);
notificationBuilder.SetContentTitle(title);
notificationBuilder.SetContentText(description);
notificationBuilder.SetSmallIcon(Resource.Drawable.Icon);
var notificationIntent = new Intent(this, typeof(MainActivity));
notificationIntent.PutExtra(.......)
var contentIntent = PendingIntent.GetActivity(Application.Context, 0, notificationIntent, PendingIntentFlags.CancelCurrent);
notificationBuilder.SetContentIntent(contentIntent);
// Actually my headache
const String NOTIFICATION_DELETED_ACTION = "NOTIFICATION_DELETED";
var receiver = new MyBroadcastReceiver();
RegisterReceiver(receiver, new IntentFilter(NOTIFICATION_DELETED_ACTION));
Intent intent = new Intent(NOTIFICATION_DELETED_ACTION);
intent.PutExtra(.......)
var deleteIntent = PendingIntent.GetActivity(Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
notificationBuilder.SetDeleteIntent(deleteIntent);
var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;
notificationManager.Notify(1, notificationBuilder.Build());
//});
}
Any ideas how to create a notification (inside the service) that will be able to trigger its swipe-to-dismiss event?
notification's swipe-to-dismiss event is triggered only in case if that notification has been created in my activity
When you When you use SetDeleteIntent(deleteIntent) method, make sure your deleteIntent is initialized by using PendingIntent.GetBroadcast method.
GetBroadcastet means retrieve a PendingIntent that will perform a broadcast, like calling Context.sendBroadcast(). When you use GetActivity method, it means retrieve a PendingIntent that will start a new activity. That's reason that your notification does not trigger OnReceive in the BroadcastReceiver. For more information you could read this document.
Modify your code :
var deleteIntent = PendingIntent.GetActivity(Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
To :
var deleteIntent = PendingIntent.GetBroadcast(Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
Then in your GCM Service, your notification's swipe-to-dismiss event will be triggered .
I am using pushbots with an android app. I have a custom broadcast receiver that handles notifications in the app. However, when I exit the app, all of the notifications are still there. How can I clear these notifications? I have tried the solutions on these questions:
How to clear a notification in Android
How to remove notification from notification bar programmatically in android?
but Im still not having any luck. Any suggestions?
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("CHAT", "RECIEVED");
Bundle notification = intent.getExtras();
String type = notification.getString("type");
//do some stuff here
NotificationManager nMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//nMgr.cancel();
nMgr.cancelAll();
Log.d("CHAT", "CANCEL");
}
};
I would like to send a LocalBroadcast when clicking on a button inside a notification. I know how to do that with a regular broadcast, but I would like to keep the broadcast inside my app. Is this possible?
The code I have is roughly:
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context)
.setContentTitle("Title")
.setContentText("content")
.setSmallIcon(R.drawable.icon1)
.setContentIntent(pIntent)
.setAutoCancel(true);
Intent myButtonIntent = new Intent(BUTTON_PRESSED);
// the following line gives me a normal broadcast, not a LocalBroadcast
PendingIntent myButtonpIntent = PendingIntent.getBroadcast(context, 12345, myButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.addAction(R.drawable.icon2, "OK", myButtonpIntent);
Notification notification = notificationBuilder.build();
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
And also:
BroadcastReceiver bReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(BUTTON_PRESSED)) {
// do something
}
}
};
LocalBroadcastManager bManager = LocalBroadcastManager.getInstance(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BUTTON_PRESSED);
bManager.registerReceiver(bReceiver, intentFilter); // I want to use the LocalBroadcastManager
// registerReceiver(bReceiver, intentFilter); // Instead, I have to use this line for a non-local broadcast
No.
First of all, LocalBroadcastManager is part of the support package (an optional library you add to your application), not part of the system itself.
Secondly, even if it were, the notification service is used by all applications. Since it's a shared resource, there is nothing "local" that occurs when you post a notification.
this might work(it works for me)
add your BroadcastReceiver to manifest.xml
<!-- If this receiver listens for broadcasts sent from the system or from
other apps, even other apps that you own, set android:exported to "true". -->
<receiver android:name=".myBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="some" />
</intent-filter>
</receiver>
creating a Notification and add action( .addaction() )
and sending Broadcast to BroadcastReceiver
(you can use the helper function)
Intent Rintent = new Intent(this , YOUR_BroadcastReceiver_CLASS.class );
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
createNotificationChannel(ChanelID ,"name " , "Desc" );
startForeground(FLAG_FORGRANDONLLINE, new NotificationCompat.Builder(ServiceFindTask.this,
NotifID) // don't forget create a notification channel first
.setOngoing(true)
.setSmallIcon(R.mipmap.somet)
.setContentTitle(getString(R.string.app_name))
.setContentText("Service is running ")
.setSound(Settings.System.DEFAULT_NOTIFICATION_URI)
.setVibrate(new long[]{1000,100})
.setContentIntent(pendingIntent)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
// Sending a action for BroadcastReceiver class
.addAction(R.drawable.body,"GO offline" , makePendingIntent(SERVICE_TO_CLIENT_GO_OFFLINE , null , Rintent))
.build());
// Helper function
public PendingIntent makePendingIntent(Integer action , #Nullable String data ,Intent intent) {
intent.setAction( action.toString());
if(data != null){
intent.putExtra("kay", data);}
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
return pendingIntent;
}
receive the action and create LocalBroadcast using LocalBroadcastManager
based on your notification action
public class myBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (Integer.parseInt(action)){
case Service.SERVICE_TO_CLIENT_GO_OFFLINE:
helpLocalBroadcastManager(intent , context , Service.SERVICE_TO_CLIENT_GO_OFFLINE , null);
break;
}
}
private void helpLocalBroadcastManager(Intent intent ,Context context ,Integer action , #Nullable String data ) {
intent = new Intent(action.toString());
// Adding some data
if(data != null){
intent.putExtra("kay", data);}
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
now you can receive the LocalBroadcast in any activity that is connect to BroadcastReceiver like this:
private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (Integer.parseInt(action)){
case Service.SERVICE_TO_CLIENT_GO_OFFLINE:
Toast.makeText(Activity_Main.this , "This is massage from Activity_Main " , Toast.LENGTH_SHORT).show();
break;
}
}
};
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this)
.registerReceiver(messageReceiver, new IntentFilter(String.valueOf(ServiceFindTask.SERVICE_TO_CLIENT_GO_OFFLINE)));
}
this question was for 8 years ago but this was something i needed now and this is how i did it THANKS FOR READING
I am creating an notification by sending GCM message to my app using this code
private static void generateNotification(Context context, int type, String title, String message) {
Intent notificationIntent;
int icon = R.drawable.ic_launcher;
java.util.Random v = new java.util.Random();
int id = v.nextInt(1000);
long when = System.currentTimeMillis();
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notification = new NotificationCompat.Builder(context);
notificationIntent = new Intent(context, Home.class);
notificationIntent.putExtra(CommonUtilities.TITLE_ALERT, title);
notificationIntent.putExtra(CommonUtilities.EXTRA_MESSAGE, message);
notificationIntent.putExtra(CommonUtilities.TYPE, type);
notificationIntent.putExtra(CommonUtilities.ID, id);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, type, notificationIntent, PendingIntent.FLAG_ONE_SHOT);
Notification notification_view = notification.setContentTitle(title)
.setContentText(message).setContentIntent(intent)
.setSmallIcon(icon).setWhen(when)
.setVibrate(new long[] { 1000 }).build();
notification_view.flags |= Notification.FLAG_AUTO_CANCEL;
// Play default notification sound
notification_view.defaults |= Notification.DEFAULT_SOUND;
// notification_view.sound = Uri.parse("android.resource://" +
// context.getPackageName() + "your_sound_file_name.mp3");
// Vibrate if vibrate is enabled
notification_view.defaults |= Notification.DEFAULT_VIBRATE;
manager.notify(id, notification_view);
}
and receiving this pending intent using receiver
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(!intent.hasExtra(CommonUtilities.TYPE)){
Log.v("msg", "intent vars not received");
return;
}
int type = intent.getExtras().getInt(CommonUtilities.TYPE);
String title = intent.getExtras().getString(CommonUtilities.TITLE_ALERT);
String newMessage = intent.getExtras().getString(CommonUtilities.EXTRA_MESSAGE);
String[] msgArr = newMessage.split(",");
Log.v("message", newMessage);
}
};
But my activity is not performing the action and showing me log. I have registered my receiver with a custom intent using
registerReceiver(mHandleMessageReceiver, new IntentFilter(CommonUtilities.DISPLAY_ACTION));
How can I find the error?
Edit
If application receives a notification while it is on foreground then notifications are received well but if the activity is not running or it is finished and I invoke it on notification click nothing happened
The code you have in generateNotification will only create a notification, not a broadcast.
Your Receiver won't ever receive anything because your'e never broadcasting. To utilize the receiver in the way you're using it you need to write code similar to this
public static final String DISPLAY_ACTION = "package.name.DISPLAY_MESSAGE";
public static final String EXTRA_MESSAGE = "message";
public static void displayMessage(Context context, String message) {
Intent intent = new Intent(DISPLAY_ACTION);
intent.putExtra(EXTRA_MESSAGE, message);
context.sendBroadcast(intent);
}
EDIT
I would add this code above to your CommonUtilities class, you also need to add this line to your generateNotification method
CommonUtilities.displayMessage(context, message);//this will then send your broadcast to the receiver.
EDIT - Show notification message when app is opened
I'm using similar functionality in my app. I saved the notification in a database as unread when it has been received by GCM and then alerted the user, as soon as the app is opened i checked for unread notifications and if found invoked the displayMessage method to show the user the missed notifications. After that I delete the notification from the db.
You wrote:
If application receives a notification while it is on foreground then
notifications are received well but if the activity is not running or
it is finished and I invoke it on notification click nothing happened
If you register your receiver from your activity by calling:
registerReceiver(mHandleMessageReceiver, new IntentFilter(CommonUtilities.DISPLAY_ACTION));
then you have registered the receiver using the context of the activity. That means that when the activity is finished, the registered receiver will be removed and destroyed (to prevent memory leaks).
If you want your receiver to be run even if your app is not running, then you need to register the receiver in the manifest, by adding an appropriate intent filter to your <receiver> definition:
<intent-filter>
<!-- use the correct name string for CommonUtilities.DISPLAY_ACTION) -->
<action android:name="blah.blah.blah.DISPLAY_ACTION"/>
</intent-filter>
Is there any way in Android to detect when a user swipes a notification to the left and deletes it? I'm using an alarmmanager to set a repeating alert and I need my repeating alert to stop when the notification is cancelled by the user. Here's my code:
Setting the repeating alert:
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), repeatFrequency, displayIntent);
My notification code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Get the notification ID.
int notifID = getIntent().getExtras().getInt("Reminder_Primary_Key");
//Get the name of the reminder.
String reminderName = getIntent().getExtras().getString("Reminder_Name");
//PendingIntent stores the Activity that should be launched when the user taps the notification.
Intent i = new Intent(this, ViewLocalRemindersDetail.class);
i.putExtra("NotifID", notifID);
i.putExtra("notification_tap", true);
//Add FLAG_ACTIVITY_NEW_TASK to stop the intent from being launched when the notification is triggered.
PendingIntent displayIntent = PendingIntent.getActivity(this, notifID, i, Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notif = new Notification(R.drawable.flag_red_large, reminderName, System.currentTimeMillis());
CharSequence from = "Here's your reminder:";
CharSequence message = reminderName;
notif.setLatestEventInfo(this, from, message, displayIntent);
//Pause for 100ms, vibrate for 250ms, pause for 100ms, and vibrate for 500ms.
notif.defaults |= Notification.DEFAULT_SOUND;
notif.vibrate = new long[] { 100, 250, 100, 500 };
nm.notify(notifID, notif);
//Destroy the activity/notification.
finish();
}
I know I need to call alarmManager.cancel(displayIntent) in order to cancel my repeating alarm. However, I don't understand where to put this code. I need to cancel the repeating alert ONLY when the user has tapped on the notification or dismissed it. Thanks for your help!
I believe that Notification.deleteIntent is what you are looking for. The doc says:
The intent to execute when the notification is explicitly dismissed by the user, either with the "Clear All" button or by swiping it away individually. This probably shouldn't be launching an activity since several of those will be sent at the same time.
To all those future people out there -- you can register a broadcast receiver to listen for notification delete inents.
Create a new broadcast receiver:
public class NotificationBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == null || !action.equals(Config.NotificationDeleteAction)) {
return;
}
// Do some sweet stuff
int x = 1;
}
}
Register the broadcast receiver within your application class:
"If your app targets API level 26 or higher, you cannot use the manifest to declare a receiver for most implicit broadcasts (broadcasts that do not target your app specifically)."
Android Documentation.
registerReceiver(
new NotificationBroadcastReceiver(),
new IntentFilter(Config.NotificationDeleteAction)
);
You probably noticed the static variable Config.NotificationDeleteAction. This is a unique string identifier for your notification. It typically follows the following {namespace}{actionName} convention:
you.application.namespace.NOTIFICATION_DELETE
Set the delete intent on your notification builder:
notificationBuilder
...
.setDeleteIntent(createDeleteIntent())
...
Where, createDeleteIntent is the following method:
private PendingIntent createDeleteIntent() {
Intent intent = new Intent();
intent.setAction(Config.NotificationDeleteAction);
return PendingIntent.getBroadcast(
context,
0,
intent,
PendingIntent.FLAG_ONE_SHOT
);
}
Your registered broadcast receiver should receive the intent when your notification is dismissed.
You can also use an Activity PendingIntent, which may be simpler to implement if you have an Activity that can handle the dismissal, because you don't have to create and configure a broadcast receiver.
public static final String DELETE_TAG = "DELETE_TAG";
private PendingIntent createDeleteIntent(Context context) {
Intent intent = new Intent(context, MyActivity.class);
intent.putExtra(DELETE_TAG, true);
return PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_ONE_SHOT
);
}
MyActivity would receive the intent in its onCreate(), and in this example, could look for the DELETE_TAG extra to recognize it.