Оптимизация работы аккумулятора (wakelocks) на Huawei EMUI 4.0

#android #gps #wakelock #huawei-mobile-services

#Android #gps #wakelock #huawei-мобильные сервисы

Вопрос:

Добрый день, ситуация:

Я разрабатываю приложение для Android, которое служит спортивным трекером / навигационным приложением, поэтому для него требуется постоянное подключение к GPS, а также постоянное бодрствующее устройство. Запись выполняется каждую секунду.

Текущее решение, работающее годами, благодаря wakelocks тому, что устройство не спит.

Режим ожидания в Android 6.0 усложняет ситуацию, но это не тот случай.

На устройстве Huawei, вероятно, другой тип оптимизации.

Вот часть журнала:

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 при выключенном экране)?

Как я писал при запуске, на всех других устройствах, кроме нового Huawei, такая система работает корректно уже много лет.

РЕДАКТИРОВАТЬ: примечание после комментария одного пользователя (удалено?), Приложение «белый список» в Huawei Battery Manager (помечено как «защищенное приложение») никак не влияет на эту проблему.

Ответ №1:

Есть два системных приложения Huawei, которые могут отключать пользовательские приложения для экономии заряда батареи:

  • SystemManager ( com.huawei.systemmanager ) уничтожает все приложения, которые все еще работают после выключения экрана, если они не находятся в списке «Защищенные приложения».
  • PowerGenie ( com.huawei.powergenie ) уничтожает все приложения, которые удерживают блокировки в режиме ожидания в течение длительного времени.

Похоже, что ваше приложение убивается PowerGenie. Вы можете избежать этого, воспользовавшись жестко запрограммированным белым списком тегов блокировки пробуждения PowerGenie. Например, если тегом вашей блокировки является «LocationManagerService», он будет проигнорирован PowerGenie, потому что системная служба содержит блокировку пробуждения с тем же тегом, и PowerGenie внесла его в белый список.

Комментарии:

1. Я провел небольшое исследование и попробовал использовать эту логику в своем приложении. Я работал над решением для бесконечного приложения службы определения местоположения. У меня есть все для работы приложения, но единственная проблема, с которой я сталкиваюсь, — это устройства Huawei и Xiaomi (и только версия Android 6.0). Я попробовал это, и бинго. Принудительное закрытие Power Engine и мое приложение работают на устройствах Huawei 6.0. Таким образом, обходной путь заключается в том, чтобы каким-то образом внести ваше приложение в белый список power Engine (не уверен, как в настоящее время, но, по крайней мере, проблема теперь ясна) Большое вам спасибо @akwizgran

2. Это работает! Я указал тег блокировки пробуждения как «LocationManagerService»

3. Могу я спросить, что вы имеете в виду, указывая тег блокировки пробуждения?

4. @OlegA И вы используете PARTIAL_WAKE_LOCK в качестве флага пробуждения?

5. @rosualin Да, я использую PowerManager. PARTIAL_WAKE_LOCK

Ответ №2:

Вы пробовали устанавливать будильник, который регулярно отключает блокировку, а затем повторно запрашивает ее через пару секунд? Если проблема в том, что Android от Huawei не нравится злоупотребление 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 не активен, ваш процесс может быть остановлен.