ちょっと話題の記事

Android Tips #23 Android4.1 で追加された Notification のスタイルを使いこなす

2012.10.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Android4.1で追加された Notification のスタイル

Android4.1 (JellyBean) で Notification のUIが大きく変更されました。Notification のスタイルに追加があり、いろいろな表現が可能になりました。 追加されたスタイルは以下の3つです。

  • BigTextStyle
  • BigInboxStyle
  • BigPictureStyle

今回は、Notification の復習もしつつ、新しく追加されたスタイルの使いかたを学んでいこうと思います!

いまさら聞けない Notification の使いかた

この機会に改めて Notification の表示のしかたについて復習しようと思います。 まだ Notification を使ったことがないかた、この機会に覚えておきましょう! もう Notification 知ってるぜ、というかたも以前の実装方法が非推奨になっているのでぜひご一読を。

SupportPackage の NotificationCompat を使おう

以前の Notification の実装方法は Notification#setLatestEventInfo() で作っていましたが、この実装方法は非推奨になっています。 現在は Notification.Builder を使って実装する方法が推奨されています。 Notification.Builder は Android3.0 (APIレベル11) から存在するAPIですが、SupportPackage に NotificationCompat.Builder というクラスが存在するので、 Android1.6 (APIレベル4) から対応したい場合はこちらを使用します。
以下は NotificationCompat.Builder を使った Notification の実装のサンプルです。

private void sendNotification() {
	// Intent の作成
	Intent intent = new Intent(MainActivity.this, MainActivity.class);
	PendingIntent contentIntent = PendingIntent.getActivity(
			MainActivity.this, REQUEST_CODE_MAIN_ACTIVITY, intent, PendingIntent.FLAG_UPDATE_CURRENT);
	
	// LargeIcon の Bitmap を生成
	Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_large);
	
	// NotificationBuilderを作成
	NotificationCompat.Builder builder = new NotificationCompat.Builder(
			getApplicationContext());
	builder.setContentIntent(contentIntent);
	// ステータスバーに表示されるテキスト
	builder.setTicker("Ticker");
	// アイコン
	builder.setSmallIcon(R.drawable.ic_small);
	// Notificationを開いたときに表示されるタイトル
	builder.setContentTitle("ContentTitle");
	// Notificationを開いたときに表示されるサブタイトル
	builder.setContentText("ContentText");
	// Notificationを開いたときに表示されるアイコン
	builder.setLargeIcon(largeIcon);
	// 通知するタイミング
	builder.setWhen(System.currentTimeMillis());
	// 通知時の音・バイブ・ライト
	builder.setDefaults(Notification.DEFAULT_SOUND
			| Notification.DEFAULT_VIBRATE
			| Notification.DEFAULT_LIGHTS);
	// タップするとキャンセル(消える)
	builder.setAutoCancel(true);
	
	// NotificationManagerを取得
	NotificationManager manager = (NotificationManager) getSystemService(Service.NOTIFICATION_SERVICE);
	// Notificationを作成して通知
	manager.notify(NOTIFICATION_CLICK, builder.build());
}

アイコンの設定が setSmallIcon() と setLargeIcon() の2つがありますが、 smallIcon はステータスバー表示とサマリとして表示されるところに使われるアイコン、 largeIcon は Notification を開いたときに大きく表示されるところに使われるアイコンです。Android 3.0 (APIレベル11) 以前では smallIcon しか使われません。 そのため、largeIcon の Bitmap を生成しているところは無駄になってしまうので Build.VERSION_CODES を使って条件分岐し、Android3.0 以降のみ作るように実装したほうが良いでしょう。
なお、バイブレーションを使用するには AndroidManifest.xml に uses-permission を追加する必要があるのでご注意ください。

<uses-permission android:name="android.permission.VIBRATE"/>

実行結果

アイコンをバージョン毎に分けよう

上記コードは Android1.6 (APIレベル4) から動作しますが、Notification に使ったアイコンのアセットファイルは Android3.0 (APIレベル11) 以降に最適化されています。 ICSでは Notification に使用されるアイコンサイズは 24dp (描画領域は 22dp 以内に収める必要あり) で作ることが推奨されています。これは Android3.0 以前の OS とは仕様が大きく異なっているため、例えば Android2.3 で動作させると下図のようになってしまいます。

少し大きくなってしまって汚いです。 Android2.3 の Notification のアイコンサイズの指定は上下に多めにとらなければいけないという決まりがあります。具体的な作成方法は公式リファレンスに載っているので、そちらを参考にしてください(Android2.2 以前ではさらに指定が異なります…)。ちなみに hdpi 用は 24 x 38 px (描画領域は24 x 24 px に収める必要あり) が推奨サイズです。うまく作成できると下図のようになります。

また、リソース名を同じにする場合は下記にように drawable フォルダを APIレベル毎に分けます。

Android3.0 (APIレベル11) 以上で使用される drawable フォルダ
res/drawable-ldpi-v11
res/drawable-mdpi-v11
res/drawable-hdpi-v11
res/drawable-xhdpi-v11

Android2.3 (APIレベル9) 以上で使用される drawable フォルダ
res/drawable-ldpi-v9
res/drawable-mdpi-v9
res/drawable-hdpi-v9
res/drawable-xhdpi-v9

Notificationのスタイルを変更する

