RemoteViewsでNotificationを作成
以下にRemoteViewsを使用してNotificationを作成している個所を抜粋します。
RemoteViews views = new RemoteViews(getPackageName(), R.layout.remote_views); notification = builder.setContent(views) .setSmallIcon(R.drawable.earth) .setContentIntent(pendingIntent) .setWhen(System.currentTimeMillis()) .getNotification();
RemoteViewsのインスタンスはコンストラクタにパッケージ名とレイアウトを指定して生成します。このレイアウトは、ADTのレイアウトエディタを使用してレイアウトできるので、App Widgetsよりは快適に作業が行えます。
Notificationは、ここでは「Notification.Builder」クラスを使用して作成しています。ちなみに、Notificationは、コンストラクタとsetLatestEventInfo()メソッド、Notification.Builderクラスを使用してインスタンスを生成・設定する他に、フィールドにオブジェクトを直接設定するバリエーションもあります。
今回のサンプルアプリではすべての方法でNotificationを生成・設定しているので、ソースコードを参照してみてください。
Notificationの8つのフラグ
動画を見て気が付いたかもしれませんが、このNotificationはクリックしても自動的に消えませんでした。これは、Notificationに以下のフラグを設定していないためです。
// このフラグ設定がない notification.flags = Notification.FLAG_AUTO_CANCEL;
このフィールドは、複数のフラグをXORで設定可能です。
フラグ | 説明 |
---|---|
FLAG_AUTO_CANCEL | Notificationがクリックされた際に、通知をキャンセル |
FLAG_FOREGROUND_SERVICE | 現在実行中のサービスを表す |
FLAG_HIGH_PRIORITY | ステータスバーが非表示でもNotificationを表示することがある |
FLAG_INSISTENT | Notificationが開かれたりキャンセルされたりするまで、音声によって繰り返し通知 |
FLAG_NO_CLEAR | ユーザーがNotificationをクリアしてもクリアされないようにする |
FLAG_ONGOING_EVENT | 現在進行中のイベントを表す |
FLAG_ONLY_ALERT_ONCE | Notificationの通知のたびにサウンドまたはバイブレーションを作動させたい場合に設定 |
FLAG_SHOW_LIGHTS | LEDを点灯させたい場合に設定 |
通常はFLAG_AUTO_CANCELだけが設定されていればいいと思いますが、必要に応じて他のフラグも効果的に使用してみてください。
オーディオリモコン用のNotificationの実装
今回と次回の目標は、Notificationを使用してオーディオリモコンを実装することでした。
オーディオリモコンのデザイン
デザインは下記のように「前の曲」「再生/一時停止」「次の曲」「停止」の操作を提供し、現在再生中の曲情報を表示する感じにします。
トラック再生時間はChronometerで自動的に更新しますが、その他の曲情報は、ボタンのイベントに応じて表示し直さなければなりません。また、「再生/一時停止」は押された際にイメージの表示を切り替えなければなりません。
「PendingIntent」とは
RemoteViews上のボタンは、押された際にイベントを直接取得できず、代わりに「android.app.PendingIntent」というIntentを使用します。
PendingIntentを使うには、「どのコンテキストで動作させるのか」というのを考えてアプリ全体を設計する必要があります。PendingIntent.getActivity()メソッド、PendingIntent.getService()メソッド、PendingIntent.getBroadcast()メソッドでPendingIntentを生成しますが、それぞれandroid.app.Activity、android.app.Service、android.content.BroadcastReceiverがPendingIntentを実行するコンテキストです。
今回のデモは、簡単のためにBroadcastReceiverを使用していますが、おそらく本当にオーディオリモコンを実装するのであれば、Serviceにする方が簡単になるはずです。
BroadcastReceiverでNotificationを操作
以下にBroadcastReceiverでNotificationを操作している個所をソースコードを抜粋して説明します。
@Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // 【1】 Notification notification = intent.getParcelableExtra("notification"); // 【2】 boolean isPlaying = intent.getBooleanExtra("isPlaying", false); long baseTime = intent.getLongExtra("baseTime", 0); // 【3】 NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); if (ACTION_INIT.equals(action)) { intent.setAction(ACTION_PLAY_PAUSE); } else if (ACTION_PLAY_PAUSE.equals(intent.getAction())) { if (isPlaying) { long current = System.currentTimeMillis() - baseTime; // 【4】 notification.contentView.setImageViewResource( R.id.playpause, R.drawable.media_play_s); notification.contentView.setChronometer( R.id.chronometer, SystemClock.elapsedRealtime() - current, null, false); intent.putExtra("current", current); } else { long current = intent.getLongExtra("current", 0); notification.contentView.setImageViewResource( R.id.playpause, R.drawable.media_pause_s); notification.contentView.setChronometer( R.id.chronometer, SystemClock.elapsedRealtime() - current, null, true); intent.putExtra("baseTime", System.currentTimeMillis() - current); } intent.putExtra("isPlaying", !isPlaying); intent.putExtra("notification", notification); } // 【5】 PendingIntent pendingIntent = PendingIntent.getBroadcast( context, R.id.playpause, intent, PendingIntent.FLAG_UPDATE_CURRENT); // 【6】 notification.contentView.setOnClickPendingIntent(R.id.playpause, pendingIntent); // 【7】 manager.notify(R.id.button3, notification); }
【1】では、IntentからNotificationを取り出します。これができるため、Notificationのカスタマイズした動作が手軽に行えます。
【2】では、現在再生中かどうかをIntentから取得します。BroadcastReceiverではなくServiceであれば、状態を保持できるため、このような受け渡しは不要です。
【3】では、android.app.NotificationManagerを取得します。BroadcastReceiverは状態が保持できないため、毎回取得する必要があります。
【4】では、RemoteViewsに値を設定します。RemoteViewsには、サポートするウィジェットに対する汎用的な設定メソッドが多数用意されている一方、ウィジェットに設定されている値を取得するメソッドは提供されていないため、現在の値が何であるか、というのはRemoteViewsを管理する側で把握しておかなければなりません。
【5】では、PendingIntentをBoradcastReceiverのコンテキストで生成します。第4引数のフラグは、以下のような意味を持ちます。
フラグ | 説明 |
---|---|
FLAG_CANCEL_CURRENT | すでにPendingIntentが存在する場合、古い方をキャンセル |
FLAG_NO_CREATE | PendingIntentがまだ存在する場合、生成せずにnullを返す |
FLAG_ONE_SHOT | 1度だけ使用可能なPendingIntentを生成 |
FLAG_UPDATE_CURRENT | Intent内のエクストラデータだけを差し替えたPendingIntentを返す |
例えば、Intentのアクションが変わる場合は、FLAG_UPDATE_CURRENTは使用できませんが、今回のようにエクストラデータのみ変わる場合は、FLAG_CANCEL_CURRENTよりもFLAG_UPDATE_CURRENTを使用する方がいいようです。
第2引数にはウィジェット単位でユニークな値を指定するようにします。PendingIntentを設定する先のViewのIDを指定すると簡単です。この第2引数はApp widgetsを含めRemoteViewsにPendingIntentを設定する際の落とし穴なので注意してください。
【6】では、ボタンにPendingIntentを設定しています。このようにすることで、ボタンがクリックされた際に、PendingIntent内のIntentがブロードキャストされる形になります。
【7】では、Notifiationを通知します。第一引数のIDはアプリ内でユニークな値を指定し、同一のIDでNotifiationを通知することにより、既存のNotificationを更新できます。
RemoteViewsを使ったカスタムレイアウトの5カ条
Notificationは、実はAndroid 1.0からある基本的な機能で、Androidユーザーならなじみのあると思いますが、RemoteViewsを使うことで、さらに便利な機能をユーザーに提供可能になります。
RemoteViewsを使用してカスタムレイアウトを作成する際には、以下のガイドラインも参考にしてみてください。
書かれている内容をいくつかピックアップします。
- 乱用してはいけない
- コンテンツの場所は適切に
- 同種の複数の通知はまとめる
- Androidが提供する通知アイコンとは異なるアイコンデザインにする
- トーストで済むならトーストで
次回は、今回作成したNotificationを使用したリモートコントロールを紹介します。
- グーグルのAPIを使うときに欠かせないGoogle OAuthの作り方と使い方
- 細か過ぎて伝わってないけど開発者が知っておきたいAndroid Mの新機能まとめ
- 腕時計から電話をかけるAndroid Wearアプリの作り方
- Android Wear用アプリの花形、時計アプリ「Watch Face」の基本的な作り方
- Android 5.0発表&スマホと連動する音声認識Android Wearアプリの作り方
- ウェアラブル端末用Android Wearアプリ開発の基礎知識
- 変わらないと生き残れないAndroid Lの新機能まとめ
- Android WearやIoTで注目のAndroidセンサー機能8選
- ウェアラブル時代に見直したいAndroidの加速度/重力センサー、ジャイロスコープ
- あなたの知らないAndroid SDKの便利tools、14選まとめ
- Android 4.4のメモリ使用状況を把握する3つのツールの使い方
- Androidでリアルタイムマルチプレーゲームを開発するには
- 低性能端末でも使えるか? Android 4.4 KitKatの新機能39選
- もはや無料BaaS。ゲーム以外でも使いたくなるGoogle Play Game Servicesのデータ管理機能
- アプリにGoogle+のソーシャルグラフを持ち込めるGoogle Play Game Servicesの基礎知識
- あなたのアプリはクラウドにデータをバックアップできますか?
- Eclipse ADTに代わるIDEとなるか? Android Studioの基礎知識
- ActionBarで、アプリのUIはこんなにスマートになる
- Android 4.x時代のアプリにないと残念なActionBarとは
- 動的クラスローディングでAndroidアプリ“裏”開発
- Android 4.xのAndroidビームをアプリに組み込むには
- AndroidアプリでNFCタグを読み書きするための基礎知識
- 新タブレット時代を見据えるAndroid 4.2の新機能9選
- Androidからイヤフォンやヘルス機器とBluetooth通信するには
- Bluetoothを使ってAndroidアプリ同士で通信するには
- Androidアプリをアプリ内購読に対応してもうける方法
- 開発者が知らないと残念過ぎるAndroid 4.1の新機能36選
- Androidのプロセス間通信を自由自在にするAIDL
- Android 4.0のサービス/プロセス間通信の基本
- Androidアプリでマルチメディアを扱うための基礎知識
- Androidのウィジェットにノーティフィケーションするには
- Android 4.0で注目の顔認識をアプリに組み込むには
- Android 4.0でアプリ開発を始めるための環境構築
- 開発者が知らないと損するAndroid 4.0の新機能44選
- Android Compatibility packageで2.x系でもマルチサイズ対応
- Androidの画面の大きさの違いを解決するFragments
- Android 3.0の新APIで簡単ドラッグ&ドロップ実装
- 開発者が知って得するAndroid 2.3の新機能18選
- アニメーションでAndroidに独創的な画面エフェクトを
- Androidアプリで“アニメーション”するための基礎知識
- XMLレイアウトでAndroidアプリに“設定画面”を追加
- 開発者が知っておきたいAndroid 2.2の新機能12連発
- もはやケータイに必須のカメラをAndroidで制御しよう
- 地図/位置情報/GPSを使うAndroidアプリを作るには
- Android NDKでJNIを使用してアプリを高速化するには
- Android 2.1の新機能「Live Wallpaper」で作る、美しく燃える“待ち受け”
- iPhoneより多彩なAndroidのセンサをアプリで操作
- SurfaceViewならAndroidで高速描画ゲームが作れる
- Android 1.6のジェスチャーとテキスト読み上げを使う
- Androidのホーム画面に常駐するアプリを作るには
- Netbookにも広まるAndroidで、かつてないWeb体験を
- アプリを国際化してAndroid Marketから世界へ発信
- 常駐アプリが作成できるAndroidの“サービス”とは
- AndroidでSQLiteのDB操作をするための基礎知識
- Androidアプリの使いやすさを左右する5つのレイアウト
- 簡単でワクワクするAndroidウィジェット10連発!
- ブラウザや地図、ストリートビューの基、Intentとは?
- Androidアプリ作成の基本“Activity”とは何か?
- Android Market配布を目指しEclipseでHelloWorld!
Copyright © ITmedia, Inc. All Rights Reserved.