2012年10月15日月曜日

Androidで設定を参照, 操作するあれこれ -バッテリーwithService編-

以前のバッテリー情報取得のその後.
Activityの内部クラスにしとけばいいや, 参照しやすいし.
などと考えていたら

Serviceに乗せなさい



orz

通達が来ましたとさ.


Serviceを用いてBattery情報を得る

当初は
「ServiceからActivityを書き換えるってどうやるんだ…?Binder?ServiceConnection?Messengerを使えば値を渡せるのか!」
などと迷走を続けていたところ

sendBroadcastでえぇやん(意訳
でないと汎用性下がるし

と2度目のorz
ほぼ一日かけてたどり着いたMessengerは無に返り, 晴れてsendBroadcastによる実装が残りましたとさorz

という愚痴を書きたかっただけ.

1. Service側

まずはService側. いたって単純で, Intent.ACTION_BATTERY_CHANGEDを受け取ったらオリジナルのIntentに必要な情報を載せて発信するだけのもの.


public class BatteryService extends Service {


    public static final String ORIGN_ACTION = "orignbatteryaction";

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
                int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
                // オリジナルのActionでintentを作成
                Intent sendIntent = new Intent(BatteryService.ORIGN_ACTION);
                // levelを載せる
                sendIntent.putExtra("level", level);
                sendBroadcast(sendIntent);
            }        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(mReceiver, filter);
    }

    @Override
    public void onStart(final Intent intent, final int startId) {
        super.onStart(intent, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
        Log.i("hogeBatteryService", "unregisterReceiver");
    }

    @Override
    public IBinder onBind(final Intent arg0) {
        return null;
    }
}

たまにはまるっと載せてみる.mReceiverの中, コメントにある通りACTIONの部分を自作してやるだけ. 名前はユニークになるように. 万一被ると大変なことになる…かも?('A`)
後はintentを送る際,

startActivity(sendIntent)

ではなく
sendBroadcast(sendIntent)

を用いれば, 行き先を指定しないIntentの出来上がり.

2. Activity側


こちらもほぼ同様.


public class ResidureBatteryCheckerActivity extends Activity {

    private static TextView textView;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_residure_battery_checker);
        textView = ((TextView) findViewById(R.id.hoge_battery_check));
    }

    @Override
    public void onResume() {
        super.onResume();
        // バッテリー情報更新のサービスを開始する
        Intent batteryIntent = new Intent(this, BatteryService.class);
        if (startService(batteryIntent) == null) {
            Log.e("hogeMakeFirstSetting", "cannot Start Service");
        } else {
            Log.i("hogeMakeFirstSetting", "Service is Start!");

            // ServiceからのBroadcastを受け取るReceiverを立てる
            IntentFilter filter = new IntentFilter();
            filter.addAction(BatteryService.ORIGN_ACTION);
            registerReceiver(orignReceiver, filter);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(orignReceiver);
        stopService(new Intent(this, BatteryService.class));
    }

    public static void changeText(final String message) {
        if (textView != null) {
            textView.setText(message);
        }
    }

    // オリジナルのIntentを受け取るReceiver
    private final BroadcastReceiver orignReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            if (intent.getAction().equals(BatteryService.ORIGN_ACTION)) {
                int level = intent.getIntExtra("level", 0);
                String message = "level is " + level;
                changeText(message);
            }
        }
    };
}

なんてことは無く, ただReceiverを立て, ただオリジナルIntentを拾い, 情報を取り出して好きに使うだけ.
なおReceiverはonDestroyなどできちんとunregisterReceiverしましょう. でないとちゃんと休ませろって警告が来ます. 主にLogに.Serviceはお好みで. ただ止める手段がないと走り続けてバッテリーがマッハ.ヽ(;´Д`)ノ








…Messengerを使ったものはこの倍はコードがあったわけで, 結果としては良かった…のかな.
Handlerとか良くわかんなかったしorz

0 件のコメント:

コメントを投稿

AWS CDKで立てたEC2インスタンスのTimeZoneとかいじりたかった話

EC2を立てることはできたけど、立てたインスタンスは UTCのままだし設定ファイルとかいちいちscpしてくるのはダルい。 当初UserDataでなんとかしようとしたものの、「書く量がヤバいしメンテしにくい」と悩んでいたところ見かけたのが  AWS::CloudFormation:...