【问题标题】:Battery optimizations (wakelocks) on Huawei EMUI 4.0+华为 EMUI 4.0+ 上的电池优化(唤醒锁)
【发布时间】:2016-10-10 09:06:22
【问题描述】:

美好的一天, 情况:

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

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

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

【问题讨论】:

    标签: android gps wakelock huawei-mobile-services


    【解决方案1】:

    有两个华为系统应用可能会为了省电而杀死用户应用:

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

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

    【讨论】:

    • 我进行了一些研究,并尝试使用此逻辑在我的应用程序中使用。我一直在为永无止境的位置服务应用程序开发解决方案。我拥有该应用程序可以运行的一切,但我唯一的问题是华为和小米设备(并且只有 6.0 版本的 android 设备)。我试了一下,宾果游戏。强制关闭 Power Engine,我的应用程序可以在 6.0 华为设备上运行。因此,解决方法是以某种方式使您的应用程序将动力引擎列入白名单(不确定目前如何,但至少问题现在很清楚)非常感谢@akwizgran
    • 有效!我已将唤醒锁定标签指定为“LocationManagerService”
    • 请问您指定唤醒锁标签是什么意思?
    • @OlegA 你使用 PARTIAL_WAKE_LOCK 作为唤醒标志?
    • @rosualin 是的,我使用 PowerManager.PARTIAL_WAKE_LOCK
    【解决方案2】:

    您是否尝试过设置一个定期释放 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 秒内,您的进程可能会被杀死。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      相关资源
      最近更新 更多