8

私はアプリを開発しましたが、画面に次いで 2 番目に消費量の多いプロセスであるバッテリーの消費量が多すぎると不満を言う人もいます。ただし、一部のデバイスでは、それほどバッテリーを消費しません。

私のアプリが行うすべての作業は、サービス内にあります。サービスは粘着性があり、常に実行されています (Android システムは、リソースが少ないときにそれを強制終了したり、デバイスがスリープ状態になったときに一時停止したりする場合があります)、画面がオンになっている限り、加速度計へのリスナーがあり、フォアグラウンド サービスではありません。ウェイクロックを保持しません。

誰かがバッテリーを大量に消費する理由を教えてもらえますか? また、一部のデバイスでのみこの問題が発生するのはなぜですか?

関連するコードは次のとおりです。

public class aListenerService extends Service implements SensorEventListener
{
    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver()
    {
        // if screen was turned on then register to accelerometer
        // if screen was turned off then unregister from accelerometer
    }

    private BroadcastReceiver mPhoneStateReceiver = new BroadcastReceiver()
    {
        // do something...
    }

    @Override
    public void onCreate() 
    {
        super.onCreate();

        // get sensor manager and accelerometer sensor
        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        // register accelerometer sensor and receiver
        mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
        IntentFilter screenFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
        registerReceiver(mScreenReceiver, screenFilter);
        registerReceiver(mPhoneStateReceiver, new IntentFilter(INTENT_ACTION_PHONE_STATE));
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
    {
        super.onStartCommand(intent, flags, startId);

        return Service.START_STICKY;
    }

    @Override
    public void onDestroy() 
    {
        super.onDestroy();

        // unregister to sensor and receivers
        mSensorManager.unregisterListener(this);
        unregisterReceiver(mScreenReceiver);
        unregisterReceiver(mPhoneStateReceiver);
    }

    @Override
    public void onSensorChanged(SensorEvent event)
    {
        // do something...
    }
}
4

1 に答える 1

8

サービスを常に実行すると、CPU とバッテリーに関してコストがかかる可能性があります。これは、サービスの欠点の 1 つです。特に、CPU 負荷の原因となるスレッドを含める場合。アプリの要件に応じて、いくつかのオプションから選択できます。

  1. サービスの結果が、ユーザーがそれを消費できるときにのみ関連する場合は、画面のオンとオフのイベントでサービスを停止および開始するか、少なくとも含まれているスレッド/ハンドラーを開始および停止することを検討できます。これは、次を使用して実行できますBroadcastReceiver

    public class ScreenReceiver extends BroadcastReceiver {
    
      @Override
      public void onReceive(Context context, Intent intent) {
          if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
              // (1) stop service or (2) stop all threads and unregister all event 
              // handlers, if the service has to register the screen receiver
          } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
              // (1) start service or (2) start all threads and register all event
              // handlers as needed
          }
      }
    }
    

    画面イベントはプログラムで登録する必要があることに注意してください。画面のオンとオフのイベントを同じサービス内に登録する必要がある場合は、stickyとして開始します。このようにして、サービス インスタンスが保持されます。(: バッテリーウィジェット、天気情報、...)

  2. イベント ベースの環境の場合は、Google Cloud Messaging (GCM) の使用を検討できます。GCM を使用すると、任意のサーバーから任意の登録済みデバイスにメッセージを送信して、ウェイクアップし、着信情報を処理することができます。常に情報をポーリングする必要はありません。

    このシナリオが要件に適合する場合は、 Google のドキュメントと例を確認してください (: メッセージング アプリ、チャット アプリなど)。

  3. データ/コードを定期的に処理/実行する必要がある場合は、次の使用を検討してくださいAlarmManager

    public void SetAlarm(Context context) {
      AlarmManager manager = (AlarmManager)context.
                              getSystemService(Context.ALARM_SERVICE);
    
      Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
      PendingIntent pendingIntent = 
                    PendingIntent.getBroadcast(context, 0, intent, 0);
    
      am.setRepeating(AlarmManager.RTC_WAKEUP, 
                      System.currentTimeMillis(), 1000 *60 , pendingIntent);
    }
    

    ただし、短い間隔 (30 分未満としましょう) には適していないという欠点があります。(: メールクライアント、...)

したがって、いくつかの代替手段があります。あなたのコードを見ると、センサーで何かをしていることがわかります。画面がオフの場合、センサー情報は必要ですか? または、どのようなイベントがサービスの開始と終了をトリガーする可能性がありますか?

常に結果が必要な場合 (たとえば GPS トラッカーの場合) は、おそらくコードを最適化する以外に選択肢はありません。バッテリーの残量が少ない場合は、サービスを停止するのが理にかなっているかもしれません (詳細については、こちらを参照してください)。

幸運を!

于 2013-08-11T12:27:34.953 に答える