I am trying to send a notification using Alarm Manager, the code is working fine on the lower SDK versions like 26 below. The android implicit background ban is not letting the notification to broadcast.
find code below for BroadcastReceiver :
public class AlarmReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("AlarmReceiver-Worked");
MainActivity.initNotificationChannels(context);
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, "default")
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(intent.getStringExtra("title"))
.setContentText(intent.getStringExtra("text"))
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_MAX);
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
Manifext.xml
<receiver android:name="com.x.Controllers.Notification.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.media.action.DISPLAY_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
first of all
not able to go past this error
which error? no log, no info what isn't working... for which actions this BroadcastReceiver is registered? is this for BOOT_COMPLETED or smth else?
besides that
private static boolean notificationChannelsInitialized = false;
if (notificationChannelsInitialized) {
return;
}
it will always return in here, you are setting this flag to true later in this method, it will never happen.
also don't use static flag, just check that Channel already exists
NotificationChannel channel = manager.getNotificationChannel("default");
notificationChannelsInitialized = Build.VERSION.SDK_INT < 26 || channel != null;
on API below 26 just assume it is there
Intent notificationIntent = new Intent(context, AlarmReceiver.class);
notificationIntent.setAction("android.media.action.DISPLAY_NOTIFICATION");
notificationIntent.putExtra("title", notificationData.getString("title"));
notificationIntent.putExtra("text", notificationData.getString("text"));
PendingIntent broadcast = PendingIntent.getBroadcast(this.context, i, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), broadcast);
Related
I have been trying to open my application to my MainActivity, and load a fragment, from a notification and I cannot seem to do so successfully. My most successful build appears to do everything successfully except actually open the app.
The app will be completely closed and I'll receive the notification and tap on it. The phone drop down menu will retract and act like it's about to open the app, then doesn't. When I open the app manually the application has been create and navigated successfully to the fragment. It just didn't open my app.
I'll list relevant code below:
Manifest Code
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.easy.planner">
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/Theme.Planner"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleInstance" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>=
<receiver
android:name=".ReminderReceiver"
android:exported="true"
android:theme="#android:style/Theme.NoDisplay"/>
</application>
</manifest>
Code in ReminderReceiver
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP & Intent.FLAG_ACTIVITY_SINGLE_TOP);
notificationIntent.putExtra("id", reminder.getId());
final PendingIntent pendingIntent;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
pendingIntent = PendingIntent.getActivity(context, reminder.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);}
else{
pendingIntent = PendingIntent.getActivity(context, reminder.getId(), intent, PendingIntent.FLAG_UPDATE_CURRENT);}
NotificationHelper helper = new NotificationHelper(context);
String title = "title";
String message = "message";
NotificationCompat.Builder builder = helper
.getReminderNotification(context, title, message,pendingIntent, true);
helper.GetManager().notify(reminder.getId(), builder.build());
Notification Helper
public class NotificationHelper extends ContextWrapper {
public static final String TAG = "Notification Helper";
public static final String REMINDERS_CHANNEL_ID = "id";
public static final String REMINDERS_CHANNEL_NAME = "name";
private NotificationManager manager;
public NotificationHelper(Context base) {
super(base);
CreateChannels(base);
}
public static boolean CreateChannels(Context context)
{
NotificationChannel reminders = new NotificationChannel(REMINDERS_CHANNEL_ID, REMINDERS_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
reminders.enableLights(true);
reminders.enableVibration(true);
NotificationManager manager = GetManager(context);
manager.createNotificationChannel(reminders);
return true;
}
public NotificationCompat.Builder getReminderNotification(Context context, String title, String message, PendingIntent pendingIntent, boolean autoCancel)
{
return new NotificationCompat.Builder(getApplicationContext(), REMINDERS_CHANNEL_ID)
.setSmallIcon(R.drawable.notification_temp)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(pendingIntent)
.setAutoCancel(autoCancel);
}
I've been looking at plenty of other stackoverflow pages and have yet to find a solution.
you can update your ReminderReceiver's code to this and check if it is working
Intent notificationIntent = new Intent(context, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP &
Intent.FLAG_ACTIVITY_SINGLE_TOP);
notificationIntent.putExtra("id", reminder.getId());
final PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(context, reminder.getId(), notificationIntent /*update*/ , PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
} else {
pendingIntent = PendingIntent.getActivity(context, reminder.getId(), notificationIntent /*update*/ , PendingIntent.FLAG_UPDATE_CURRENT);
}
NotificationHelper helper = new NotificationHelper(context);
String title = "title";
String message = "message";
NotificationCompat.Builder builder = helper
.getReminderNotification(context, title, message, pendingIntent, true);
helper.GetManager().notify(reminder.getId(), builder.build());
I think you are apssing wrong intent into your NotificationBuilder.
Hope this works!!
I'm stuck while dealing with this api 31. i made a chat app. When I create an action button to receive a phone call it works on android below API 31 or below Android 12, but it doesn't work on Android 12 (only work if the notification is not has action). maybe someone here can help me in finding a solution to this problem?
FirebaseService.java
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
boolean cancelNotification = false;
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Map<String, String> params = remoteMessage.getData();
JSONObject data = new JSONObject(params);
PendingIntent pendingIntent;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE);
}
else {
pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
}
String channel_id = getNotificationData(data, "channel");
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channel_id)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getNotificationData(data, "title"))
.setContentText(getNotificationData(data, "body"))
.setAutoCancel(true)
.setContentIntent(pendingIntent);
if(channel_id.equals("cll2") && getNotificationData(data, "call_action").equals("open")){
playCallSound(this);
if(WindowUtil.isAppOnBackground(this) || isScreenOff()){
ArrayList<String> par = new ArrayList<>();
par.add("call_channel");
par.add("call_type");
par.add("call_token");
par.add("call_peer");
String callType = getNotificationData(data, "call_type");
if(callType.equals("3") || callType.equals("4")){
par.add("call_group_name");
par.add("call_group_caller");
}
Intent receiveCallAction = new Intent(this, CallReceiver.class);
receiveCallAction.putExtra("action", "ANSWER");
Intent cancelCallAction = new Intent(this, CallReceiver.class);
cancelCallAction.putExtra("action", "DECLINE");
for (String s : par) {
receiveCallAction.putExtra(s, getNotificationData(data, s));
cancelCallAction.putExtra(s, getNotificationData(data, s));
}
notificationBuilder.setOngoing(true);
receiveCallAction.setAction("RECEIVE_CALL");
cancelCallAction.setAction("CANCEL_CALL");
PendingIntent receiveCallPendingIntent = PendingIntent.getBroadcast(this, 1200, receiveCallAction, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent cancelCallPendingIntent = PendingIntent.getBroadcast(this, 1201, cancelCallAction, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder
.addAction(R.drawable.ic_baseline_call_24_green, "Answer", receiveCallPendingIntent)
.addAction(R.drawable.ic_baseline_call_red_24, "Decline", cancelCallPendingIntent);
}else{
cancelNotification = true;
}
}if(channel_id.equals("cll2") && getNotificationData(data, "call_action").equals("end_timeout")){
stopRinging();
}else if(channel_id.equals("ntf1")){
if(UserUtil.IS_CHAT_ACTIVITY){
cancelNotification = true;
}
if(!cancelNotification){
playNotificationSound(this);
}
}
if(!cancelNotification){
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
NotificationChannel channel = new NotificationChannel(channel_id,
getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
channel.enableLights(true);
channel.enableVibration(true);
mNotificationManager.createNotificationChannel(channel);
}
mNotificationManager.notify(1000, notificationBuilder.build());
}
}
CallReceiver.java (Broadcast Receiver)
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getExtras() != null) {
String action = intent.getStringExtra("action");
// Perform the action
performClickAction(context, action, intent.getExtras());
// Close the notification after the click action is performed.
NotificationManager mNotificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(1000);
// Stop the ringtone
stopRinging();
}
}
on my AndroidManifest.xml
<service
android:name=".services.FirebaseService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<receiver
android:name=".receiver.CallReceiver"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="CALL_RECEIVER" />
</intent-filter>
</receiver>
Thank you
i solve this problem by this code
PendingIntent receiveCallPendingIntent;
PendingIntent cancelCallPendingIntent;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
receiveCallPendingIntent = PendingIntent.getBroadcast(this, 1200, receiveCallAction, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
cancelCallPendingIntent = PendingIntent.getBroadcast(this, 1201, cancelCallAction, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
}else{
receiveCallPendingIntent = PendingIntent.getBroadcast(this, 1200, receiveCallAction, PendingIntent.FLAG_UPDATE_CURRENT);
cancelCallPendingIntent = PendingIntent.getBroadcast(this, 1201, cancelCallAction, PendingIntent.FLAG_UPDATE_CURRENT);
}
also add this permission for force Android 12^ (AndroidManifest.xml)
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><receiver
android:name=".receiver.CallReceiver"
android:exported="false"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
I would like to set a repeating alarm, in android 8 or 9 it works.
The question is how to set it to work it in 12 working parallel with android 8?
This is in the main activity, I set a startAlarm, and there is the missing part how to set the alarm in the case of sdk >= 31. When I start android to test it sends a notification at the beginning of the application but it do not send notification later.
MainActivity.java:
private void startAlarm(long when) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (alarmManager.canScheduleExactAlarms()) {
Log.e(TAG, "startAlarm: canScheduleExactAlarms");
}
}
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 1, intent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
} else {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 1, intent, 0);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
when*1000,
pendingIntent
);
} else {
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
when*1000,
pendingIntent
);
}
}
I set AlarmReceiver to send notification.
AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationHelper notificationHelper = new NotificationHelper(context);
NotificationCompat.Builder nb = notificationHelper.getChannelNotification();
notificationHelper.getManager().notify(1, nb.build());
long timeInSec = System.currentTimeMillis() / 1000;
Settings.setLastNotificationSent(timeInSec, context);
}
}
I set the permission in the manifest.
AndroidManifest:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<receiver android:name=".receiver.AlarmReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Probably you have to cancel previous alarm when you receive message in AlarmReceiver. I had the same problem and if i receive message from previous alarm i cancel it and then i can create new one.
private void cancelAlarm(){
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 1, intent,
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
} else {
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pintent);
pintent.cancel();
}
Inside the onCreate method of my Service I create a notification by doing the following:
String channelId = "001";
String channelName = "myChannel";
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE);
channel.setLightColor(Color.BLUE);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (manager != null) {
manager.createNotificationChannel(channel);
Notification notification;
Intent myIntent = new Intent("alarmReceiver");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, 0);
Notification.Action action = new Notification.Action.Builder(
Icon.createWithResource(this, R.drawable.ic_stop_black_24dp),
"action string",
pendingIntent).build();
//Modify notification badge
notification = new Notification.Builder(getApplicationContext(), channelId).setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setCategory(Notification.CATEGORY_SERVICE)
.addAction(action)
.build();
startForeground(101, notification);
}
The alarmReceiver in the Intent above is registered in my manifest as shown below (I did the following after seeing this question):
<receiver android:name=".AlarmReceiver">
<intent-filter>
<action android:name="alarmReceiver" />
</intent-filter>
</receiver>
and here is my AlarmReceiver class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("onReceive - ","was called");
}
}
The notification is shown, as well as the button, but when I press the button nothing happens.
I'm not sure what I'm doing wrong. Any help would greatly be appreciated.
Set PendingIntent to foreground service, And potentially add a flag:
FLAG_UPDATE_CURRENT
PendingIntent pendingIntent = PendingIntent.getForegroundService(this, 0, myIntent, FLAG_UPDATE_CURRENT);
Your broadcast is Implicit, so if you want to use getBroadcast() it may be best to Explicitly declare the receiver by providing the intent with the componentName of the receiver.
eg:
intent.setComponent(new ComponentName("packagename","fully qualified class name"));
Have you declared the service in your manifest?
I'm trying to learn how to develop applications for Android devices. For some time I have been developing an application in which there is a function for sending notifications (reminders) at different times of the day. But if the phone is locked and the time to send the notification is more than 10 minutes then they do not come. Tried BroadcasrReceiver:
public class NotificationReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
addNotif(context, "Times UP Receiver", "5 second Receiver", "Alert Receiver");
}
private void addNotif(Context context, String msg, String msgText, String msgAlert) {
Notification.Builder builder = new Notification.Builder(context);
Intent intent = new Intent(context, MainActivity.class);
PendingIntent notifIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
builder.setPriority(Notification.PRIORITY_HIGH).setContentIntent(notifIntent)
.setSmallIcon(R.drawable.ic_android_black_24dp)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_android_black_24dp))
.setTicker(msgAlert)
.setWhen(System.currentTimeMillis())
.setContentTitle(msg)
.setContentText(msgText);
Notification notification = builder.build();
notification.defaults = Notification.DEFAULT_ALL;
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(101, notification);
}
}
use AlarmManager:
Calendar calNotif = Calendar.getInstance();
Intent alertIntent = new Intent(getBaseContext(), NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), 102, alertIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager notifAlarm = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
notifAlarm.set(AlarmManager.RTC_WAKEUP, calNotif.getTimeInMillis() + (15 * 60 * 1000), pendingIntent);
I also tried to use Service:
public class NotificationService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Calendar calNotif = Calendar.getInstance();
Intent alertIntent = new Intent(getBaseContext(), NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), 103, alertIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager notifAlarm = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
notifAlarm.set(AlarmManager.RTC_WAKEUP, calNotif.getTimeInMillis() + (16 * 60 * 1000), pendingIntent);
return START_STICKY;
}
}
Manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".NotificationReceiver" />
<service android:name=".NotificationService" />
But nothing works. My head hurts, I still can not understand why notifications do not come. Tell me please what's the problem.
Don't use BaseContext and your going to test notification then why should you delayed 15 mins for notification. Minimize your time and check after its works increase your time.
In YourActivity
Calendar calNotif = Calendar.getInstance();
Intent alertIntent = new Intent(this, NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 102, alertIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager notifAlarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN)
notifAlarm.setExact(AlarmManager.RTC_WAKEUP, calNotif.getTimeInMillis()+10000, pendingIntent);
else
notifAlarm.set(AlarmManager.RTC_WAKEUP, calNotif.getTimeInMillis()+10000, pendingIntent);
In your Notification Code
builder.setPriority(Notification.PRIORITY_HIGH).setContentIntent(notifIntent)
.setSmallIcon(R.drawable.ic_android_black_24dp)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_android_black_24dp))
.setTicker(msgAlert)
.setWhen(System.currentTimeMillis())
.setContentTitle(msg)
.setContentText(msgText);
Remove setLargeIcon beacause it uses Bitmap and takes more memory. After its worked you can implement using service.