アンドロイドのは通知の種類と実装方法についてまとめました。 Notificationを実装するには、まずNotification Channelを作成する必要があります。 そしてBigText、BigPicture、Inbox、Messaging、Media StyleなどでNotificationを登録することができます。また、Head Up画面にポップアップ表示したり、Replyボタンを追加することもできます。
アンドロイドQを基準にNotificaitonをどのように実装するか、画面にどのように見えるかを知ってみましょう。
この記事で紹介するコードは、すべての鼻間違って作成しました。すべてのコードは、GitHubで確認することができます。
Notification Channel生成
Android O(API 26)でNotification Channel概念が追加されました。 だからAndroid O以上のデバイスにNotificationを浮上させよう遠い先Channelを作成する必要があります。
次のコードは、Channelを生成するコードです。
private fun createNotificationChannel(context: Context, importance: Int, showBadge: Boolean,
                                      name: String, description: String) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channelId = "${context.packageName}-$name"
        val channel = NotificationChannel(channelId, name, importance)
        channel.description = description
        channel.setShowBadge(showBadge)
        val notificationManager = context.getSystemService(NotificationManager::class.java)
        notificationManager.createNotificationChannel(channel)
    }
}NotificationManager.createNotificationChannel()でチャンネルを作成することができ、 チャンネルID、チャンネル名、チャンネルの重要度に生成されたNotificationChannelオブジェクトを引数として渡します。
- Channel Id:アプリごとにuniqueのIDを生成する必要があり、長い切り捨てられます。
 - Channel Name:ユーザに表示されるチャンネルの名前です。
 - Channel Importance:チャンネルが重要度を意味し、IMPORTANCE_DEFAULT、IMPORTANCE_HIGHなどに設定することができます。
 
チャンネルが作成されると、ノーフィケーションを登録することができます。ノーフィケーションを登録するときにチャネルを作成するときに使用したChannel Idを使用します。
Notification登録
チャンネルを作成した場合、登録したチャンネルIDでは通知を登録することができます。 簡単なノーティは以下のようにアイコン、タイトル、コンテンツを表示します。
次のコードは、基本的なノーフィケーションを登録するコードです。
createNotificationChannel(this, NotificationManagerCompat.IMPORTANCE_DEFAULT,
    false, getString(R.string.app_name), "App notification channel") // 1
val channelId = "$packageName-${getString(R.string.app_name)}" // 2
val title = "Android Developer"
val content = "Notifications in Android P"
val intent = Intent(baseContext, NewActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(baseContext, 0,
    intent, PendingIntent.FLAG_UPDATE_CURRENT)    // 3
val builder = NotificationCompat.Builder(this, channelId)  // 4
builder.setSmallIcon(R.drawable.ic_codechacha)    // 5
builder.setContentTitle(title)    // 6
builder.setContentText(content)    // 7
builder.priority = NotificationCompat.PRIORITY_DEFAULT    // 8
builder.setAutoCancel(true)   // 9
builder.setContentIntent(pendingIntent)   // 10
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID, builder.build())    // 11コメントの '// 1'ように重要な部分に番号を付けた、下記に詳細に説明しました。
- は通知チャンネルを作成していたら作成します。
 - チャンネルを作成するときに使用したチャネルIDです。ノーティ登録するときに必要です。
 - PendingIntentです。ノーティをタッチしたときにアクティビティを実行するために必要です。
 - Notificationを作成するBuilderです。ここでchannelIdを引数として配置します。
 - ノーティに表示されるアイコンです。
 - ノーティに見えるタイトルです。
 - ノーティのタイトルの下に表示されるテキストです。
 - ノーティの重要度を表します。重要度に応じてノーが見られないことがあります。
 - AutoCancelがtrueの場合、ユーザーがノーをタッチしたとき消えるします。 falseの場合押しても消えません。
 - 上記で作成しPendingIntentをノーに登録します。
 - NotificationManager.notify()でノーを登録します。
 
