Battery optimizations (wakelocks) on Huawei EMUI 4.0+

送分小仙女□ 提交于 2019-11-30 20:21:29

There are two Huawei system apps that may kill user apps to save battery:

  • SystemManager (com.huawei.systemmanager) kills any apps that are still running after the screen is turned off, unless they're in the "Protected Apps" list.
  • PowerGenie (com.huawei.powergenie) kills any apps that hold wake locks for a long time.

It sounds like your app is being killed by PowerGenie. You can avoid this by taking advantage of PowerGenie's hardcoded whitelist of wake lock tags. For example, if your wake lock's tag is "LocationManagerService" it will be ignored by PowerGenie, because a system service holds a wake lock with the same tag and PowerGenie has whitelisted it.

Have you tried setting an Alarm that regularly releases the WakeLock and then reacquires it after a couple of seconds? If the issue is that Huawei's Android does not like the abuse of Wakelocks, maybe they are fine if you release it every now and then? For example: I suppose you will have a background process running in foreground. If so, in your onStartCommand insert:

setupWakeupAlarm(context);

where the method is defined as:

private static void setupWakeupAlarm(Context context) {
    AlarmManager mWakeUpAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    PendingIntent mWakeUpAlarmIntent;
    Intent serviceIntent;
    serviceIntent = new Intent(context, SSAlarmReceiver.class);
    mWakeUpAlarmIntent = PendingIntent.getBroadcast(context, 0, serviceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    // every 5 minutes 
    mWakeUpAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
            SystemClock.elapsedRealtime() + WAKEUP_ALARM_FREQUENCY, mWakeUpAlarmIntent);
    Log.d("TAG", "wakup alarm set up or reset!");
}

and where the receiver is a local class:

static public class SSAlarmReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(final Context context, Intent intent) {
        setupWakeupAlarm(context);
        mBackgroundService.stopForeground(true);
        if (mWakeLock.isHeld())
            mWakeLock.release();
        new Timer().schedule(
                new TimerTask() {
                    @Override
                    public void run() {
                        mWakeLock.acquire();
                        mBackgroundService.startForeground(mNotificationId, mNotification.getNotification());
                        }
                },
                3000
        );
    }
}

Note that in my case I also had my background service running in foreground and I decided to stop the foreground. Not sure it is necessary.

The risk is of course that in the 3 seconds the Wakelock is not active, your process can be killed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!