My app doesn't show notification when it is closed - android

I hope you're doing well. Please, if anyone can help me with this, kindly do it. I spent more days and time searching solution for that but I'm not satisfied.
I'm working on a todo and note taking app. About the todo functionality, the user can add a task, set the due date and time and select a ringtone for the todo. The user gets a notification with the ringtone chosen when the date and time set for the todo expire. I used Alarm manager with Broadcast receiver first and everything was working fine when I'm interacting with the app. But when I close the app and the activity is destroyed, the app doesn't send notification anymore. I did more researches on that but the solutions I found didn't work. Amoung the solutions, someone suggested to use service. So I replaced the Broadcast receiver by a service but it doesn't solve my problem. The app sends notification only when I'm interacting with it but when it gets closed, it doesn't send the notification. If there is anything I can do, please kindly help me.
Here is how I set the alarm
The alarm manager sends data to the servive class. All the data are saved in Room database.
object TodoAlarm {
#SuppressLint("SimpleDateFormat", "InlinedApi")
fun setTodoAlarmReminder(context: Context, todo: Todo) {
val alarmManager: AlarmManager? =
context.getSystemService(Context.ALARM_SERVICE) as AlarmManager?
val timeFormat = SimpleDateFormat("hh:mm a")
val parsedTime = timeFormat.parse(todo.time)
val expectedFormat = SimpleDateFormat("hh:mm")
val newTime = expectedFormat.format(parsedTime!!)
Log.d(TODO_ALARM_TAG, "NEW FORMATTED TIME IS $newTime")
val (todoHour, todoMinute) = newTime.split(":").map { it }
Log.d(TODO_ALARM_TAG, "THE HOUR IS $todoHour and minute is $todoMinute")
val intent = Intent(context, TodoAlarmService::class.java)
val pendingIntent = PendingIntent.getService(
context,
todo.id,
intent.apply {
action = SET_ACTION
putExtra("name", todo.name)
putExtra("date", todo.date)
putExtra("time", todo.time)
putExtra("id", todo.id)
putExtra("todo", todo)
putExtra("ringtoneUri", todo.ringtoneUri)
putStringArrayListExtra("days", todo.repeatFrequency as ArrayList<String>?)
Log.d(TODO_ALARM_TAG, "${todo.id}")
},
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_ONE_SHOT
)
val dateAndTimeReminder = "${todo.date} ${todo.time}"
Log.d(TODO_ALARM_TAG, "Date and Time $dateAndTimeReminder")
val format = SimpleDateFormat("dd/MM/yyyy h:mm a")
val todoTime = format.parse(dateAndTimeReminder)
val currentTime = Calendar.getInstance().time
Log.d(TODO_ALARM_TAG, "TODO TIME $todoTime")
Log.d(TODO_ALARM_TAG, "CURRENT TIME $currentTime")
if (todoTime >= currentTime) {
if (todo.repeatFrequency != null && todo.repeatFrequency.isNotEmpty()){
alarmManager?.let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
todoTime.time,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
} else {
alarmManager.setInexactRepeating(
AlarmManager.RTC_WAKEUP,
todoTime.time,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
}
}
}else{
alarmManager?.let {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
todoTime.time,
pendingIntent
)
} else {
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
todoTime.time,
pendingIntent
)
}
}
}
}
}
}
The service class the data. I didn't past all the code here because it's too long but it how it looks like.
class TodoAlarmService : Service(){
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent != null) {
showNotification(intent)
}
return START_STICKY
}
override fun onBind(p0: Intent?): IBinder? {
TODO("Not yet implemented")
}
fun showNotification(intent: Intent){
val context = applicationContext
val name = intent.getStringExtra("name")
val date = intent.getStringExtra("date")
val time = intent.getStringExtra("time")
val uri = intent.getStringExtra("ringtoneUri")
val dayList = intent.getStringArrayListExtra("days")
val todoDateAndTime = "$date $time"
val id = intent.getIntExtra("id", 0)
val notificationHelper = NotificationHelper(context)
val sound = RingtoneManager.getRingtone(context, uri?.toUri())
val startServiceIntent = Intent(context, TodoRingtoneService::class.java)
startServiceIntent.putExtra("ringtoneUri", uri)
val calendar = Calendar.getInstance()
val day = calendar.get(Calendar.DAY_OF_WEEK)
if (SET_ACTION == intent.action) {
if (id >= 0) {
if (dayList != null) {
when (dayList.size) {
0 -> {
context.startService(startServiceIntent)
notificationHelper.onCreateNotification(name = name!!, todoDateAndTime)
}
1 -> {
if (dayList[0] == "Daily") {
if (day == Calendar.MONDAY || day == Calendar.TUESDAY ||
day == Calendar.WEDNESDAY || day == Calendar.THURSDAY || day == Calendar.FRIDAY ||
day == Calendar.SATURDAY || day == Calendar.SUNDAY
) {
context.startService(startServiceIntent)
notificationHelper.onCreateNotification(name = name!!,
todoDateAndTime)
}
} else {
if (dayList[0] == "Monday") {
if (day == Calendar.MONDAY) {
context.startService(startServiceIntent)
notificationHelper.onCreateNotification(name = name!!,
todoDateAndTime)
}
}
...
I start the service in onStop main activity method.
#SuppressLint("NewApi")
override fun onStop() {
super.onStop()
startTodoAlarmService()
}
private fun startTodoAlarmService(){
val serviceIntent = Intent(this, TodoAlarmService::class.java)
applicationContext.startService(serviceIntent)
}
My Manifest file:
<?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="eg.esperantgada.dailytodo">
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SET_ALARM"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<application
android:name=".application.TodoApplication"
android:allowBackup="true"
android:fullBackupContent="true"
android:hardwareAccelerated="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.DailyToDo"
tools:ignore="DataExtractionRules,ExtraText">
<activity
android:name=".SecondStartActivity"
android:exported="false"
android:launchMode="singleTask"
android:theme="#style/Theme.AppCompat.NoActionBar"/>
<activity
android:name=".StartActivity"
android:configChanges="orientation|screenSize"
android:exported="true"
android:launchMode="singleTop"
android:theme="#style/Theme.AppCompat.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".SettingsActivity"
android:label="#string/title_activity_settings"
android:parentActivityName=".MainActivity" />
<receiver android:name=".broadcastreceiver.TodoAlarmReceiver"
android:enabled="true"/>
<receiver android:name=".broadcastreceiver.StopRingtoneReceiver"
android:enabled="true"/>
<receiver android:name=".broadcastreceiver.CancelNotificationReceiver"/>
tools:ignore="Instantiatable" />
<service android:name=".service.TodoRingtoneService"/>
<service android:name=".service.TodoAlarmService"
android:exported="true"
android:label="#string/app_name"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="eg.esperantgada.TodoAlarmService"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-1581485430995496~1199027256" />
</application>
</manifest>
If you want me to give any other details, kindly let me know. I'll really appreciate your help. Thanks

Related

Notification delayed on Pixel 4a running Android 13

I'm working on building an alarm clock app. The end goal is to add a specific feature to it, but right now I'm working on making it function as a regular alarm clock.
One problem I'm coming across is that when I run it on my Pixel 4a, the notification to dismiss the alarm comes later than it should. The BroadcastReceiver that launches the Service is called on time, and the ringtone and vibration are activated as soon as the broadcast is received, but I have noticed a delay of up to 15 seconds from when the broadcast is received to the time the alarm notification appears. Another strange thing is that if I set another alarm for a short time later, the notification may appear instantly like it should.
On Android Studio's emulator, the notification appears on time every time EDIT: on API 30. On API 33, the same thing happens as on my phone.
Here is the code for the service:
class AlarmService : Service() {
private lateinit var ringtone: Ringtone
private lateinit var vibrator: Vibrator
override fun onCreate() {
super.onCreate()
vibrator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val vibratorManager =
getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
vibratorManager.defaultVibrator
} else {
// Backwards compatibility for API < 31 requires using deprecated service
#Suppress("DEPRECATION")
getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val pendingIntent = getPendingIntent(intent)
val alarmLabel = intent?.getStringExtra(LABEL)
val shouldVibrate = intent?.getBooleanExtra(VIBRATE, false) ?: false
val ringtoneUri = getRingtoneUri(intent)
ringtone = getRingtone(ringtoneUri)
val notification = getNotification(pendingIntent, alarmLabel)
ringAndVibrate(shouldVibrate)
startForeground(1, notification)
return START_STICKY
}
override fun onDestroy() {
super.onDestroy()
ringtone.stop()
vibrator.cancel()
}
override fun onBind(p0: Intent?): IBinder? {
return null
}
#SuppressLint("UnspecifiedImmutableFlag") // In android < S, mutability flags not compatible
private fun getPendingIntent(intent: Intent?): PendingIntent {
val notificationIntent = Intent(this, RingActivity::class.java)
moveExtras(intent, notificationIntent)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getActivity(
this,
0,
notificationIntent,
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
} else {
PendingIntent.getActivity(
this,
0,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
}
private fun getRingtoneUri(intent: Intent?): Uri =
intent?.getParcelableExtra(RINGTONE_URI) ?: RingtoneManager.getDefaultUri(
RingtoneManager.TYPE_ALARM
)
private fun getRingtone(ringtoneUri: Uri): Ringtone {
val ringtone = RingtoneManager.getRingtone(this, ringtoneUri)
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build()
ringtone.audioAttributes = audioAttributes
ringtone.isLooping = true
return ringtone
}
private fun getNotification(pendingIntent: PendingIntent, alarmLabel: String?): Notification =
NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(alarmLabel ?: getString(R.string.notification_default_alarm_label))
.setSmallIcon(R.drawable.ic_baseline_alarm_24)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_ALARM)
.setFullScreenIntent(pendingIntent, true)
.build()
private fun ringAndVibrate(vibrate: Boolean) {
ringtone.play()
if (vibrate) {
val vibEffect = VibrationEffect.createWaveform(longArrayOf(0, 100, 1000), 0)
vibrator.vibrate(vibEffect)
}
}
}
EDIT: Here is the Android manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="[REDACTED]">
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:name=".app.AlarmApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="[REDACTED]">
<activity
android:name=".features.alarmring.RingActivity"
android:exported="false" />
<activity
android:name=".features.mainscreen.MainActivity"
android:exported="true"
android:showOnLockScreen="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".features.alarmscheduling.AlarmBroadcastReceiver"
android:exported="false">
</receiver>
<service android:name=".features.alarmring.AlarmService" />
</application>
</manifest>

Is my alarmManager code, capable to send broadcast?

I'm trying to create an alarm Manager that sends notification every 24 hours at specific time consulted other Stackoverflow code. I tried this code below but onReceive() never gets executed. What i'm doing wrong?
private var HOUR_TO_SHOW_PUSH = 21
private var MINUTE_TO_SHOW_PUSH = 0
private val REQUEST_CODE = 100
private lateinit var alarmManager: AlarmManager
private lateinit var pendingIntent: PendingIntent
class MainActivity : AppCompatActivity() {
...
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlertReceiver::class.java)
pendingIntent = PendingIntent.getBroadcast(this, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val calendar = GregorianCalendar.getInstance().apply {
if (get(Calendar.HOUR_OF_DAY) >= HOUR_TO_SHOW_PUSH) {
add(Calendar.DAY_OF_MONTH, 1)
}
set(Calendar.HOUR_OF_DAY, HOUR_TO_SHOW_PUSH)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
AlertReceiver
class AlertReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
override fun onReceive(context: Context?, intent: Intent?) {
Toast.makeText(context, "Alarm", Toast.LENGTH_LONG).show()
println("Alarm")
Log.e("Alarm","Alarm Triggered")
}
Manifest
<receiver
android:name=".AlertReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<action android:name="MyBroadcastReceiverAction"/>
</intent-filter
</receiver>
Normally you would register your receiver in the AndroidManifest like this:
<receiver android:name=".MyBroadcastReceiver" 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>
https://developer.android.com/guide/components/broadcasts
it depends on the battery optimization applied to the app by the device, it varies from a device manufacturer to other
Normally you will find it in Settings > Apps > "your app name" > Battery Saver Set it to No Restrictions

React native with foreground service - handleWindowVisibility: no activity for token android.os.BinderProxy

I create app in react native, that needs to run foreground service containing native code. The service itself works well but after killing main application process (by pressing square button and swiping the app away) - it sometimes returns without any complications on launch from icon or notification but it oftens displays blank screen (without any activity launched) and prints handleWindowVisibility: no activity for token android.os.BinderProxy in logcat. I've been googling it for a few hours but there is little feedback on that matter and nothing seems to work for me.
The class I use to communicate through RCT Bridge
#ReactMethod
fun init() {
val service = Intent(context, MyService::class.java)
service.action = SERVICE_ACTION_EXECUTE
if(!isMyServiceRunning(MyService::class.java)) {
Log.i("MyService", "Starting new service")
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(service)
} else {
context.startService(service)
}
}
val serviceConnection = object: ServiceConnection {
override fun onServiceConnected(p0: ComponentName?, binder: IBinder?) {
myService = (binder as MyService.LocalBinder).getService()
myService?.bindClient(this#Integrator)
}
override fun onServiceDisconnected(p0: ComponentName?) {
myService?.unbindClient()
}
}
context.bindService(service, serviceConnection, Context.BIND_AUTO_CREATE)
}
private fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
val manager: ActivityManager? =
context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager?
for (service in manager?.getRunningServices(Int.MAX_VALUE)!!) {
if (serviceClass.name == service.service.className) {
return true
}
}
return false
}
My foreground service:
#RequiresApi(api = Build.VERSION_CODES.O)
private fun createNotificationChannel() {
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val name: CharSequence =
getString(R.string.app_name)
val channel =
NotificationChannel(NOTIFICATION_CHANNEL_ID, name, NotificationManager.IMPORTANCE_LOW)
notificationManager.createNotificationChannel(channel)
}
private fun buildNotification(): Notification {
val intent = Intent(applicationContext, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, intent, 0)
if(notificationBuilder == null) {
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
notificationBuilder = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(pendingIntent)
.setCategory(Notification.CATEGORY_SERVICE)
.setOngoing(true)
}
// Set Exit button action
val exitIntent =
Intent(applicationContext, MyService::class.java).setAction(SERVICE_ACTION_STOP)
notificationBuilder!!.addAction(
android.R.drawable.ic_delete,
getString(R.string.close),
PendingIntent.getService(applicationContext, 0, exitIntent, 0)
)
return notificationBuilder!!.build()
}
override fun onCreate() {
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
createNotificationChannel()
val notification = buildNotification()
startForeground(NOTIFICATION_FOREGROUND_SERVICE_ID, notification)
val action = intent?.action
if(action != null){
when(action) {
SERVICE_ACTION_EXECUTE -> {
Log.d(TAG, "Service executed")
executor.execute(IncomingIntentRouter(intent))
}
SERVICE_ACTION_STOP -> {
Log.d(TAG, "Service stopped")
stopService()
}
}
} else {
Log.d(TAG, "Got null onStartCommand() action")
}
return START_STICKY
}
Android manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="#style/AppTheme"
android:networkSecurityConfig="#xml/network_security_config"
android:extractNativeLibs="true">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService" />
</application>

Android notification not comes

I have an Android app where i schedule some notifications at specific times every day with alarmManager and receiver like this
fun addNot() {
val alarmMgr = context!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager?
val intent = Intent(this.context!!, MyAlarmReceiverTest::class.java)
val pendingIntent = PendingIntent.getBroadcast(this.context!!, 0, intent, 0)
val current = Calendar.getInstance()
val time = createDate("13:58:00")
if(time < current) {
time.add(Calendar.DATE,1)
}
alarmMgr!!.setRepeating(AlarmManager.RTC_WAKEUP, time.timeInMillis ,AlarmManager.INTERVAL_DAY,pendingIntent)
}
fun createDate(str: String):Calendar {
val separated = str.split(":").toTypedArray()
val datetimeToAlarm = Calendar.getInstance()
datetimeToAlarm.set(Calendar.HOUR_OF_DAY,separated[0].toInt())
datetimeToAlarm.set(Calendar.MINUTE,separated[1].toInt())
datetimeToAlarm.set(Calendar.SECOND,separated[2].toInt())
return datetimeToAlarm
}
With this receiver
class MyAlarmReceiverTest : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val notification = Notification.Builder(MyApplication.appContext)
.setContentTitle("title goes here")
.setContentText("this is content")
.setSmallIcon(R.mipmap.app_logo_final)
.setLargeIcon(
BitmapFactory.decodeResource(
MyApplication.appContext.getResources(),
R.mipmap.app_logo_final
)
)
.setContentIntent(null)
.build()
notification.sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + MyApplication.appContext.getPackageName() + "/raw/a")
var notificationManager = MyApplication.appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager?.notify(45545454, notification)
}
}
And the manifest
<receiver
android:name=".MyAlarmReceiverTest"
android:enabled="true"
android:stopWithTask="false">
<intent-filter>
<action android:name="com.simplemobiletools.applauncher.sendbroadcast" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
Questions :
1- the above notification sometimes triggers and sometimes not , why ?
2- should i use job or workmanager for this ?
App support is from api 21 if this matters

alarmmanger sometimes works or not when the app is killed in android

I want to notify at midnight. So I used alrammanager. the alrammanager is working well when it is in foreground or background. But the problem is occured when my app is killed. The alrammanager sometimes works or not. I don't understand this weird happening...
For example, when the notification occurs every three minutes, the app works well even if it is in the foreground or background. But when the app kiiled, the notification is occured or not even though there is no change in code. Please help me...
MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val picker = findViewById(R.id.timePicker) as TimePicker
picker.setIs24HourView(true)
val nextNotifyTime: Calendar = GregorianCalendar()
val nextDate: Date = nextNotifyTime.getTime()
val currentTime: Date = nextNotifyTime.getTime()
val HourFormat = SimpleDateFormat("kk", Locale.getDefault())
val MinuteFormat = SimpleDateFormat("mm", Locale.getDefault())
val pre_hour: Int = HourFormat.format(currentTime).toInt()
val pre_minute: Int = MinuteFormat.format(currentTime).toInt()
if (Build.VERSION.SDK_INT >= 23) {
picker.hour = pre_hour
picker.minute = pre_minute
} else {
picker.currentHour = pre_hour
picker.currentMinute = pre_minute
}
val button: Button = findViewById(R.id.button) as Button
button.setOnClickListener {
val hour: Int
val hour_24: Int
val minute: Int
if (Build.VERSION.SDK_INT >= 23) {
hour_24 = picker.hour
minute = picker.minute
} else {
hour_24 = picker.currentHour
minute = picker.currentMinute
}
if (hour_24 > 12) {
hour = hour_24
}
else {
hour = hour_24- 12
}
val calendar: Calendar = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, hour)
set(Calendar.MINUTE, minute)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
if(calendar.after(Calendar.getInstance())) {
//calendar.add(Calendar.DATE, 1)
}
diaryNotification(calendar)
}
}
fun diaryNotification(calendar: Calendar) {
val pm = this.packageManager
val receiver = ComponentName(this, DeviceBootReceiver::class.java)
val alarmIntent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, 60*1000, pendingIntent)
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP)
}
AlarmReceiver
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationIntent = Intent(context, MainActivity::class.java)
notificationIntent.flags = (Intent.FLAG_ACTIVITY_CLEAR_TOP
or Intent.FLAG_ACTIVITY_SINGLE_TOP)
var notification = CustomNotification.getNotificationBuilderInstance(context)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelName = "channel name"
val importance = NotificationManager.IMPORTANCE_LOW
val channel = NotificationChannel(CHANNEL_ID, channelName, importance)
notificationManager.createNotificationChannel(channel)
}
notificationManager.notify(NOTIFICATION_ID, notification.build())
}
}
DeviceBootReceiver
class DeviceBootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (Objects.equals(intent.action, "android.intent.action.BOOT_COMPLETED")) {
val alarmIntent = Intent(context, AlarmReceiver::class.java)
val pendingIntent =
PendingIntent.getBroadcast(context, 0, alarmIntent, 0)
val manager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val millis = Calendar.getInstance().timeInMillis
manager.setRepeating(
AlarmManager.RTC_WAKEUP, millis,
60*1000, pendingIntent
)
}
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.haii.alarmdemo">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:name=".GlobalApplication"
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=".DeviceBootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".AlarmReceiver" />
</application>
</manifest>
go to settings -> app -> YOUR APK NAME -> enable AUTOSTART (or something similar)
now even if your app is killed you will receive your notification
Also I suggest you to take a look at this link: LINK
Hope this "solution" can help you, cya ;)

Categories

Resources