IDが同じであれば、1つのノー万生成され、異なる複数のノーが生成されます。 IDを知ること、そのIDで登録されたノーをコードでキャンセルすることもできます。
まとめると、ノーフィケーションは、Notification.Builderを利用して生成し、この過程でPendingIntentとリソースを設定することができます。 そしてNotificationManager.notify()を使用して生成されたノーを登録することができます。
BigTextスタイル
基本的なノーティず、他のカスタムノーを作成したいときがあります。 Androidは、頻繁に使用されているノーフィケーションをスタイルという概念で使用できるようにしました。 適用する方法は、まず、スタイルオブジェクトを作成し、Builderに追加して、ノーを作成します。
一番最初にBigTextスタイルについて説明します。 BigTextStyleは大量のテキストを示すことができるノーです。 基本ノーと異なり、BigTextStyleノーは畳み(collapse)展開することができ(expand)があります。
BigTextStyleが適用され、コードは次のとおりです。
val NOTIFICATION_ID = 1001;
createNotificationChannel(this, NotificationManagerCompat.IMPORTANCE_DEFAULT, false,
        getString(R.string.app_name), "App notification channel")
val channelId = "$packageName-${getString(R.string.app_name)}"
val title = "Android Developer"
val content = "Notifications in Android P"
val intent = Intent(baseContext, NewActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(baseContext, 0,
        intent, PendingIntent.FLAG_UPDATE_CURRENT)
val bigText = "Android 9 introduces several enhancements to notifications," +
        " all of which are available to developers targeting API level 28 and above."
val style = NotificationCompat.BigTextStyle()   // 1
style.bigText(bigText)    // 2
val builder = NotificationCompat.Builder(this, channelId)
builder.setSmallIcon(R.drawable.ic_codechacha)
builder.setContentTitle(title)
builder.setContentText(content)
builder.setStyle(style)   // 3
builder.priority = NotificationCompat.PRIORITY_DEFAULT
builder.setAutoCancel(true)
builder.setContentIntent(pendingIntent)
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID, builder.build())上記と同じ方法で説明をします。 Basicノーティと同じ設定の説明は省略しました。
- BigTextStyleオブジェクトを生成します。
 - スタイルにbigText(長いテキスト)を設定します。
 - BuilderにBigTextStyleを設定します。
 
基本的なノーティ生成コードとほとんど同じで、スタイルオブジェクトが追加されることが、他の部分です。
BigPictureスタイル
BigPictureStyleは大きな画像を表示するノーフィケーションです。
以下は、BigPictureStyleが適用されたノフィケーションコードです。
val NOTIFICATION_ID = 1001;
createNotificationChannel(this, NotificationManagerCompat.IMPORTANCE_DEFAULT, false,
    getString(R.string.app_name), "App notification channel")
val channelId = "$packageName-${getString(R.string.app_name)}"
val title = "Castle"
val content = "Welcome to my catle"
val intent = Intent(baseContext, NewActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(baseContext, 0,
        intent, PendingIntent.FLAG_UPDATE_CURRENT)
val style = NotificationCompat.BigPictureStyle()    // 1
style.bigPicture(
    BitmapFactory.decodeResource(resources, R.drawable.castle))   // 2
val builder = NotificationCompat.Builder(this, channelId)
builder.setSmallIcon(R.drawable.ic_codechacha)
builder.setContentTitle(title)
builder.setContentText(content)
builder.setStyle(style)   // 3
builder.priority = NotificationCompat.PRIORITY_DEFAULT
builder.setAutoCancel(true)
builder.setContentIntent(pendingIntent)
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID, builder.build())- BigPictureStyleオブジェクトを生成します。
 
