2015年6月10日水曜日

[メモガキ開発日記] 毎朝、今日のメモを表示する機能を作る

メモガキの新機能として、毎朝、今日のメモを確認できる機能を作ります。

使い道

通知機能(リマインダー)を使うことでもメモを見返せますが、朝に今日のメモをまとめて確認できるようにする。これだけでは、普通にメモガキを起動すれば確認できます。
そこで、メモガキを起動することを忘れたとしても、朝起きてスマホの画面をオンにするだけで、今日のメモが表示されるようにする。



作る

メモガキがスマホの画面がオンされたことを常時検知できる必要があるので、サービスを作成し、常時サービス内で画面オンイベントを受け取れるようにする。サービスが画面オンイベントを受け取ったら、今日のメモを表示するアクティビティを起動します。

全体像として、アクティビティ(Activity)、サービス(Service)、アンドロイド(Android)間の制御は次のように作成します。



①サービス起動、②サービス停止

サービスの起動・停止は、ContextのstartService、stopServiceメソッドを使います。
Context context = getActivity().getApplicationContext();
Intent serviceIntent = new Intent(context, RpService.class);// サービスのクラスを指定

// サービス起動
context.startService(serviceIntent);

// サービス停止
context.stopService(serviceIntent);


③画面オンの受け取り

画面オンイベントは、BroadcastReceiverを使うことでAndroidからイベントを受け取ることができます。
BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action != null) {
            if (action.equals(Intent.ACTION_SCREEN_ON)) {
                // 画面ON時の処理

            }
        }
    }
};

サービス起動時、停止時にBroadcastReceiverの登録と解除が必要になります。
public class RpService extends Service {
...
    @Override
    public void onCreate() {
        super.onCreate();

        // ブロードキャストリスナーの登録
        // IntentFilterとして、画面オンを示すIntent.ACTION_SCREEN_ONを指定します
        registerReceiver(mBroadcastReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
    }
    @Override
    public void onDestroy() {
        super.onDestroy();

        // ブロードキャストリスナーの登録解除
        unregisterReceiver(mBroadcastReceiver);
    }
....
}


④アクティビティの起動

これはstartActivityを使って起動できるので省略します。


⑤設定再読込要求

設定画面等でサービスに関連する設定を変更した場合に、サービスに設定を再読込するよう要求する必要があります。今回だと、朝に今日のメモは表示しますが、朝のいつに表示するのか時刻を設定できる必要があります。その時刻を変更した際に、サービスも変更した設定情報を読込する必要があります。

これを実現するのに、LocalBroadcastManagerを使うと簡単に実現できます。
BroadcastManagerと同様な機能ですが、ブロードキャスト範囲がアプリ内に限定できます。
アクティビティ側からカスタムIntentを送信して、サービス側で受け取ります。

ブロードキャストを送信する場合は、LocalBroadcastManagerのインスタンスを取得して、sendBroadcastでIntentを送るだけ。
Context context = getApplicationContext();
LocalBroadcastManager.getInstance(context)
    .sendBroadcast(new Intent(RpNoteIntent.ACTION_UPDATE_SERVICE));


サービス側での受け取りは、BroadcastReceiverと同様にリスナーを作成します。
BroadcastReceiver mLocalBroadcastManager = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action != null) {
            if (action.equals(RpNoteIntent.ACTION_UPDATE_SERVICE)) {
                // 設定の再読込処理

            }
        }
    }
};

リスナーの登録・解除は、LocalBroadcastManagerのインスタンスに対して行います。
public class RpService extends Service {
...
    @Override
    public void onCreate() {
        super.onCreate();

        // ローカルブロードキャストリスナーの登録
        LocalBroadcastManager.getInstance(getApplicationContext())
            .registerReceiver(mLocalBroadcastReceiver, new IntentFilter(RpNoteIntent.ACTION_UPDATE_SERVICE));
    }
    @Override
    public void onDestroy() {
        super.onDestroy();

        // ローカルブロードキャストリスナーの登録解除
        LocalBroadcastManager.getInstance(getApplicationContext())
            .unregisterReceiver(mLocalBroadcastReceiver);
    }
....
}


この機能は、メモガキ Ver.0.14.8から実装されます。
ダウンロード (Google Play)