i am currently devoloping small app and i struggle about sending notifications.
My Goal: I have different tasks and they need to send unique notifications at unique time to user even
while app is closed.
What I did?: I did create different broadCastReceiver's to make them work in harmony with
alarmManager' s but even i changed the request code , flag or channel code, i do get notifications at
same time if user enables notifications for more than one task, but alarmManagers for notifications
are not supposed to work after same time.
'receiver' part of AndroidManifest.xml
<receiver
android:name=".BroadcastReceiver"
android:exported="true">
<intent-filter>
<action
android:name="pendingIntent">
</action>
</intent-filter>
</receiver>
<receiver
android:name=".BroadcastReceiver2"
android:exported="true">
<intent-filter>
<action
android:name="pendingIntent2">
</action>
</intent-filter>
</receiver>
first and second broadCastReceiver
public class BroadcastReceiver extends android.content.BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "100")
.setSmallIcon(R.drawable.logologo)
.setContentTitle("Title")
.setContentText("Text")
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(100, builder.build());
}
}
}
public class BroadcastReceiver2 extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,"102")
.setSmallIcon(R.drawable.logologo)
.setContentTitle("Title")
.setContentText("Text")
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(102, builder.build());
}
}
First and second Channel
public void createChannel1()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
CharSequence name = "channel1";
String description = "channel1 description";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel1 = new NotificationChannel("100", name, importance);
channel1.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel1);
}
}
public void createChannel2()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
CharSequence name = "channel2";
String description = "channel2 description";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel2 = new NotificationChannel("102", name,importance);
channel2.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel2);
}
}
Activity that needed to send Notification from first broadCastReceiver on Channel1 and
Activity that needed to send Notification from second broadCastReceiver on Channel2
button30.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(SmokeActivity.this, BroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(SmokeActivity.this, 100, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000 * 60, pendingIntent);
}
});
button29.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(WaterActivity.this, "Notifications Set", Toast.LENGTH_SHORT).show();
Intent intent2 = new Intent(WaterActivity.this, BroadcastReceiver2.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(WaterActivity.this,0,intent2,0);
AlarmManager alarmManager2 = (AlarmManager)getSystemService(ALARM_SERVICE);
// Set the alarm to start at 8:30 a.m.
Calendar calendar2 = Calendar.getInstance();
calendar2.setTimeInMillis(System.currentTimeMillis());
calendar2.set(Calendar.HOUR_OF_DAY, 8);
calendar2.set(Calendar.MINUTE, 30);
alarmManager2.setRepeating(AlarmManager.RTC_WAKEUP, calendar2.getTimeInMillis(),
1000*45, pendingIntent2);
}
});
For anyone suffering from same problem, the thing is android system does not allow us to send notification after first 10 minute when you create notification.
Related
I am trying to create an app that will open another app at a specified time. To do this, I used an AlarmManager that starts a service. It works just fine if my app is open when the alarm is triggered. I get a notification that the service started, and the other app opens. However, if my app is in the background (after pressing the home button), and the alarm triggers, I get a notification that the service started, but the other app does not launch. What am I doing wrong? I am testing this on a Pixel 3 emulator running API level 29 (Android 10/Q).
MainActivity.java
public class MainActivity extends AppCompatActivity {
public static final int REQUEST_CODE=101;
public static int aHour;
public static int aMinute;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void setAlarm() {
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, amReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, aHour);
calendar.set(Calendar.MINUTE, aMinute);
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
//Some code that sets aHour and aMinute
//Some code that triggers setAlarm()
}
amReciever.java
public class amReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, launcherService.class);
ContextCompat.startForegroundService(getApplicationContext(), i);
}
}
launcherService.java
public class launcherService extends Service {
public static final String CHANNEL_ID = "ForegroundServiceChannel";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Foreground Service")
.setContentText("App is launching.")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
Intent launcher = getApplicationContext().getPackageManager().getLaunchIntentForPackage("com.example.app");
if (launcher != null) {
startActivity(launcher);
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<service android:name=".launcherService"
android:enabled="true"
android:exported="true" />
As of Android 10 (API level 29), you cannot start activities from the background anymore.
There are a number of exceptions to this rule that may or may not apply to your given scenario.
If none of the exceptions apply, you might want to consider displaying a high-priority notification, possibly with a full-screen Intent.
So I made some code that makes the app show up at the time specified. It works well enough when the app is open on the screen, but when it is closed, it doesn't work at all. I need help making it show up.
Code for MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initChannels(this);
alarmMgr = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, MyReceiver.class);
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 00);
// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
}
Code for MyReceiver.java which extends BroadcastReceiver:
public MyReceiver() {
}
#Override
public void onReceive(Context context,Intent intent) {
Intent intent1 = new Intent(context, MyNewIntentService.class);
context.startService(intent1);
}
Code for MyNewIntentService which extends IntentService:
private static final int notificationId = 4242;
public MyNewIntentService() {
super("MyNewIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
//NOTIFICATION CREATION
// Create an explicit intent for an Activity in your app
Intent notifyIntent = new Intent(this, MainActivity.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifyIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, "default")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("This is the title")
.setContentText("This is the body of the notification.")
.setVisibility(VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, mBuilder.build());
}
And I added this in the AndroidManifest.xml:
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="false" >
</receiver>
<service
android:name=".MyNewIntentService"
android:exported="false" >
</service>
I know there's a lot of text in this question and I apologize for that, but I think that'll make it easier for you to help me or see what the problem is.
try this
firebase notification are two types:
data message: when your app background/foreground/killed your push notification is worked
display message: when your app foreground push notification works
Handle push notification these stages background/foreground/killed
it depends your json response make sure your json response like this:
{
"to": "registration_ids",
"data": {
"key": "value",
"key": "value",
"key": "value",
"key": "value"
}
}
this is my code when your app background/foreground/killed it works fine
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG, "remoteMessage......" + remoteMessage.getData());
try {
Map<String, String> params = remoteMessage.getData();
JSONObject object = new JSONObject(params);
Log.e(TAG, object.toString());
body = object.getString("not_id");
dataa = object.getString("data");
title = object.getString("not_type");
type = object.getString("type");
Sender = object.getString("Sender");
SenderProfileUrl = object.getString("SenderProfileUrl");
wakeUpScreen();
addNotification(remoteMessage.getData());
}
/* when your phone is locked screen wakeup method*/
private void wakeUpScreen() {
PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
Log.e("screen on......", "" + isScreenOn);
if (isScreenOn == false) {
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "MyLock");
wl.acquire(10000);
PowerManager.WakeLock wl_cpu = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyCpuLock");
wl_cpu.acquire(10000);
}
}
/*Add notification method use for add icon and title*/
private void addNotification(Map<String, String> data) {
int icon = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ?R.drawable.logo_app: R.drawable.logo_app;
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setSmallIcon(icon)
//.setSmallIcon(R.drawable.logout_icon)
.setContentTitle(data.get("title") + "")
.setChannelId("channel-01")
.setAutoCancel(true)
.setSound(uri)
.setContentText(data.get("body") + "");
Notification notification = new Notification();
Log.e(TAG, "titlee" + data.get("title"));
// Cancel the notification after its selected
notification.flags |= Notification.FLAG_AUTO_CANCEL;
if (sound)
notification.defaults |= Notification.DEFAULT_SOUND;
if (vibration)
notification.defaults |= Notification.DEFAULT_VIBRATE;
builder.setDefaults(notification.defaults);
}
}
when i click notification bar goto the particular screen using type like this:
/*notification send with type calling */
if (data.get("not_type").equals("calling")) {
if (data.get("type").equals("name")) {
Log.e(TAG, "ttt--" + type);
Intent notificationIntent = new Intent(this, CallingActivity.class);
notificationIntent.putExtra("notification_room_id", body);
notificationIntent.putExtra("data", dataa);
notificationIntent.putExtra("calling", "calling");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
builder.setSound(uri);
builder.setAutoCancel(true);
// Add as notification
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Hello";// The user-visible name of the channel.
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel("channel-01", name, importance);
manager.createNotificationChannel(mChannel);
}
manager.notify((int) ((new Date().getTime() / 1000L) % Integer.MAX_VALUE), builder.build());
}
this is my manifest add notification class and token class
<service android:name=".notification.NotificationService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".notification.TokenService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service
android:name=".notification.NLService"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
i hope it helps you
This question already has answers here:
Android notification is not showing
(14 answers)
Closed 4 years ago.
//I had given intent in oncreate
Intent alarmIntent = new Intent(getContext(), ServiceReceiver.class);
pendingIntent = PendingIntent.getBroadcast(getContext(),
0, alarmIntent, 0);
// here i am setting alarm
public void setALARM(String time, String strDate){
AlarmManager manager = (AlarmManager) getContext()
.getSystemService(Context.ALARM_SERVICE);
String strHour=formateDateFromstring("HH:mm","HH",time);
String strMin=formateDateFromstring("HH:mm","mm",time);
String strdate=formateDateFromstring("yyyy-MM-dd","dd",strDate);
String strMonth=formateDateFromstring("yyyy-MM-dd","MM",strDate);
String strYear=formateDateFromstring("yyyy-MM-dd","yyyy",strDate);
int hour=Integer.parseInt(strHour);
int min=Integer.parseInt(strMin);
int date=Integer.parseInt(strdate);
int month=Integer.parseInt(strMonth)-1;
int year=Integer.parseInt(strYear);
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH,date); //1-31
cal.set(Calendar.MONTH,month); //first month is 0!!! January is zero!!!
cal.set(Calendar.YEAR,year);//year...
cal.set(Calendar.HOUR_OF_DAY,hour); //HOUR
cal.set(Calendar.MINUTE,min);//MIN
cal.set(Calendar.SECOND,0);
manager.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
pendingIntent);
}
//Here is my receiver class
public class ServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.logob_icon_prestigesalon)
.setContentTitle("ABC")
.setContentText("time to go")
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
Toast.makeText(context,"service",Toast.LENGTH_LONG).show();
NotificationManager notificationmanager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationmanager.notify(0, builder.build());
}
}
//I mentioned receiver class in manifest
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".ServiceReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<!-- Will not be called unless the application explicitly enables it -->
<receiver android:name=".DeviceBootReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
I want to set an alarm for the exact time.I checked the code in debug mode whether the debug is coming inside the onReceive if the given time comes.The debug is coming whe the given time is reached.The issue is notification is not visible.
Not sure if it is your specific problem, but NotificationCompat.Builder(Context context) is deprecated in API level 26.1.0. You should use NotificationCompat.Builder(Context, String) instead. All posted Notifications must specify a NotificationChannel Id for 26+ devices as you can check in Notification and Notification.Builder documentation
Try something like this,Have not tested.
String channelID = "Notification_Channel_ID";
String channelDesr = "Notification_channel_description";
buildNotificationChannel(channelID,channelDesr);
public void buildNotificationChannel(String channelID, String description) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager manager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
if (manager.getNotificationChannel(channelID) == null) {
NotificationChannel channel = new NotificationChannel(channelID, description,
NotificationManager.IMPORTANCE_LOW);
channel.setDescription(description);
manager.createNotificationChannel(channel);
}
}
}
NotificationCompat.Builder builder = new
NotificationCompat.Builder(context,channelID)
.setSmallIcon(R.drawable.logob_icon_prestigesalon)
.setContentTitle("ABC")
.setContentText("time to go")
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
Toast.makeText(context,"service",Toast.LENGTH_LONG).show();
NotificationManager notificationmanager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
notificationmanager.notify(0, builder.build());
Basically, I am trying to build an alarm app which has some buttons with some predefined Date and Time. I have tried using AlarmManager and broadcast receiver in the first place but didn't work. So, I used foreground service with alarmManager but still, the alarm doesn't fire when the app is destroyed. I am a newbie. I tried searching the internet but I had no luck. Hope there is a lot of people here to help me out. Thanks in Advance.
Here I am just trying to set only one alarm for testing. Otherwise, I am using a variable as request code for multiple alarms.
AndroidManifest.xml
<receiver android:name=".AlarmReceiver" />
<activity
android:name=".Activity.PlayerDetailsActivity"
android:theme="#style/AppTheme.NoActionBar"></activity>
<activity android:name=".Activity.FixtureActivity" />
<service android:name=".MyService"/>
MyService.java
public class MyService extends Service {
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Started", Toast.LENGTH_SHORT).show();
Log.e("service","service");
long longExtra = intent.getLongExtra(Constants.ALARM_TIME, 0000);
//Testing Area Start
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(longExtra);
int mMin = calendar.get(Calendar.MINUTE);
int mMonth = calendar.get(Calendar.MONTH);
int mDay = calendar.get(Calendar.DAY_OF_MONTH);
int mHour = calendar.get(Calendar.HOUR_OF_DAY);
Log.e("hour min month day"," "+mHour + " : "+mMin+" month : "+mMonth+" "+" Date : "+mDay+" ");
String currentDateTime=getDeviceDateTime();
Log.e("CurrentdateTime",""+currentDateTime);
Log.e("longExtra",""+longExtra);
//Testing Area End
String CHANNEL_ID = "my_channel_01";
NotificationChannel channel = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channel = new NotificationChannel(CHANNEL_ID,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("dfdf")
.setSmallIcon(R.drawable.ic_notifications_black_24dp)
.setContentText("dfdfd").build();
startForeground(3, notification);
}
/*Intent alertIntent = new Intent(getApplicationContext(), AlarmReceiver.class);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Log.d("I",""+longExtra);
alarmManager.set(AlarmManager.RTC_WAKEUP, 6000000, PendingIntent.getBroadcast(getApplicationContext(), 0, alertIntent,
PendingIntent.FLAG_ONE_SHOT));*/
AlarmManager manager= (AlarmManager)getSystemService(ALARM_SERVICE);
Intent myIntent;
myIntent = new Intent(getApplicationContext(),AlarmReceiver.class);
myIntent.putExtra("check",true);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,0,myIntent,0);
Long finalTime =longExtra-System.currentTimeMillis();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
manager.setExact(AlarmManager.RTC_WAKEUP,longExtra,pendingIntent);
}
else
manager.set(AlarmManager.RTC_WAKEUP,longExtra,pendingIntent);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Alarmreceiver.java
public class AlarmReceiver extends BroadcastReceiver
{
public static final String CHANNEL_ID = "47";
#Override
public void onReceive(Context context, Intent intent)
{
intent = new Intent(context, SplashActivity.class);
intent.putExtra("not",true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationCompat = new NotificationCompat.Builder(context,CHANNEL_ID);
notificationCompat.setSmallIcon(R.drawable.ic_notifications_black_24dp);
notificationCompat.setContentTitle("My Noticiation");
notificationCompat.setContentText(getPreferences(context).getDateTime());
notificationCompat.setContentIntent(pendingIntent);
notificationCompat.setSound(alarmSound);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "channel name", importance);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
Notification notification = notificationCompat.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(100,notification);
Toast.makeText(context, "Alarm Working", Toast.LENGTH_SHORT).show();
}
}
you have to start your service so then it can set alarm and fire reciever
start it like this from your activity class
Intent intent=new Intent(this,MyService.class);
startService(intent);
Consider using JobScheduler as a persistence mechanism. It is wakeful and handles the wake locks for you. Only downside it's for Android SDK >= 21 (Lollipop).
There's also a new friend in town that does the backward compatibility for you: WorkManager and will work with all version of Android, even below Lollipop.
Intent myIntent;
myIntent = new Intent(this, AlarmReceiver.class);
myIntent.putExtra("check",true);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, 0);
=============================
Would you change your above code like this ?
Intent myIntent;
myIntent = new Intent(this , MyService.class);
myIntent.setAction("REQUEST_FROM_ALARM_MANAGER");
PendingIntent pendingIntent = PendingIntent.getForegroundService(this,0,myIntent,0);
====================================================
And Service class
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mContext = this;
Log.e(TAG, "onStartCommand " + intent);
if(intent == null) {
return START_NOT_STICKY;
}
if("REQUEST_FROM_ALARM_MANAGER".equals(intent.getAction())){
// show Notification here for your foreground service
}
return START_NOT_STICKY;
}
You have to start a service that survive to your app, you can see here how to do it
I need to show the user a notification at the same time every day (based on a user selecting the time it is shown). With API 25 and earlier I can use AlarmManager without a problem. However with API 26 (Oreo) it will crash my app if the app is in the background for more than a few minutes. Nothing I've done seems to prevent AlarmManager crashing after about a minute of the app being in the background.
Based on what I have seen online the only solution is to use a JobScheduler, but there doesn't seem to be anyway to have a JobScheduler start at a certain time and then recur every day. (I can have it run at a certain time by calling setOverrideDeadline or I can make it recurring by calling setPeriodic, but calling both throws and exception.)
This is my code for the JobScheduler (I have it set to recur every 15 seconds for testing, but I also want to be able to start it at a certain time):
private void setReminders(){
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_BOOT_COMPLETED) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.RECEIVE_BOOT_COMPLETED }, 613);
return;
}
SharedPreferences sharedPreferences = this.getSharedPreferences(getString(R.string.shared_pref_file_name), ContextWrapper.MODE_PRIVATE);
boolean showReminder = sharedPreferences.getBoolean(getString(R.string.shared_pref_reminder_active_key), false);
int hour = sharedPreferences.getInt(getString(R.string.shared_pref_reminder_hour_key), 21);
int minute = sharedPreferences.getInt(getString(R.string.shared_pref_reminder_minute_key), 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
long startUpTime = Calendar.getInstance().getTimeInMillis() + 10000; //calendar.getTimeInMillis() + 10000;
JobInfo.Builder builder = new JobInfo.Builder( 613, new ComponentName(getPackageName(), SefiraReminderJobService.class.getName()));
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE)
.setOverrideDeadline(15000)
.setRequiresDeviceIdle(false)
.setRequiresCharging(false)
.setPersisted(true);
builder.setPeriodic(Math.max(15000, JobInfo.getMinPeriodMillis()));
JobScheduler jobScheduler = (JobScheduler) getSystemService( Context.JOB_SCHEDULER_SERVICE );
if(jobScheduler.schedule(builder.build()) == JobScheduler.RESULT_FAILURE ) {
Log.w("MainActivity.setReminders", "Something went wrong when scheduling the reminders" );
}
}
This is my JobIntentService class:
public final class ReminderJobService extends JobIntentService {
private NotificationManager notificationManager;
private PendingIntent pendingIntent;
private static int NOTIFICATION_ID = 1234;
private static String NOTIFICATION_CHANNEL_ID = "my-reminder-channel";
private Notification notification;
#Override
protected void onHandleWork(#NonNull Intent intent) {
Context context = this.getApplicationContext();
notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent mIntent = new Intent(this, MainActivity.class);
pendingIntent = PendingIntent.getActivity(context, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Reminders", NotificationManager.IMPORTANCE_DEFAULT);
// Configure the notification channel.
notificationChannel.setDescription("My Reminders");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationManager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
notification = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.ic_launcher_foreground)
//.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.ic_launcher))
//.setTicker("ticker value")
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM))
.setContentTitle("Reminder")
.setContentText("Reminder Message").build();
notification.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
notification.defaults |= Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE;
notification.ledARGB = 0xFFFFA500;
notification.ledOnMS = 800;
notification.ledOffMS = 1000;
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
try {
notificationManager.notify(NOTIFICATION_ID, notification);
} catch (Exception ex){
ex.printStackTrace();
}
}
}
My AndroidManifest contains the following:
<service android:name="ReminderJobService"
android:permission="android.permission.BIND_JOB_SERVICE"></service>
As well as:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
How can I send a recurring notification each day at a specific time on Android 26/8.0/Oreo even when the app is in the background?
This workable decision but with deprecated logic:
public scheduleEvent(int id, long scheduleTime) {
final PendingIntent pendingIntent = pendingIntent(id);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, scheduleTime, pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, scheduleTime, pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, scheduleTime, pendingIntent);
}
private PendingIntent pendingIntent(int id) {
final Intent intent = new Intent(app, EventReceiver.class);
intent.setAction("some event " + id);
return PendingIntent.getBroadcast(context, 10, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Create EventReceiver don't forget add it in AndroidManifest
public class EventReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(final Context context, final Intent intent) {
final ComponentName comp = new ComponentName(context.getPackageName(), EventService.class.getName());
startWakefulService(context, intent.setComponent(comp));
}
}
Create EventService, also add it to the AndroidManifest
public class EventService extends IntentService {
#Override
protected void onHandleIntent(final Intent intent) {
//Your logic here
}
}