2.スタイルにBig Pictureを登録します。引数はBitmapイメージを受けます。 BitmapFactoryにリソースをBitmapに変換しました。 3. Builderのスタイルを設定しました。
基本的なノフィケーションコードにBigPictureStyleが適用されました。
受信ボックスのスタイル
InboxStyleは大量のアイテムを表現するのに良いは通知のスタイルです。 例えば、電子メールアプリなどで使われることができます。このスタイルのノーもあきらめた展開することができます。
以下は、InboxStyleが適用されたノフィケーションコードです。
val NOTIFICATION_ID = 1001;
createNotificationChannel(this, NotificationManagerCompat.IMPORTANCE_DEFAULT, false,
    getString(R.string.app_name), "App notification channel")
val channelId = "$packageName-${getString(R.string.app_name)}"
val title = "3 Mails"   // 1
val content = "+5 Mails"   // 2
val intent = Intent(baseContext, NewActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(baseContext, 0,
        intent, PendingIntent.FLAG_UPDATE_CURRENT)
val style = NotificationCompat.InboxStyle()   // 3
style.addLine("Mail1 ...")    // 4
style.addLine("Mail2 ...")
style.addLine("Mail3 ...")
val builder = NotificationCompat.Builder(this, channelId)
builder.setSmallIcon(R.drawable.ic_codechacha)
builder.setContentTitle(title)
builder.setContentText(content)
builder.setStyle(style)   // 5
builder.priority = NotificationCompat.PRIORITY_DEFAULT
builder.setAutoCancel(true)
builder.setContentIntent(pendingIntent)
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID, builder.build())- ノーティのタイトルです。
 - ノーティが接した時に見えるテキストです。繰り広げられたときは見えません。
 - InboxStyleオブジェクトを生成します。
 - addLine()でリストのアイテムを登録し、ノーが繰り広げられた時に見えるテキストです。
 - Builderにスタイルを設定します。
 
メッセージングスタイル
MessagingStyleはユーザー間の対話内容を表現するときに使われることができるスタイルです。 下の図のようにメッセージアプリで見ることができるようなノーフィケーションです。
以下は、MessagingStyleが適用されたノフィケーションのコードです。
val NOTIFICATION_ID = 1001;
createNotificationChannel(this, NotificationManagerCompat.IMPORTANCE_DEFAULT, false,
    getString(R.string.app_name), "App notification channel")
val channelId = "$packageName-${getString(R.string.app_name)}"
val title = "Messaging style title"
val content = "Messaging style content"
val intent = Intent(baseContext, NewActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(baseContext, 0,
        intent, PendingIntent.FLAG_UPDATE_CURRENT)
val userIcon1 = IconCompat.createWithResource(this, R.drawable.codechacha)  // 1
val userIcon2 = IconCompat.createWithResource(this, R.drawable.android)
val userIcon3 = IconCompat.createWithResource(this, R.drawable.android)
val userName1 = "Chacha"    // 2
val userName2 = "Android"
val userName3 = "JS"
val timestamp = System.currentTimeMillis()   // 3
val user1 = Person.Builder().setIcon(userIcon1).setName(userName1).build()  // 4
val user2 = Person.Builder().setIcon(userIcon2).setName(userName2).build()
val user3 = Person.Builder().setIcon(userIcon3).setName(userName3).build()
val style = NotificationCompat.MessagingStyle(user3)  // 5
style.addMessage("You can get great deals there", timestamp, user1)  // 6
style.addMessage("I know what to get", timestamp, user2)  // 7
val builder = NotificationCompat.Builder(this, channelId)  // 8
builder.setSmallIcon(R.drawable.ic_codechacha)
builder.setContentTitle(title)
builder.setContentText(content)
builder.setStyle(style)  // 9
builder.priority = NotificationCompat.PRIORITY_DEFAULT
builder.setAutoCancel(true)
builder.setContentIntent(pendingIntent)
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID, builder.build())- Personオブジェクトの作成に使われるIconオブジェクトを作成します。
 - Personオブジェクトの名前です。
 - Message登録する際に使われる時間です。サンプルなので、現在の時刻を入れてくれました。
 - Person.Builderを利用して、Personオブジェクトを作成しました。ここで、アイコンと名前が入ります。
 - MessagingStyleオブジェクトを生成し、引数としてPersonオブジェクトを渡します。 Personは、メッセージの受信者です。
 