ということで、新しく追加されたスタイルを試してみたいと思います。
Notification にスタイルを適用するには、スタイルを new するだけです。引数には NotificationCompat.Builder のインスタンスを渡します。あとはスタイルの build() で Notification が作れるので、そのインスタンスを notify() で通知に使います。スタイルは NotificationCompat に含まれているので、動作はしませんが 4.1 以前でも NoSuchMethodError は出ません。

BigTextStyle

BitTextStyle は SummaryText と アイコンを表示できるスタイルです。

private void sendNotification() {
	Intent intent = new Intent(MainActivity.this, MainActivity.class);
	PendingIntent contentIntent = PendingIntent.getActivity(
			MainActivity.this, REQUEST_CODE_MAIN_ACTIVITY, intent, PendingIntent.FLAG_UPDATE_CURRENT);
	
	Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_large);
	
	NotificationCompat.Builder builder = new NotificationCompat.Builder(
			getApplicationContext());
	builder.setContentIntent(contentIntent);
	builder.setTicker("Ticker");
	builder.setContentTitle("ContentTitle");
	builder.setContentText("ContentText");
	builder.setSmallIcon(R.drawable.ic_small);
	builder.setLargeIcon(largeIcon);
	builder.setWhen(System.currentTimeMillis());
	builder.setDefaults(Notification.DEFAULT_SOUND
			| Notification.DEFAULT_VIBRATE
			| Notification.DEFAULT_LIGHTS);
	builder.setAutoCancel(true);
	
	// BigTextStyle を適用
	NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(builder);
	bigTextStyle.bigText("BigText");
	bigTextStyle.setBigContentTitle("BigContentTitle");
	bigTextStyle.setSummaryText("SummaryText");
	
	// NotificationManagerを取得
	NotificationManager manager = (NotificationManager) getSystemService(Service.NOTIFICATION_SERVICE);
	// Notificationを作成して通知
	manager.notify(NOTIFICATION_CLICK, bigTextStyle.build());
}

BigTextStyle は通常のスタイルと非常によく似ています。異なるところは SummaryText を表示できるという点です。同じアプリから通知される Notification は複数送られてくる場合、ひとつの項目としてまとめることができます。BigTextStyle で指定している bigText と bigContentTitle は最後に通知されたものが表示されますが、SummaryText はその Notification の要約として使用するテキストです。メール通知を例にすると、メールの送信者に bigContentTitle、メールのタイトルに bigText、「○件のメールが来てます」的なメッセージに SummaryText をそれぞれ使用すると情報が整理できます。


また setContentTitle でセットした内容は BigContentTitle に上書きされてしまうので Android3.0 以上だと setContentTitle のテキストは表示されません。 しかし Android3.0 未満では setContentTitle しか見ていないので、 setContentTitle にテキストをセットしないと何も表示されません。 上書きされるならいらないじゃん、ということではなく、セットしておく必要があるので注意してください。

BigPictureStyle

BigPictureStyle は Notification の背景に大きい画像を置くことができるスタイルです。

// BigPictureStyle
NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle(builder);
bigPictureStyle.bigPicture(bigPicture);
bigPictureStyle.setBigContentTitle("BigContentTitle");
bigPictureStyle.setSummaryText("SummaryText");

bigPicture() にセットした Bitmap が大きく表示されます。また SummaryText もセットできるので、要約を書くこともできます。この BigPicture ですが、推奨サイズがどこにも記載されていません…。いったい何対何の比率で作れば良いのでしょうか。。サンプルでは 450 x 240 px で作ってます。なんとなく。

InboxStyle

InboxStyle は複数行のテキストを表示できるスタイルです。

// InboxStyle
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(builder);
inboxStyle.setBigContentTitle("BigContentTitle");
inboxStyle.setSummaryText("SummaryText");
for (int i = 0; i < 10; i++) {
	inboxStyle.addLine("Line" + (i + 1));
}
[/java]
</p>

<p>
addLine() でいくつも行を増やすことができます。例として10行追加してみましたが、7行までしか表示できませんでした。端末ごとに変わってくるのでしょうか。そのほか、他のスタイル同様 BigContentTitle と SumarryText をセットすることができます。
</p>

<h2 id="toc-notification-">Notification にボタンを追加する</h2>
<p>
これは 4.0 からの機能になりますが、 Notification にボタンを入れることができます。例として3つのアクションボタンを設置してみました。
</p>

<p>

builder.addAction(R.drawable.ic_small, "アクション1", contentIntent);
builder.addAction(R.drawable.ic_small, "アクション2", contentIntent);
builder.addAction(R.drawable.ic_small, "アクション3", contentIntent);

実行結果

contentIntent はボタンを押したときに発行する Intent を指定します。デフォルトのスタイルだけではなく、すべてのスタイルにボタンを表示することができます。3つまでしか追加できないようなのでご注意ください。

まとめ

4.0 から Notification のカスタマイズがかなりできるようになりましたが、 4.1 からはさらにいろいろなカスタマイズができるようになりました。アプリの機能に合わせて、ユーザーに効果的に伝わるように活用していきたいですね。
また今回は 4.0 以下の OS でも動作することを注視してサンプルを書きました。NotificationCompat を使うことで Notification のスタイル変更をわざわざバージョン毎に分けてに実装する必要がないので、いままで作成したアプリにも気軽に導入できます。ぜひ試してみてください!

参考