web-dev-qa-db-ja.com

電話がスリープ状態になった後、フォアグラウンドサービスでwifiをアクティブに保ちます

電話がロックされているときにwifiからパケットを受信したい。問題は、画面をロックすると、フォアグラウンドサービスがパケットの受信を停止することです。私はこのようなフォアグラウンドサービスを使用しています:

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

私はそれが殺されていないであることを確認するために次のことをしています:

  1. フォアグラウンドサービスの開始
  2. StartCommandResult.Stickyの使用
  3. ウェイクロックの使用
  4. Wifiロックの使用
  5. WifiSleepPolicyをNeverに設定します(電話の設定で設定します)
  6. インテントでActionIgnoreBatteryOptimizationSettingsを設定する
  7. デバッグ中にadbコマンドプロンプトを使用してアプリをホワイトリストに登録する

他に何が欠けていますか? Android 6.0-API23でSamsungA5を使用しています。

Adbコマンドプロンプトからログを調べ、サービスが実際にフォアグラウンドサービスとして実行されており、すべてのロックが保持されていることを確認しました。

22
FCin

あなたがしていることはただ素晴らしいです、すべてが良いです。 しかし!!

devleport.Android.com の投稿を見てみましょう:

Google Playポリシーでは、アプリのコア機能に悪影響が及ばない限り、アプリがAndroid 6.0+(Dozeおよびアプリスタンバイ))の電源管理機能の直接免除をリクエストすることを禁止しています。

あなたは言った:

Android 6.0-API23でSamsungA5を使用しています。

つまり、アプリのコア機能はnot /であるため、電話がスリープ状態になったときにフォアグラウンドサービスを維持することはできません。悪影響を受ける

これが、電話がスリープ状態のときにパケットの受信を停止したことに気付く理由です。

添付したリンク全体と、 電源マネージャー ガイドをご覧ください。

編集:さらに気づいた:

画面をオフにして、ユーザーがデバイスのプラグを抜いて一定時間静止したままにすると、デバイスはDozeモードになります。 Dozeモードでは、システムはバッテリーの節約を試みますネットワークおよびCPUを集中的に使用するサービスへのアプリのアクセスを制限します。また、アプリがネットワークにアクセスするのを防ぎ、ジョブ、同期、および標準アラームを延期します。

居眠り制限

  • ネットワークアクセスが一時停止されています。
  • システムはウェイクロックを無視します。
  • 標準のAlarmManagerアラーム(setExact()およびsetWindow()を含む)は、次のメンテナンスウィンドウに延期されます。
  • Doze中に発生するアラームを設定する必要がある場合は、setAndAllowWhileIdle()またはsetExactAndAllowWhileIdle()を使用してください。
  • SetAlarmClock()で設定されたアラームは引き続き正常に発生します—システムはそれらのアラームが発生する直前にDozeを終了します。
  • システムはWi-Fiスキャンを実行しません。
  • システムは同期アダプターの実行を許可しません。
  • システムはJobSchedulerの実行を許可しません。

これで、すべての質問に対する私の答えは終わりです。

編集2:

もう少し調査しましたが、この問題に関する投稿全体が Xamarin.Android にあります。

それをバイパスするために10分ごとに電話を起こす解決策もあります ここ

5
Barr J