Inline Reply機能を追加したときにすぐに返事が可能で、この因子のPersonオブジェクトが返信したかのようになります。 Inline Replyは、以下で紹介されます。 6. User1からのメッセージを追加まし書き込みます。 7. User2が送信したメッセージを追加しました。 8. Builderを作成します。 9. Builderでスタイルを設定します。
MessagingStyleの引数に入るUserはメッセージを受信するUserです。 addMessage()に入るPerson引数は、メッセージを送信したUserです。
メディアスタイル
MediaStyleは音楽再生に関連ノーに使用することができるスタイルです。下の図のように、Play、Skip Prevなどのボタンがあり、ボタンが押されたときMedia Sessionを制御することができます。 ここでノーティを浮かべることのみ説明します。
以下は、MediaStyleが適用され、コードです。
val NOTIFICATION_ID = 1001;
createNotificationChannel(this, NotificationManagerCompat.IMPORTANCE_DEFAULT, false,
        getString(R.string.app_name), "App notification channel")
val channelId = "$packageName-${getString(R.string.app_name)}"
val title = "Don't Say a Word"
val content = "Ellie Goulding"
val intent = Intent(baseContext, NewActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(baseContext, 0,
        intent, PendingIntent.FLAG_UPDATE_CURRENT)
val builder = NotificationCompat.Builder(this, channelId)
builder.setSmallIcon(R.drawable.ic_codechacha)
builder.setContentTitle(title)  // 1
builder.setContentText(content)  // 2
builder.setLargeIcon(
    BitmapFactory.decodeResource(resources, R.drawable.castle)) // 3
builder.addAction(NotificationCompat.Action(
    R.drawable.ic_thumb_down,"skip prev", pendingIntent))   // 4
builder.addAction(NotificationCompat.Action(
    R.drawable.ic_skip_prev,"skip prev", pendingIntent))
builder.addAction(NotificationCompat.Action(
    R.drawable.ic_pause,"pause", pendingIntent))
builder.addAction(NotificationCompat.Action(
    R.drawable.ic_skip_next,"skip next", pendingIntent))
builder.addAction(NotificationCompat.Action(
    R.drawable.ic_thumb_up,"skip prev", pendingIntent))
builder.setStyle(MediaStyle().setShowActionsInCompactView(1, 2, 3)) // 5
builder.priority = NotificationCompat.PRIORITY_DEFAULT
builder.setAutoCancel(true)
builder.setContentIntent(pendingIntent)
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID, builder.build())- ノーティに表示されるタイトルです。
 - タイトルの下に表示されるコンテンツです。
 - ノーティの右側に表示されるイメージです。
 - ノーティに表示されるアイコンです。 addAction()に追加し、アイコン、タイトル、PendingIntentを引数として挿入します。
 
アイコンが押されるPendingIntentが実行されます。この例では、5つのアイコンをaddAction()で追加しました。 5. BuilderにMediaStyleスタイルを作成して追加します。 MediaStyleを作成しsetShowActionsInCompactView(1、2、3)を設定しました。 このコードは、ノーが接した時Index 1、2、3回のアイコンだけを表示可能にすることです。
Builder.addAction()のアイコンとアイコンが押されたときに実行PendingIntentを追加します。
このPendingIntentを使用すると、Mediaを制御することができます。
MediaStyle.setShowActionsInCompactView()は、折れたとき表示されるアイコンのIndexを設定します。 上の図のように広げたときは、すべてのアイコンが見えますが、折れたときの3つのアイコンだけを見えるようにしました。
インライン返信
Inline Replyはノーですぐ応答をすることができる機能です。 MessagingStyleのコードでInline Replyを追加します。
expanded notification, Reply button
      
    
  
  
    
collapsed notification, Replyボタンが見えん
      
    
  
  
    
