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

8

您好, 情况如下:

我正在开发一款Android应用程序,它作为运动追踪/导航应用程序 - 因此需要与GPS保持永久连接,并且设备保持唤醒状态。记录每秒完成。

多年来,当前解决方案的工作是由于wakelocks保持设备唤醒。

Android 6.0+中的Doze模式使情况变得复杂,但这不是本例。

在华为设备上,可能有不同类型的优化。

以下是日志的一部分:

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个回答

10

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

  • SystemManager (com.huawei.systemmanager):除非应用程序在“受保护应用程序”列表中,否则在屏幕关闭后仍在运行的应用程序将被杀死。
  • PowerGenie (com.huawei.powergenie):长时间持有唤醒锁的应用程序将被杀死。

看起来你的应用程序被PowerGenie杀死了。你可以利用PowerGenie硬编码的唤醒锁标签白名单来避免这种情况。例如,如果你的唤醒锁标签是“LocationManagerService”,它将被PowerGenie忽略,因为系统服务持有具有相同标签的唤醒锁并已被PowerGenie列入白名单。


它可以工作了!我已将唤醒锁标签指定为“LocationManagerService”。 - Oleg A
请问您指定唤醒锁标签的意思是什么? - rosu alin
@OlegA 你使用PARTIAL_WAKE_LOCK作为唤醒标志吗? - rosu alin
这个问题在Mate 10 Pro上使用一段时间后仍会导致我的GPS失效 :( - rosu alin
@rosualin 标签是 newWakeLock() 的第二个参数。 - akwizgran
显示剩余3条评论

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

请注意,在我的情况下,我还在前台运行我的后台服务,并决定停止前台。不确定是否有必要。
当然,风险是在3秒钟内Wakelock未激活时,您的进程可能会被终止。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接