Reputation: 8856
This question may looks very broad but I will try to sum up as short I could do.
So I am replicating a sample app on Play store Multi Timer Free
App is for setting Multiple Timers.
I have almost completed the app. but I am facing some issues of battery optimization and Alarm Manager specifically Huawai and Honor (china Andorid OS). My Foreground service stops working after some time.
Question: Sample app mentioned above works very fantastic even without battery optimization whitelist. What could be the solution for this?
I have almost tries everything mentioned in links follows. but no luck
Doze mode - do foreground services continue to run?
How to handle background services in ANDROID O?
How to turn off battery optimization on Huawei devices
How to turn off battery optimization on the Huawei devices
How to turn off battery optimization on Huawei devices
Huawei device killing my foreground service, even with dontkillmyapp.com's solution
Optimize for Doze and App Standby
Android M startActivity battery optimization
Battery optimizations (wakelocks) on Huawei EMUI 4.0+
service killed when app cloes just in huawei device
Oreo (8.1) cannot start activity on lock screen
Creating a never ending background service in Android > 7
How does doze mode affect background/foreground services, with/without partial/full wakelocks?
What to do if alarms or sleep tracking don’t work?
Sample Code, When pressed device lock/unlock button, I want a simple TOAST to be shown when SCREEN_ON broadcast is received. This works fine for some time.
But in Huawei device => After killing the app by swipe -> after a 1 - 2 minutes my toast will stop working.
package com.demo.forgroundservicedemo
import android.content.Intent
import android.os.IBinder
import androidx.core.app.NotificationCompat
import android.os.Build
import android.app.*
import android.app.NotificationManager
import android.app.NotificationChannel
import android.content.BroadcastReceiver
import android.content.Context
import android.content.IntentFilter
import android.graphics.Color
import android.util.Log
import androidx.annotation.RequiresApi
import android.os.SystemClock
import android.app.AlarmManager
import android.app.PendingIntent
import android.widget.Toast
class ForegroundService : Service() {
override fun onCreate() {
Log.e("ForegroundService", "onCreate called")
super.onCreate()
}
@RequiresApi(Build.VERSION_CODES.O)
private fun startMyOwnForeground() {
val NOTIFICATION_CHANNEL_ID = CONST.CHANNELID
val channelName = CONST.channelName
val chan = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
channelName,
NotificationManager.IMPORTANCE_NONE
)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(chan)
val notificationIntent = Intent(this, MainActivity::class.java)
notificationIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
val intent = PendingIntent.getActivity(
this, 0,
notificationIntent, 0
)
val notificationBuilder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
notificationBuilder.setContentIntent(intent)
val notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(CONST.serviceTitle)
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.setAutoCancel(false)
.build()
notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
startForeground(2, notification)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.e("ForegroundService", "onStartCommand called")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.e("SDK_INT", ">= Build.VERSION_CODES.O")
startMyOwnForeground()
} else {
startForeground(1, Notification())
}
registerBroadcastReceiver()
return START_STICKY
}
override fun onDestroy() {
Log.e("ForegroundService", "onDestroy called")
super.onDestroy()
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
private var mPowerKeyReceiver: BroadcastReceiver? = null
private fun registerBroadcastReceiver() {
Log.e("registerBroadcast", "called")
val theFilter = IntentFilter()
/** System Defined Broadcast */
theFilter.addAction(Intent.ACTION_SCREEN_ON)
//theFilter.addAction(Intent.ACTION_SCREEN_OFF)
mPowerKeyReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.e("onReceive", "onReceive called")
val strAction = intent!!.action
if (strAction == Intent.ACTION_SCREEN_ON) {
Toast.makeText(context, "SCREEN ON", Toast.LENGTH_LONG).show()
}
}
}
applicationContext.registerReceiver(mPowerKeyReceiver, theFilter)
}
private fun unregisterReceiver() {
val apiLevel = Build.VERSION.SDK_INT
if (apiLevel >= 7) {
try {
applicationContext.unregisterReceiver(mPowerKeyReceiver)
} catch (e: IllegalArgumentException) {
mPowerKeyReceiver = null
}
} else {
applicationContext.unregisterReceiver(mPowerKeyReceiver)
mPowerKeyReceiver = null
}
}
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
Log.e("onTaskRemoved", "onTaskRemoved called")
unregisterReceiver()
val restartService = Intent(
applicationContext,
this.javaClass
)
restartService.setPackage(packageName)
val restartServicePI = PendingIntent.getService(
applicationContext, 1, restartService,
PendingIntent.FLAG_ONE_SHOT
)
val alarmService =
applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmService.setExactAndAllowWhileIdle(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 500,
restartServicePI
)
}
}
Upvotes: 6
Views: 1372
Reputation: 11
Emui 5.0 / 5. X: Settings > Application Management > Settings > special access rights Zhidao > ignore battery optimization > application, set to allow. Emui 8.0 / 8. X: Settings > apps and notifications > app Management > Settings > special access > ignore battery optimization > app, set to allow
Upvotes: 0
Reputation: 1737
Maybe the problem is that you don't have setRepeating
when scheduling an alarm?
I'm doing the same thing basically (updating the widget when the screen is ON), and I'm doing it like this:
alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis() + 1000, interval, pendingIntent)
Upvotes: 0