以下は、上記のMessagingStyle例にInline Replyが適用されたコードです。
val NOTIFICATION_ID = 1001;
createNotificationChannel(this, NotificationManagerCompat.IMPORTANCE_DEFAULT, false,
    getString(R.string.app_name), "App notification channel")
val channelId = "$packageName-${getString(R.string.app_name)}"
val title = "3 Messages"
val content = "+5 Messages"
val intent = Intent(baseContext, NewActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(baseContext, 0,
    intent, PendingIntent.FLAG_UPDATE_CURRENT)
val replyLabel = "Enter your reply here"
val remoteInput = RemoteInput.Builder("key_reply")
    .setLabel(replyLabel)
    .build()
val replyAction = NotificationCompat.Action.Builder(
    android.R.drawable.sym_action_chat, "REPLY", pendingIntent)   // 1
    .addRemoteInput(remoteInput)  // 2
    .setAllowGeneratedReplies(true)  // 3
    .build()
val userIcon1 = IconCompat.createWithResource(this, R.drawable.codechacha)
val userIcon2 = IconCompat.createWithResource(this, R.drawable.android)
val userIcon3 = IconCompat.createWithResource(this, R.drawable.person)
val userName1 = "Chacha"
val userName2 = "Android"
val userName3 = "JS"
val timestamp = System.currentTimeMillis()
val user1 = Person.Builder().setIcon(userIcon1).setName(userName1).build()
val user2 = Person.Builder().setIcon(userIcon2).setName(userName2).build()
val user3 = Person.Builder().setIcon(userIcon3).setName(userName3).build()
val style = NotificationCompat.MessagingStyle(user3)
style.addMessage("You can get great deals there", timestamp, user1)
style.addMessage("I know what to get", timestamp, user2)
val builder = NotificationCompat.Builder(this, channelId)
builder.setSmallIcon(R.drawable.ic_codechacha)
builder.setContentTitle(title)
builder.setContentText(content)
builder.setStyle(style)
builder.priority = NotificationCompat.PRIORITY_DEFAULT
builder.setAutoCancel(true)
builder.setContentIntent(pendingIntent)
builder.addAction(replyAction)    // 4
builder.addAction(android.R.drawable.ic_menu_close_clear_cancel,
    "DISMISS", pendingIntent); // 5
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID, builder.build())ほとんどのコードは、MessagingStyle例と同じです。他の部分は次の3つです。
- Reply Actionを作成します。
 - この機能は、よく分からなくて、今後の更新いたします。
 - この機能は、よく分からなくて、今後の更新いたします。
 - BuilderにReplay Actionを追加します。
 - Dismiss Actionを追加します。ボタンのアイコンとボタンが押されたときに実行するPendingIntentを引数として挿入します。
 
Builder.addAction()を介してノーのInline Replyボタンを作成することができます。
RemoteInputの因子がノーでどのような影響を与えるか詳細知らず、今後の更新いたします。
ヘッドアップ通知
Head up Notificationは、前面にノーが浮かぶことです。 ユーザーがStatusbarを下げて確認しなくてもすぐに画面に浮かぶので、簡単に目立ちます。電話のような重要な仕事を発表したとき、このようなノーを適用するといいようです。 重要ではないのに使用される場合、ユーザーがこのアプリが震動と考えることができます。
以下の画面は、Head up notificationです。例では、基本的なノーに適用したが、すべてのスタイルのノーに適用することができます。
      
    
  
  
    
以下は、Head Up Notifiationが適用されたコードです。
val NOTIFICATION_ID = 1001;
createNotificationChannel(this, NotificationManagerCompat.IMPORTANCE_HIGH, false,
    getString(R.string.app_name), "App notification channel")   // 1
