2019年3月14日木曜日

リーダの制御をうまいことする

今回の内容は RFID とはあんまり関係ないんですが、Android から RFID のリーダを制御するときのあるある的なネタです。

リーダを制御する場合、Bluetooth でつないだり 直接接続(シリアル的な)でつないだりとリーダごとに違うんですが、問題は通信先のリーダは1つということで、スマホにおいてはカメラやマイクなどハードを使うときと同じように1つのアプリで専有しちゃうとまずいということなんですね。

つまりアプリの起動時にリーダに接続(専有)して、終了時に切断(開放)する必要があるということです。さらにサスペンドしてるときとかアプリが裏に回ったときなんかも細かく切断する必要があります。

じゃぁ、Android の Activity のライフサイクルにおいて onResumeで接続して、onPauseで切断すればいいじゃん的な流れに当然なりますよね。しかし複数の画面があるアプリで画面を切り替えると onPause とか呼ばれちゃうので画面を切り替えるたびに切断、接続を繰り返すのでちょっとそれはなーってなります。

ようするに自分のアプリが画面に出ているときは接続してて、画面からいなくなったら(それが終了であれ裏に回ったであれサスペンドであれ)切断するというのをやりたいのですが簡単そうでなかなかできません。

そこでこちらの記事を参考にしてみました。
https://qiita.com/wasnot/items/e7e4699de4b21f150c63

Applicationを継承して、Activity のライフサイクルじゃなくて Application のライフサイクルを利用しようというわけです。

public class MyApplication extends Application {

    private static MyReaderController mController;

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new MyLifecycleHandler());

        mController = ....
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
    }

    private class MyLifecycleHandlerimplements ActivityLifecycleCallbacks {
        private int activities = 0;

        @Override
        public void onActivityCreated(Activity activity, Bundle bundle) { }

        @Override
        public void onActivityStarted(Activity activity) {
            activities++;
            if (activities == 1) {
                mController.start();
            }
        }

        @Override
        public void onActivityResumed(Activity activity) { }

        @Override
        public void onActivityPaused(Activity activity) { }

        @Override
        public void onActivityStopped(Activity activity) {
            activities--;
            if (activities <= 0) {
                mController.stop();
            }
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { }

        @Override
        public void onActivityDestroyed(Activity activity) { }
    }
}


やり方は簡単で、Application を継承したクラスを作って、AndroidManifest.xml の application の name属性 に作成したクラス名を指定するだけです。

この onActivityStartyed と onActivityStopped がそれぞれアプリ内で Activity がスタートしたときとストップしたときに呼ばれますので、呼ばれた数をカウントして1個目だったら画面に表示されはじめた、0個になったら画面から居なくなったと判断できるわけですね。

これが正解なのかよくわかりませんが、実装は楽でした。

0 件のコメント:

コメントを投稿