In my app on a device running 'Pie' I trigger a notification with a try again action when a job (yigit/android-priority-jobqueue) fails. the action button "Try Again" calls the broadcast receiver onReceive as expected and the action name is correct but the intent extras are null. The channels have been created also.
The notification code is as follows:
NotificationManager manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
int notificationId = 123;
Intent intent = new Intent(getApplicationContext(), MyReceiver.class);
PendingIntent contentPendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
Intent tryAgainIntent = new Intent(getApplicationContext(), MyReceiver.class);
tryAgainIntent.setAction(TRY_AGAIN_ACTION);
tryAgainIntent.putExtra(Extras.POST_ID, postId);
PendingIntent tryAgainPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, tryAgainIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), "com.example.android.GENERAL_NOTIFICATIONS")
.setSmallIcon(R.drawable.ic_logo)
.setContentTitle("Post sync failed")
.setContentText("Syncing the post failed")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setWhen(System.currentTimeMillis())
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("Syncing the post failed, try again?"))
.setContentIntent(contentPendingIntent)
.addAction(R.drawable.ic_logo, "Try Again", tryAgainPendingIntent)
.setAutoCancel(true);
// send the notification
manager.notify(notificationId, builder.build());
My receiver is as follows:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
if(TRY_AGAIN_ACTION.equals(action)) {
// gets here fine
Long postId = intent.getLongExtra(Extras.POST_ID, -1);
// postId is always -1
Long postId = (Long) extras.get(Extras.POST_ID);
// postId is always -1 here also
}
}
}
My manifest entry is:
<receiver
android:name=".receivers.MyReceiver"
android:exported="false">
<intent-filter>
<action android:name="TRY_AGAIN_ACTION" />
</intent-filter>
</receiver>
I'm stumped as to why it all works except the intent extras in the receiver are null, any suggestions?
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'm developing addAction notification from iBeacon, how do i give boolean status success or not to this actionIntent from this pendingIntent notification which will received in onReceive method in ActionReceiver.class
this is the notification method from MainActivity.class
Intent broadcastIntent = new Intent(this, ActionReceiver.class);
broadcastIntent.putExtra("action", "notif1");
PendingIntent actionIntent = PendingIntent.getBroadcast(
this, 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new Notification.Builder(this)
.setSmallIcon(R.mipmap.th_notif_logo)
.setTicker("Your Title")
.setWhen(System.currentTimeMillis())
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.addAction(R.drawable.ic_petunjuk_icon,"Clue", actionIntent)
.setDefaults(Notification.DEFAULT_ALL) // requires VIBRATE permission
.setStyle(new Notification.BigTextStyle().bigText(message))
.setContentIntent(pIntentAction)
.setPriority(Notification.PRIORITY_HIGH)
.build();
this is the onReceive method in ActionReceiver.class
#Override
public void onReceive(Context context, Intent intent) {
String action=intent.getStringExtra("action");
if(action.equals("notif1")){
SharedPreferences preferences = context.getSharedPreferences("MYPREFS", MODE_PRIVATE);
final String nama_tim = preferences.getString("username", "Key not correct");
InserData(nama_tim, "fsrd");
Toast.makeText(context.getApplicationContext(),"Action Receiver berhasil masuk",Toast.LENGTH_SHORT).show();
}
else if(action.equals("action2")){
}
//This is used to close the notification tray
Intent it = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.sendBroadcast(it);
}
so when i got boolean status success or not, i can do something in MainActivity.class
if (actionIntent == success){
//do something
}
really appreciate your help guys..
On your MainActivity.class
Intent broadcastIntent = new Intent("action-key"); // Specify the action to your intent.
broadcastIntent.setPackage(getPackageName());
// The values you want receive in the BroadcastReceiver.
broadcastIntent.putExtra("key-action", "notif1");
broadcastIntent.putExtra("key-boolean", true);
PendingIntent actionIntent = PendingIntent.getBroadcast(
this, 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT)
NotificationCompat.Action notificationAction = new NotificationCompat.Action(R.drawable.ic_action, "Action Name", actionIntent)
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new NotificationCompat.Builder(this,"channelId")
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker("Your Title")
.setWhen(System.currentTimeMillis())
.setContentTitle("test")
.setContentText("test")
.setAutoCancel(true)
.addAction(notificationAction) // Adds an action button to the notification
.setContentIntent(contentIntent) // Launches the intent when you click the notification.
.setDefaults(Notification.DEFAULT_ALL) // requires VIBRATE permission
.setPriority(Notification.PRIORITY_HIGH)
.build();
....
....
// Instead of using your own class receiver, you have to use the default default class receiver if you want your data to reach to your MainActivity.class easily.
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == "action") {
bool result = intent.getBooleanExtra("key-boolean", false); // Your value
}
}
};
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("action");
registerReceiver(broadcastReceiver, intentFilter);
Have you tried using public static boolean? Can you explain exactly when do you want your boolean to be true or false?
I am trying to make notification with remove button, notifications are stored in SQLite DB and after the press, I want to remove "record" by id. Firstly I get a notification, store it to db , store unique id and pass it to a method which creates a notification. It gets fine in the method.
public static String CUSTOM_ACTION = "com.example.app.Services.REMOVE";
Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(CUSTOM_ACTION);
snoozeIntent.putExtra("NOT_WORKING", String.valueOf(id));
PendingIntent snoozePendingIntent =
PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.drawable.ic_stat_bell)
.setContentTitle("Loggly")
.setContentText(messageBody)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.addAction(R.drawable.ic_delete_forever_black_24dp, "Remove", snoozePendingIntent);
then I have a broadcast receiver for handling data from notification. Here is how it looks in my manifest file.
<receiver android:name=".MyBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="com.example.app.Services.REMOVE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
And here is the broadcast receiver the value which I got from extras is always null ... I have been trying to find a solution, but with no result.
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String id;
if (extras != null) {
id = extras.getString("NOT_WORKING");
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager notificationManager = (NotificationManager) context.getSystemService(ns);
if (notificationManager != null) {
notificationManager.cancel(0);
}
Intent inten = new Intent(context, RemoveService.class);
inten.putExtra("NOT_WORKING", id);
context.startService(inten);
}
}
}
Finally, I am starting intent service, which should delete the "record" from the database, but when the broadcast receiver does not receive id it can't do anything.
I just created a sample notification on my side and the problem is the way you are creating the pendingIntent. Just add the proper flag to the pendingIntent parameter and it will work fine.
PendingIntent snoozePendingIntent = PendingIntent.getBroadcast(this, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
You can use FLAG_ONE_SHOT as well. If it satisfies your use case. You can go through different flags which can be used in PendingIntent
I've successfully created a status bar notification but I want it to pop up 6 hours after the user exits the app.
I have the following code:
public class myClass extends superClass implements myinterface {
final int NOTIF_ID = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {.........}
/* more methods etc */ ......
#Override
protected void onDestroy() {
View iop = (View) findViewById(R.id.app);
sendNotification(iop);
super.onDestroy();
}
public void sendNotification(View view) {
// Use NotificationCompat.Builder to set up our notification.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
//icon appears in device notification bar and right hand corner of notification
builder.setSmallIcon(R.drawable.ic_launcher);
// This intent is fired when notification is clicked
Intent intent = new Intent(view.getContext(), AndroidLauncher.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
// Set the intent that will fire when the user taps the notification.
builder.setContentIntent(pendingIntent);
// Large icon appears on the left of the notification
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
// Content title, which appears in large type at the top of the notification
builder.setContentTitle("Notifications Title");
// Content text, which appears in smaller text below the title
builder.setContentText("Your notification content here.");
// The subtext, which appears under the text on newer devices.
// This will show-up in the devices with Android 4.2 and above only
builder.setSubText("Tap to view documentation about notifications.");
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Will display the notification in the notification bar
notificationManager.notify(NOTIF_ID, builder.build());
}
A status bar notification pops up when the app is exited but I want it to popup after 6 hours since the time user exits the app. How do I go about it?
Thanks in advance!
You can use an AlarmManager to schedule a broadcast that contains your notification.
private void scheduleNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle("Scheduled Notification");
builder.setContentText(content);
builder.setSmallIcon(R.drawable.ic_launcher);]
Notification notification = builder.build();
Intent notificationIntent = new Intent(this, NotificationPublisher.class);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID, 1);
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION, notification);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
long futureInMillis = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(6);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, futureInMillis, pendingIntent);
}
Then use a BroadcastReceiver to receive the intent and show the notification.
public class NotificationPublisher extends BroadcastReceiver {
public static String NOTIFICATION_ID = "notification-id";
public static String NOTIFICATION = "notification";
public void onReceive(Context context, Intent intent) {
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = intent.getParcelableExtra(NOTIFICATION);
int id = intent.getIntExtra(NOTIFICATION_ID, 0);
notificationManager.notify(id, notification);
}
}
Don't forget to register the receiver in your AndroidManifest.xml file.
(Source: https://gist.github.com/BrandonSmith/6679223)
create a new class which will execute the alarm using pending intent and alarm manager.
long time= 6*60*60*1000; //6 hours
new Alarm_task(this, time).run();
public class Alarm_task implements Runnable{
// The android system alarm manager
private final AlarmManager am;
// Your context to retrieve the alarm manager from
private final Context context;
long alarm_time;
public Alarm_task(Context context, long time) {
this.context = context;
this.am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
this.alarm_time = time;
}
#Override
public void run() {
// Request to start are service when the alarm date is upon us
//pop up a notification into the system bar not a full activity
Intent i = new Intent("intent name");
// can create a dialog in that intent or just call the sendNotification() function
/** Creating a Pending Intent */
PendingIntent operation = PendingIntent.getActivity(getBaseContext(), 0, i, Intent.FLAG_ACTIVITY_NEW_TASK);
/** Setting an alarm, which invokes the operation at alart_time */
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() + alarm_time, operation);
}
}
define intent in your manifest file:
<activity
android:name=".Activity name"
android:label="#string/app_name" >
<intent-filter>
<action android:name="Intent name" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
now in that activity you can call Sendnotification() function during onCreate().. or show some UI according to your application
call this method from onDestroy
public void Remind (String title, String message)
{
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent notificationIntent = new Intent("android.media.action.DISPLAY_NOTIFICATION");
notificationIntent .PutExtra ("message", message);
notificationIntent .PutExtra ("title", title);
notificationIntent.addCategory("android.intent.category.DEFAULT");
PendingIntent broadcast = PendingIntent.getBroadcast(context, 0 , notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar cal = Calendar.getInstance();
if (android.os.Build.VERSION.SDK_INT>16)
{
alarmManager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis()+ 6*60*60*1000, broadcast);
}else
{
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis() + 6*60*60*1000, broadcast);
}
}
Create a new JAVA file
public class Broadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent1) {
String message = intent1.getStringExtra ("message");
String title = intent1.getStringExtra ("title");
// This intent is fired when notification is clicked
Intent notificationIntent = new Intent(context, AndroidLauncher.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(AndroidLauncher.class);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Use NotificationCompat.Builder to set up our notification.
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
//icon appears in device notification bar and right hand corner of notification
builder.setSmallIcon(R.mipmap.ic_launcher);
// Set the intent that will fire when the user taps the notification.
builder.setContentIntent(pendingIntent);
// Content title, which appears in large type at the top of the notification
builder.setContentTitle("Notifications Title");
// Content text, which appears in smaller text below the title
builder.setContentText("Your notification content here.");
// The subtext, which appears under the text on newer devices.
// This will show-up in the devices with Android 4.2 and above only
builder.setSubText("Tap to view documentation about notifications.");
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// Will display the notification in the notification bar
notificationManager.notify(0, builder.build());
}
Register this Receiver in Manifest
<receiver android:name=".Broadcast">
<intent-filter>
<action android:name="android.media.action.DISPLAY_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
You can do it by using alarm manager service and notification manager.
I have an action to Dial a number via
uri = Uri.parse("tel:" + address);
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(uri);
PendingIntent pd = PendingIntent.getActivity(context, 0,intent,
PendingIntent.FLAG_UPDATE_CURRENT);
notif.addAction(R.drawable.ic_menu_call, "Call", pd);
but the problem is that I don't know
how/when to call the NotificationManager's manager.cancel() function
so as to dismiss the notification when the call action is clicked!
I had the same situation and I managed to solve it by creating a broadcast receiver that is called when the action button is pressed. The broadcast receiver then receives an intent with the notification id that you want to dismiss and the number you want to dial.
The is the code that creates the notification:
NotificationManager notificationManager =
(NotificationManager)MyApplication.getAppContext().getSystemService(Context.NOTIFICATION_SERVICE);
//for some versions of android you may need to create a channel with the id you want
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel chan = new NotificationChannel("your_channel_id", "ChannelName", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(chan);
}
Intent intent = new Intent(MyApplication.getAppContext(), ActionReciever.class);
intent.putExtra("phoNo", phoneNumber);
// num is the notification id
intent.putExtra("id", num);
PendingIntent myPendingIntent = PendingIntent.getBroadcast(
MyApplication.getAppContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
);
Notification n = new NotificationCompat.Builder(MyApplication.getAppContext(),
"your_channel_id")
.setSmallIcon(R.drawable.app_pic)
.addAction(R.drawable.app_pic, "Dial now", myPendingIntent)
.setAutoCancel(true)
.build();
notificationManager.notify(num, n);
This is the broadcast receiver code, it is called when the action button is pressed. The received intent here is the intent inside the pending intent we prepared in the notification:
public class ActionReciever extends BroadcastReceiver {
#SuppressLint("MissingPermission")
#Override
public void onReceive(Context context, Intent intent) {
String phoneNumber = intent.getStringExtra("phoNo");
int id = intent.getIntExtra("id",0);
Intent i = new Intent(Intent.ACTION_DIAL);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setData(Uri.parse("tel:" + phoneNumber));
NotificationManager notificationManager =
(NotificationManager) MyApplication.getAppContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(id);
context.startActivity(i);
}
}
Register the BroadcastReceiver in the app manifest inside application tag
<receiver android:name=".ActionReciever" />
MyApplication is a class that extends the default Application so I can have a place to store the context I need.
public class MyApplication extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
Note that you need to update the manifest to run the MyApplication class like this:
android:name="com.example.yourpackage.MyApplication"
This code works even if the app is down and without a background service.
See Android READ PHONE STATE? - about phone state.
case TelephonyManager.CALL_STATE_RINGING:
notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(100); // cancel notification by ID
break;
// build your notification.
intent notificationIntent = new Intent(context,
YourPhoneActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, 0,
notificationIntent, 0);
Bitmap bm = BitmapFactory.decodeResource(context.getResources(),
iconLarge);
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context).setSmallIcon(iconSmall).setLargeIcon(bm)
.setContentTitle(title).setContentText(message)
.setAutoCancel(false).setContentIntent(intent).setWhen(when)
.setTicker(message);
builder.getNotification();