val channelId = "$packageName-${getString(R.string.app_name)}"
val title = "Android Developer"
val content = "Notifications in Android P"
val intent = Intent(baseContext, NewActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val fullScreenPendingIntent = PendingIntent.getActivity(baseContext, 0,
        intent, PendingIntent.FLAG_UPDATE_CURRENT)    // 2
val builder = NotificationCompat.Builder(this, channelId)
builder.setSmallIcon(R.drawable.ic_codechacha)
builder.setContentTitle(title)
builder.setContentText(content)
builder.priority = NotificationCompat.PRIORITY_HIGH   // 3
builder.setAutoCancel(true)
builder.setFullScreenIntent(fullScreenPendingIntent, true)   // 4
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.notify(NOTIFICATION_ID, builder.build())- チャンネルを作成するときに重要度をIMPORTANCE_HIGHに設定する必要があります。
 - PendingIntentを作成します。 BuilderにfullScreenPendingIntentを登録するので、変数名をfullScreenPendingIntentとしました。
 - BuilderのpriorityをPRIORITY_HIGHに設定する必要があります。
 - fullScreenPendingIntentを登録します。
 
そして、最も重要なことは、アプリのAndroidManifest.xmlに以下のパーミッションを必ず追加する必要があります。 Installパーミッションであるため、インストールするだけですぐに権限を受け取ります。
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>Head up notificationは、チャンネルの重要度をIMPORTANCE_HIGH、ノーの重要度をPRIORITY_HIGHに設定する必要があります。
そしてfullScreenIntentを追加する必要があります。
最後に、最も重要なことは、Qから USE_FULL_SCREEN_INTENT権限がない場合Head upノーを浮かせることができないので、必ず追加してくれるとします。
まとめ
様々な種類のは通知について調べてみました。 上で紹介しスタイルを自分のアプリに適用することができない場合は、Customて実装する必要があります。
この記事で使用されたコードは、GitHubにあります。
参考
Related Posts
- Android - FusedLocationProviderClientに位置情報を取得する
 - Android - GPS、Network位置情報を取得する(LocationManager)
 - Android - adbコマンドでActivity実行
 - アンドロイド - MediaStoreにメディアファイルを保存する方法
 - Android - Runtime permissionリクエスト方法と例(kotlin)
 - Android11 - Storage(ストレージ)の変更まとめ
 - Jetpack Compose - RowとColumn
 - Android 13 - 細かいメディアファイルの権限
 - Android 13でNotification権限をリクエスト、通知を表示する
 - エラー解決:android gradle plugin requires java 11 to run. you are currently using java 1.8.
 - Query method parameters should either be a type that can be converted into a database column or a List
 - Android - TabLayoutの実装方法(+ ViewPager2)
 - Android - adbコマンドで特定のパッケージのプロセスの終了
 - Android - adb push、pullでファイルのコピー、ダウンロード
 - Android - adbコマンドでsettings value確認、変更、
 - Android 12 - IntentFilterのexported明示的な宣言
 - Android - adb logcatコマンドでログ出力
 - Android - ACTION_BOOT_COMPLETEDイベント受信
 - Android - Foreground Service実行
 - Android - ファイル入出力の例(Read、Write、内部、外部ストレージ)
 - Android - アプリの権限を確認(Permission check)
 - Android - adbで実行中のプロセス、スレッドリスト及びメモリ情報の確認
 - Android - Broadcast Receiver登録およびイベントの受信方法
 - Android - Cleartext HTTP ... not permitted例外解決方法
 - Androidのビルドエラー - Calls to Java default methods are prohibited in JVM target 1.6
 - アンドロイド - Assetsでファイルを読み取る方法
 - アンドロイドのさまざまなNotification種類と実装方法
 - アンドロイド - INSTALL_FAILED_TEST_ONLYエラー解決方法
 - Android EspressoのCustom Matcher実装方法
 - Android Espressoを使用してUIをテストする方法(3)
 - アンドロイド - CTS hostsideをgradleで構築する方法
 - Androidのアプリのデータフォルダーのパスと内部/外部ストレージ説明
 - アンドロイド - 最初のApp作成
 - Androidをインストールする方法(Windows)