web-dev-qa-db-ja.com

AndroidとGoogle Play Services Locationでの過度のAlarm Managerウェイクアップ

Androidから過剰なアラームマネージャーのウェイクアップに関するGoogle Playコンソールで重要なパフォーマンスレポートを受け取りました。

https://developer.Android.com/topic/performance/vitals/wakeup.html

Google Play ServicesのLocation APIを使用して、バックグラウンドで位置情報の更新を要求します。レポートでは、過度のウェイクアップウェイクアップは、LocationListenerからのcom.google.Android.location.ALARM_WAKEUP_LOCATORによって引き起こされたことが示されています。

アラームを引き起こすコードスニペットの下:

private synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(context)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    mGoogleApiClient.connect();
}

/**
 * Runs when a GoogleApiClient object successfully connects.
 */
@Override
public void onConnected(Bundle connectionHint) {
    try {
        // Set location request
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5 * 60000);
        mLocationRequest.setFastestInterval(60000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        mLocationRequest.setMaxWaitTime(30 * 60000);

        // Create a pending intent to listening on location service when the update become available
        Intent mIntent = new Intent(context, LocationReceiver.class);
        mIntent.setAction(LocationReceiver.LOCATION_EXTRA);
        mPendingIntent = PendingIntent.getBroadcast(context, 42, mIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        // Permission check before launching location services
        if (ContextCompat.checkSelfPermission(context,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, mPendingIntent);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

このアラームウェイクアップは、Google PlayサービスのLocation APIにリンクされていますか?

誰もこの問題を修正する方法を知っていますか?

26
poiuytrez

Google Location api

これは com.google.Android.location.ALARM_WAKEUP_LOCATOR の問題であり、デバイスを60秒ごとに起動し、最大15秒間起動したままにしておくと、バッテリーの消耗が大きくなります。

fixes 外部経由の電話での使用 apps があり、アプリの許可を実際に取り消す方法をユーザーに教えてきました。

ソリューション

以下は、アプリのバッテリー使用量を削減するツールを提供します。

ソリューションはアプリのユースケースとビジネスロジック、およびロケーションの更新で何を達成したいかの費用便益分析に依存するため、アプリにカスタマイズされたソリューションを提供することは不可能です。

時間間隔

バッテリーのパフォーマンスに問題があるのは当然です。次の設定から:

mLocationRequest.setInterval(5 * 60000);
mLocationRequest.setFastestInterval(60000);
mLocationRequest.setMaxWaitTime(30 * 60000);

間隔は5分ごとに更新するように設定されています(5 * 60000ms)。それは1日24時間です。これが5分ごとに正常に更新される場合:1日あたり12回== 288回。

最速の間隔は1分(60000)に設定されています。場所はデバイス上の他の場所にアクセスするため利用できますが、アプリでは引き続き電力を使用します)。

Maxwaittimeはわずか30分です。つまり、せいぜいデバイスが起動され、1日に最低48回ポーリングされるということです。

これらの時間を増やす

setMaxWaitTime...これにより、デバイスのハードウェア機能に応じて、バッテリーの消費が少なくなり、より正確な位置を特定できます。すぐにロケーションを配信する必要がない場合は、この値をニーズに合わせてできるだけ大きく設定する必要があります。 ...

In Android 8 Googleはリクエスト数を 1時間あたり数 のみに制限しています。リクエストの間隔を設定する際のガイドラインとしてこれを使用することを検討してください。

更新回数の制限

特定の時間枠内の更新の数を制限できます。更新の数が使用されたらロケーション要求をアクティブにキャンセルするか、要求で expiration を設定します。このように、アプリ内の何らかのトリガーでリクエストを作成してアプリを管理し、際限なく継続しないように慎重に管理できます。アプリのユースケースがわからないため、フローを作成することは困難です。

setNumUpdates(int numUpdates)

デフォルトでは、リクエストが明示的に削除されるまでロケーションは継続的に更新されますが、オプションで一定数の更新をリクエストできます。たとえば、アプリケーションが単一の新しい場所のみを必要とする場合、要求を場所クライアントに渡す前に、このメソッドを値1で呼び出します。

場所の更新を停止する

もう1つのオプションは、不要な場合に 位置の更新を停止する を管理することです。リンクは、アクティビティがフォーカスを失ったときにこれを呼び出す例を示しますが、特定の要件が満たされた場合(ビジネスロジック内)またはアプリ内からオン/オフをユーザーに許可することで、アプリ内に実装できます自体。

バッテリーの最適化

アプリが バッテリーの最適化を無視する ではないことを確認してください。

変位

setSmallestDisplacement(float minimumDisplacementMeters) を管理することも、ビジネスロジックに応じてアプリを微調整するのに役立ちます。

以下は更新された質問の前に書かれました。

開発者とユーザーの両方がアプリの更新を設定できる頻度。 間隔 および 優先度

開発者 の場合。

たとえば、ロケーションリクエストを行うときにこれらを設定できます。

protected void createLocationRequest() {
    LocationRequest mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(10000);
    mLocationRequest.setFastestInterval(5000);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}

PRIORITY_NO_POWER の設定もあります。これは、ユーザーが要求したときにのみアプリが更新を取得することを意味します。

ユーザー向け。

ロケーション設定の変更をユーザーに促す が必要です

task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
    @Override
    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
        // All location settings are satisfied. The client can initialize
        // location requests here.
        // ...
    }
});

