Huawei device killing my foreground service, even with dontkillmyapp.com's solution Huawei device killing my foreground service, even with dontkillmyapp.com's solution android android

Huawei device killing my foreground service, even with dontkillmyapp.com's solution


I had a similar problem a few months ago, I spent a lot of time to search a solution and finally i have found this (i don't know if works for you, but it was help me).

I implemented in an application that I developed, a service that recover the user position every minutes, this position is saved in the sqlite database of the device. I need that the application work alway without interrupt.

In the test phase I found that some devices interrupted the execution of my code (like in your case).

After several fists on my desk, I realized that the problem was related to energy saving options which are different for some manufacturers but also for Android versions.

This solution help me:

@SuppressLint({"NewApi", "BatteryLife"})private void checkOptimization() {    String packageName = getApplicationContext().getPackageName();    PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);    if (pm != null) {        if (!pm.isIgnoringBatteryOptimizations(packageName)) {                Intent intent = new Intent();                intent.setAction(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);                intent.setData(Uri.parse("package:" + ctx.getPackageName()));                ctx.startActivity(intent);        } else {            new initialize().execute();        }    }}

Basically I ask the user (I can't do it any other way) to allow my application to avoid being optimized (this code work for Build.VERSION.SDK_INT >= 23)

The manifest file needs this permission:

android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS  


This is not a Huawei related solution but there are useful actions to mitigate the problem.

Calling startForeground and START_STICKY is required in this case

/** YourService **/override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {    startForeground(        App.NOTIFICATION_ID_YOUR_SERVICE,        buildNotification("Foo bar")    )    return START_STICKY}

These two methods allow the user to disable doze (Oreo>) and enable autostart permission (some OEM) to preserve the STICKY service lifecycle.

/** YourActivity **/fun openBatteryOptimization(context: Context) {    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {        val intent = Intent()        intent.action = Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS        context.startActivity(intent)    } else {        //Timber.d("Battery optimization not necessary")    }}fun openAutostartSettings(context: Context) {    try {        val intent = Intent()        val manufacturer = Build.MANUFACTURER        if ("xiaomi".equals(manufacturer, ignoreCase = true)) {            intent.component = ComponentName(                "com.miui.securitycenter",                "com.miui.permcenter.autostart.AutoStartManagementActivity"            )        } else if ("oppo".equals(manufacturer, ignoreCase = true)) {            intent.component = ComponentName(                "com.coloros.safecenter",                "com.coloros.safecenter.permission.startup.StartupAppListActivity"            ) //need "oppo.permission.OPPO_COMPONENT_SAFE" in the manifest        } else if ("vivo".equals(manufacturer, ignoreCase = true)) {            intent.component = ComponentName(                "com.vivo.permissionmanager",                "com.vivo.permissionmanager.activity.BgStartUpManagerActivity"            )        } else if ("Letv".equals(manufacturer, ignoreCase = true)) {            intent.component = ComponentName(                "com.letv.android.letvsafe",                "com.letv.android.letvsafe.AutobootManageActivity"            )        } else if ("Honor".equals(manufacturer, ignoreCase = true)) {            intent.component = ComponentName(                "com.huawei.systemmanager",                "com.huawei.systemmanager.optimize.process.ProtectActivity"            )        } else {            //Timber.d("Auto-start permission not necessary")        }        val list = context.packageManager            .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)        if (list.size > 0) {            context.startActivity(intent)        }    } catch (e: Exception) {    }}

Also using partial wake lock help to mitigate but it does not guarantee to keep alive the service.

/** YourService **/private val wakeLock: PowerManager.WakeLock by lazy {    (getSystemService(Context.POWER_SERVICE) as PowerManager).run {        newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ServiceWakelock")    }}private fun acquireWakelock() {    try {        wakeLock.let {            wakeLock.setReferenceCounted(false)            if (!wakeLock.isHeld) {                wakeLock.acquire()            }        }    } catch (e: RuntimeException) {    }}private fun releaseWakelock() {    try {        wakeLock.let {            if (it.isHeld) {                it.release()            }        }    } catch (e: RuntimeException) {    }}override fun onCreate() {    super.onCreate()    acquireWakelock()}override fun onDestroy() {    releaseWakelock()    super.onDestroy()}

With Binder you can check if the service is running or not (and starts it up again) and you can get the instance of the service.

/** YourActivity **/private val mConnection = object : ServiceConnection {    override fun onServiceConnected(className: ComponentName, iBinder: IBinder) {        // The system calls this to deliver the IBinder returned by the service's onBind() method.        val binder = iBinder as YourService.YourBinder        service = binder.getService()        bound = true    }    override fun onServiceDisconnected(arg0: ComponentName) {        // The Android system calls this when the connection to the service is unexpectedly lost, such as when the service has crashed or has been killed. This is not called when the client unbinds        bound = false    }}private fun bindYourService() {    Intent(this, YourService::class.java).also { intent ->        applicationContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE)    }}private fun unbindYourService() {    try {        applicationContext.unbindService(mConnection)    } catch (e: Exception) {        Timber.e(e)    }    bound = false}/** YourService **/private val binder = YourBinder()inner class YourBinder: Binder() {    fun getService(): YourService = this@YourService}override fun onBind(intent: Intent): IBinder {    return binder}override fun onRebind(intent: Intent?) {    super.onRebind(intent)}override fun onUnbind(intent: Intent?): Boolean {    return super.onUnbind(intent)}


Huawei's EMUI monitors and manages the battery consumption of the apps strictly. Even app has the permissions of Secondary Launch, Run in Background and Auto-Launch, EMUI may kill it or it's background processes after a while.

EMUI manages this through a list and as i know if an application is having such issues, it is necessary to apply for a special permission to be on that list.