Храните Wi-Fi в режиме ожидания перед тем, как телефон перейдет спать
Я хочу получать пакеты с Wi-Fi, когда мой телефон заблокирован. Проблема в том, что когда я блокирую свой экран, мой основной сервис перестает принимать пакеты. Я использую Foreground Service следующим образом:
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
var notification = new Notification.Builder(this)
.SetContentTitle(Resources.GetString(Resource.String.app_name))
.SetContentText(Resources.GetString(Resource.String.notification_text))
.SetSmallIcon(Resource.Drawable.ic_stat_name)
.SetContentIntent(BuildIntentToShowMainActivity())
.SetOngoing(true)
.AddAction(BuildRestartTimerAction())
.AddAction(BuildStopServiceAction())
.Build();
// Enlist this instance of the service as a foreground service
StartForeground(Constants.SERVICE_RUNNING_NOTIFICATION_ID, notification);
/*DO THIS EVEN WHEN SCREEN IS LOCKED*/
var powerManager = (PowerManager)GetSystemService(PowerService);
_wakeLock = powerManager.NewWakeLock(WakeLockFlags.Partial, "WakeLockTag");
_wakeLock.Acquire();
var wifiManager = (WifiManager)GetSystemService(WifiService);
_wifiLock = wifiManager.CreateWifiLock(WifiMode.FullHighPerf, "xamarin_wifi_lock");
_wifiLock.Acquire();
if (!powerManager.IsIgnoringBatteryOptimizations("com.xamarin.xample.foregroundservicedemo") ||
!_wakeLock.IsHeld || !_wifiLock.IsHeld)
throw new InvalidOperationException("OPTIMIZATIONS NOT ACTIVE");
string msg = timestamper.GetFormattedTimestamp();
Log.Debug(TAG, msg);
Intent intent = new Intent(Constants.NOTIFICATION_BROADCAST_ACTION);
intent.SetAction(Android.Provider.Settings.ActionIgnoreBatteryOptimizationSettings);
intent.PutExtra(Constants.BROADCAST_MESSAGE_KEY, msg);
LocalBroadcastManager.GetInstance(this).SendBroadcast(intent);
Task.Run(() =>
{
using (var client = new UdpClient(12345))
{
while (true)
{
var result = client.ReceiveAsync().Result;
Console.WriteLine($"RECEIVED: {result.Buffer.Length}");
}
}
});
return StartCommandResult.Sticky;
}
Я делаю следующее, чтобы убедиться, что он не убит:
- Запуск службы на переднем плане
- Использование
StartCommandResult.Sticky
- Использование Wake Lock
- Использование Wifi Lock
- Установка WifiSleepPolicy на
Never
(у меня есть настройка в настройках моего телефона) - Настройка
ActionIgnoreBatteryOptimizationSettings
в намерениях - Переключение моего приложения с помощью командной строки adb во время отладки
Что еще мне не хватает? Я использую Samsung A5 с Android 6.0 - API 23.
Я просмотрел журналы из командной строки adb, и я проверил, что моя служба фактически работает как Foreground Service, и все блокировки хранятся.
Ответы
Ответ 1
То, что вы делаете, просто здорово, все хорошо. Тем не мение!!
Давайте посмотрим на сообщение devleport.android.com:
Политики Google Play запрещают приложениям запрашивать прямое освобождение от функций управления питанием в Android 6. 0+ (Doze и App Standby), если не будет затронута основная функция приложения.
Вы заявили:
Я использую Samsung A5 с Android 6.0 - API 23.
Значит, вы не сможете сохранить свою функцию переднего плана, когда телефон перейдет в спящий режим, потому что основная функция приложения не пострадает.
Это причина, по которой вы заметили, что перестали получать пакеты, когда телефон спит.
пожалуйста, изучите всю ссылку, которую я приложил, а также руководство по управлению Power Manager.
Теперь я заметил, что кроме того:
Если пользователь покидает устройство, отключенное и неподвижное в течение определенного периода времени, при выключенном экране устройство переходит в режим Doze. В режиме "Дозирование" система пытается сохранить батарею , ограничив доступ приложений к сети и интенсивным нагрузкам. Он также запрещает приложениям получать доступ к сети и откладывает их работу, синхронизацию и стандартные аварийные сигналы.
Ограничения на дозу:
- Доступ к сети приостановлен.
- Система игнорирует блокировки слежения.
- Стандартные тревоги AlarmManager (включая setExact() и setWindow()) откладываются до следующего окна обслуживания.
- Если вам нужно установить аварийные сигналы, которые срабатывают во время Doze, используйте setAndAllowWhileIdle() или setExactAndAllowWhileIdle().
- Аварийные сигналы, установленные с помощью setAlarmClock(), продолжают нормально срабатывать - система выходит из Doze незадолго до того, как эти аварийные сигналы срабатывают.
- Система не выполняет сканирование Wi-Fi.
- Система не позволяет запускать адаптеры синхронизации.
- Система не позволяет запустить JobScheduler.
Это завершит мой ответ на все ваши запросы.
EDIT 2:
Я исследовал немного дальше, есть целый пост по этой проблеме в Xamarin.Android.
есть также решение разбудить телефон каждые 10 минут, чтобы обойти его здесь.