06. バッテリー監視サンプル

バッテリーの状態監視をするためには、「BroadcastReceiver」というクラスを継承

class SampleReceiver extends BroadcastReceiver {

:

}

を定義して、アレコレするのですけど、バッテリー監視に関してはもう少しシンプルにできることがわかりましたので、共有したいと思います。

以下のコードは、TextViewに、1秒毎に電池の残量を確認して表示するプログラムです。

public class MainActivity extends Activity {

private TextView statusView; //①

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

statusView = new TextView(this); //②

setContentView(statusView); //③

}

@Override

protected void onStart(){

super.onStart();

final Handler handler = new Handler(Looper.getMainLooper()); //④

handler.postDelayed(new Runnable(){ //⑤

@Override

public void run() {

IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); //⑥

Intent intent = registerReceiver(null, filter); //⑥

int level = intent.getIntExtra("level", 0); //⑥

int scale = intent.getIntExtra("scale", 0); //⑥

int rate = (int)(100*(float)level/(float)scale); //⑥

statusView.setText(String.format("電池残量:%d%",rate));

handler.postDelayed(this, 1000*1); //⑦

}

}, 1000*1);

}

}

①でインスタンスだけ作成しておいて、onCreate()の②で生成し、③で表示させています。

onStart()でバッテリー監視を行っていますが、onStart()にこのコードを置いているのは気まぐれです。onCreate()の中に書いてもいいですが、ここではActivityのlife-cycleに最適化する話はしないことにします。

さて、「定期的にバッテリーを監視する」ために、ここではHandlerのpostDelayedを用いることにしています。postとは「投入する」という意味で、postDelayedだと「遅らせて投入する」という意味になります。

④でHandlerを生成して、⑤でpostDelayedにより、Runnableオブジェクトを定義して実行しています。

⑥がポイントで、

  • IntentFilter(まあフィルターです)を、ACTION_BATTERY_CHANGED(バッテリーの情報変化)時という条件で生成します。

  • Intentを生成します。このとき、registerReceiverの第一引数が null です。ふつうは「BroadcastReceiver」のオブジェクトが入るのですが、nullにすることで、バッテリーの情報を即座にintentとしてゲットできます。BroadcastReceiverについては、他に詳しいサイトが多数ありますが、このサイトでも後日記載したいと思います。

  • ⑥の下3行は、ゲットしたintentから情報を入手し、バッテリー残量を計算しています。

その次の行で、setTextによりTextViewへ文字を書き込んでいます。

⑦は、自分自身(this)を1秒後に実行する、という意味になります。

とまあ、記述は簡単なのですが、技術的なポイントはいろいろありまして、説明が長くなってしまいました。

『重要』

非同期処理、などで検索すると、似たような記述でThreadを使うケースもあります。しかし、ThreadだとTextViewを用いて「表示を更新」することができません。これはどういうことかといいますと…

  • Handlerは、メインスレッドと同期して処理されるため、TextViewなどの描画更新が可能

  • Threadは、メインスレッドと「別のスレッド」で処理されるため、メインスレッドに置かれたTextViewなどの描画オブジェクトを更新することができない(実施すると例外がおきます)

ということになります。非同期処理は、Androidでいろいろやり出すとぶつかる壁みたいなものですが、徐々に理解できてくると、実行手段を使い分けできるようになってきます。