华为EMUI 4.0+上的电池优化(唤醒锁)

时间:2016-10-10 09:06:22

标签: android gps wakelock huawei

美好的一天, 情况:

我正在开发用作运动追踪器/导航应用的Android应用程序 - 因此它需要永久连接到GPS以及永久唤醒设备。每秒录制一次。

当前的解决方案工作多年,感谢wakelocks使设备保持清醒状态。

Android 6.0中的打盹模式比较复杂,但情况并非如此。

华为设备可能是不同类型的优化。

以下是日志的一部分:

10-10 10:33:18.462 1014-384 D/PFW.HwPFWAppWakeLockPolicy: getUidWakeLock uid: 10097 wakelock >= 10 mins 10-10 10:33:18.543 1014-384 D/PFW.HwPFWAppWakeLockPolicy: force stop abnormal wakelock app uid: 10097 10-10 10:33:18.558 1014-384 I/ActivityManager: Force stopping menion.android.locus appid=10097 user=0: from pid 1014

所以大约在30多分钟,系统只是决定该应用使用过多wakelocks并使用所有服务,历史记录完全终止它,只需kill

有关此行为和任何建议的任何经验,如何执行此简单任务(屏幕关闭时永久录制GPS位置)更好?

正如我在开始时所写的,除了新华为之外的所有其他设备,这样的系统可以正常工作多年。

编辑:请注意一位用户的评论(已删除?),华为电池管理器中的“白​​名单”应用(标记为“受保护的应用”)对此问题没有影响。

2 个答案:

答案 0 :(得分:9)

有两个华为系统应用程序可能会杀死用户应用程序以节省电池电量:

  • 系统管理员(com.huawei.systemmanager)会杀死屏幕关闭后仍在运行的所有应用,除非他们在"受保护的应用"列表。
  • PowerGenie(com.huawei.powergenie)会杀死任何持有唤醒锁定的应用程序。

听起来你的应用被PowerGenie杀死了。您可以通过利用PowerGenie的唤醒锁定标签的硬编码白名单来避免这种情况。例如,如果您的唤醒锁标记是" LocationManagerService"它将被PowerGenie忽略,因为系统服务使用相同的标签保存唤醒锁,并且PowerGenie将其列入白名单。

答案 1 :(得分:1)

您是否尝试过设置定期释放WakeLock的闹钟,然后在几秒钟后重新启动它?如果问题是华为的Android不喜欢Wakelocks的滥用,那么如果你不时发布它们可能会好吗? 例如:我想你将在前台运行后台进程。如果是这样,请在onStartCommand中插入:

setupWakeupAlarm(context);

其中方法定义为:

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!");
}

接收者是本地班级的地方:

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
        );
    }
}

请注意,在我的情况下,我的后台服务也在前台运行,我决定停止前台。不确定是否有必要。

风险当然是在Wakelock未激活的3秒内,您的过程可能会被杀死。