task.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        int statusCode = ((ApiException) e).getStatusCode();
        switch (statusCode) {
            case CommonStatusCodes.RESOLUTION_REQUIRED:
                // Location settings are not satisfied, but this can be fixed
                // by showing the user a dialog.
                try {
                    // Show the dialog by calling startResolutionForResult(),
                    // and check the result in onActivityResult().
                    ResolvableApiException resolvable = (ResolvableApiException) e;
                    resolvable.startResolutionForResult(MainActivity.this,
                            REQUEST_CHECK_SETTINGS);
                } catch (IntentSender.SendIntentException sendEx) {
                    // Ignore the error.
                }
                break;
            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                // Location settings are not satisfied. However, we have no way
                // to fix the settings so we won't show the dialog.
                break;
        }
    }
});

変更の管理 ユーザー設定でロケーションコールバックを使用します。

...既存の LocationListener の代わりに新しい LocationCallback クラスを使用して、位置の更新に加えて LocationAvailability 更新を受信し、 LocationRequestsの現在のセットに影響を与える設定が変更される可能性がある場合は常に、単純なコールバック。

Google 対処済み Android 8。

消費電力を削減するために、Android 8.0(APIレベル26)は、バックグラウンドアプリがユーザーの現在位置を取得できる頻度を制限します。アプリは、1時間に数回しか位置の更新を受信できません。

注:これらの制限は、アプリのターゲットSDKバージョンに関係なく、Android 8.0(APIレベル26)以上を実行しているデバイスで使用されるすべてのアプリに適用されます。


Alarm Managerを使用している場合。

これは Alarm Manager に関連している可能性があります。

これは単純な修正ではありません。最終的には、更新のスケジュール方法を書き直す必要があります。

  1. 少なくとも問題をスローダウンするには、コードをデバッグし、Alarm Managerがスケジュールを呼び出したり作成したりする間隔を短縮するインスタンスを見つける必要があります。

  2. その後、アプリの位置更新スケジューリング部分全体を書き換える必要があります。

問題の修正

ウェイクアップアラームをスケジュールするアプリ内の場所を特定し、それらのアラームがトリガーされる頻度を減らします。ヒントを次に示します。

  • RTC_WAKEUP またはELAPSED_REALTIME_WAKEUPフラグのいずれかを含む AlarmManager のさまざまな set() メソッドの呼び出しを探します。
  • アラームが設定されたソース内の場所を簡単に識別できるように、アラームのタグ名にパッケージ、クラス、またはメソッド名を含めることをお勧めします。追加のヒントを次に示します。
    • 電子メールアドレスなど、個人識別情報(PII)を名前に含めないでください。それ以外の場合、デバイスはアラーム名の代わりに_UNKNOWNを記録します。
    • クラス名やメソッド名をプログラムで取得しないでください。たとえば、 getName() を呼び出して取得しないでください。Proguardによって難読化される可能性があります。代わりに、ハードコードされた文字列を使用してください。
    • アラームタグにカウンタまたは一意の識別子を追加しないでください。システムは、すべて一意の識別子を持っているため、そのように設定されたアラームを集約することはできません。

問題を修正した後、次の [〜#〜] adb [〜#〜] コマンドを実行して、ウェイクアップアラームが期待どおりに機能していることを確認します。

adb Shell dumpsysアラーム

このコマンドは、デバイスのアラームシステムサービスのステータスに関する情報を提供します。詳細については、 dumpsys を参照してください。

上記のいずれかに特定の問題がある場合は、 mcveで別の質問を投稿する必要があります

アプリを改善するには、ここで ベストプラクティス で説明されているようにコードを書き直す必要があります。 アラームマネージャーを使用してバックグラウンドタスクをスケジュールしないでください。電話がスリープ状態の場合、ロケーションはバックグラウンドタスクと見なされます。さらに、あなたはそれがバックグラウンドタスクだと言います。 JobScheduler または Firebase JobDispatcher を使用します。

アラームマネージャーがより良い選択である場合(、ここにはありません)ここでよく読んでおくことが重要です スケジューリング繰り返しアラームトレードオフを理解する

設計が不十分なアラームは、バッテリーの消耗を引き起こし、サーバーに大きな負荷をかける可能性があります。

30
Yvette Colomb