8

美好的一天,情况:

我正在开发用作运动追踪器/导航应用程序的 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 位置)?

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

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

4

2 回答 2

10

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

  • SystemManager ( com.huawei.systemmanager) 会杀死屏幕关闭后仍在运行的所有应用程序,除非它们位于“受保护的应用程序”列表中。
  • PowerGenie ( com.huawei.powergenie) 会杀死任何长时间持有唤醒锁的应用程序。

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

于 2017-11-01T11:08:18.783 回答
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 秒内,您的进程可能会被杀死。

于 2017-02-11T17:35:05.790 回答