Reputation: 13
I want to notify the user at a specific time using Alarm Manager. I have go through many answers and implemented but not working. The following code is working fine when App is running. It is not working when APP IN BACKGROUND & APP IS KILLED. Manifest file code
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver
android:name=".newAlarmBroadcast.AlarmReceiver"
android:enabled="true"
android:exported="false" />
AlarmReceiver class
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Notification.createNotificationChannel(context);
Notification.displayNotification(
context, context.getString(R.string.alarm), "Its time to do your work",
Constants.NOTIFICATION_ID
);
Notification Class
public class Notification {
public static void createNotificationChannel(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(
Constants.NOTIFICATION_CHANNEL_ID,
context.getString(R.string.alarm_channel),
importance
);
channel.setDescription(context.getString(R.string.channel_message));
NotificationManager manager = context.getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
public static void displayNotification(
Context context,
String title,
String body,
int id
) {
Intent intent = new Intent(context, NotesMainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, id, intent, 0);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(context, Constants.NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat manager = NotificationManagerCompat.from(context);
manager.notify(id, notificationBuilder.build());
}
Here I am setting alarm time
@SuppressLint("SimpleDateFormat")
private void setTheAlarm(long dateTime) {
alarmManager = (AlarmManager) requireActivity().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(requireActivity(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(requireActivity(), Constants.ALARM_ID, intent, 0);
if (SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, dateTime, pendingIntent);
} else {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, dateTime, pendingIntent);
}
Note Constants.NOTIFICATION_ID & Constants.ALARM_ID both are same as required.
Upvotes: 1
Views: 515
Reputation: 58
Use WorkManager as it is easier, light-weight on the OS and backward compatible.
add to your dependencies
implementation "androidx.work:work-runtime-ktx:2.7.1"
implementation "androidx.work:work-runtime:2.7.1"
Create worker class:
class MyWorker(val appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {
override fun doWork(): Result {
val notCompat = NotificationManagerCompat.from(appContext.applicationContext)
val channel = NotificationChannelCompat.Builder("com.yourcompany.noti_id", NotificationManagerCompat.IMPORTANCE_DEFAULT).setName("Importance").setName("Importance").setVibrationEnabled(true).build()
notCompat.createNotificationChannel(channel)
val noti = NotificationCompat.Builder(appContext.applicationContext, channel.id).setSmallIcon(R.drawable.ic_launcher_foreground).setContentTitle("Internal Test").setContentText("Hope" + Calendar.getInstance().timeInMillis).build()
/**
// If your are going to be doing long running operations. To avoid being killed by the //OS
setForegroundAsync(ForegroundInfo(channel.id.hashCode(), noti))
// .... Do long running operations here ....
**/
// Or If you are not doing long running operations....
NotificationManagerCompat.from(appContext.applicationContext).notify("organ".hashCode(), noti)
return Result.success()
}
add this to your manifest if you post as long running operations
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="location|microphone"
tools:node="merge" />
Possibly in a fore-ground service
WorkManager.getInstance(this )
.enqueueUniquePeriodicWork("com.yourcompany.mywork", ExistingPeriodicWorkPolicy.REPLACE,
PeriodicWorkRequestBuilder<MyWorker>(30, TimeUnit.MINUTES).setInitialDelay(1, TimeUnit.MINUTES).setConstraints(Constraints.NONE).build())
or If it is a one time work
WorkManager.getInstance(this).enqueueUniqueWork("com.yourcompany.mywork", ExistingWorkPolicy.REPLACE, OneTimeWorkRequestBuilder<MyWorker>().setScheduleRequestedAt(10, TimeUnit.MINUTES).build())
See also: https://developer.android.com/topic/libraries/architecture/workmanager https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running
Upvotes: 1