Slide 1

Slide 1 text

։ൃऀ͕஌͓͖͍ͬͯͨ ௨஌ͷྺ࢙ Keisuke Kobayashi (kobakei) DroidKaigi 2018 Day2 Room1 18:30~19:00

Slide 2

Slide 2 text

About Me • Keisuke Kobayashi • GitHub, Qiita: kobakei • Twitter: kobakei122 • Kyash, Inc.

Slide 3

Slide 3 text

Kyash

Slide 4

Slide 4 text

ࠓ೔࿩͢͜ͱ • ௨஌ͷྺ࢙ͱޙํޓ׵ੑΛߟྀ࣮ͨ͠૷ʹ
 ͍ͭͯ঺հ͠·͢ • ॳ৺ऀ޲͚ • ࠷ۙAndroid։ൃΛ࢝Ίͨํ • Firebaseʹ೚͖ͤͬΓͰ࣮૷͍ͯ͠Δํ

Slide 5

Slide 5 text

ࠓ೔࿩͞ͳ͍͜ͱ • αϙʔτϥΠϒϥϦ͕αϙʔτ͍ͯ͠ͳ͍
 ICSΑΓੲͷ࿩͸͠·ͤΜ • Wearͷ࿩͸͠·ͤΜ

Slide 6

Slide 6 text

௨஌ͷྺ࢙

Slide 7

Slide 7 text

௨஌ • Ϣʔβʔʹͱͬͯॏཁͳػೳ • සൟʹมߋ͕ೖΔ • SDKόʔδϣϯͷ෼ذ͕ඞཁ • ಉ࣮͡૷Ͱ΋ɺݟ͑ํ͕OS͝ͱʹҧ͏ • ಈ࡞֬ೝ͕େม

Slide 8

Slide 8 text

"1*MFWFM όʔδϣϯ໊ ίʔυωʔϜ ओͳػೳ *$4 *$4 +FMMZ#FBO ΞΫγϣϯɺελΠϧ௥Ճ +FMMZ#FBO +FMMZ#FBO ,JU,BU -PMMJQPQ ϚςϦΞϧσβΠϯɺϩοΫεΫϦʔϯɺ
 ϔουΞοϓɺελΠϧ௥Ճ -PMMJQPQ .BTINBMMPX /PVHBU όϯυϧɺϦϓϥΠɺελΠϧ௥Ճ /PVHBU 0SFP νϟϯωϧɺόοδ 0SFP

Slide 9

Slide 9 text

"1*MFWFM όʔδϣϯ໊ ίʔυωʔϜ ओͳػೳ *$4 *$4 +FMMZ#FBO ΞΫγϣϯɺελΠϧ௥Ճ +FMMZ#FBO +FMMZ#FBO ,JU,BU -PMMJQPQ ϚςϦΞϧσβΠϯɺϩοΫεΫϦʔϯɺ
 ϔουΞοϓɺελΠϧ௥Ճ -PMMJQPQ .BTINBMMPX /PVHBU όϯυϧɺϦϓϥΠɺελΠϧ௥Ճ /PVHBU 0SFP νϟϯωϧɺόοδ 0SFP

Slide 10

Slide 10 text

"1*MFWFM όʔδϣϯ໊ ίʔυωʔϜ ओͳػೳ *$4 *$4 +FMMZ#FBO ΞΫγϣϯɺελΠϧ௥Ճ +FMMZ#FBO +FMMZ#FBO ,JU,BU -PMMJQPQ ϚςϦΞϧσβΠϯɺϩοΫεΫϦʔϯɺ
 ϔουΞοϓɺελΠϧ௥Ճ -PMMJQPQ .BTINBMMPX /PVHBU όϯυϧɺϦϓϥΠɺελΠϧ௥Ճ /PVHBU 0SFP νϟϯωϧɺόοδ 0SFP

Slide 11

Slide 11 text

"1*MFWFM όʔδϣϯ໊ ίʔυωʔϜ ओͳػೳ *$4 *$4 +FMMZ#FBO ΞΫγϣϯɺελΠϧ௥Ճ +FMMZ#FBO +FMMZ#FBO ,JU,BU -PMMJQPQ ϚςϦΞϧσβΠϯɺϩοΫεΫϦʔϯɺ
 ϔουΞοϓɺελΠϧ௥Ճ -PMMJQPQ .BTINBMMPX /PVHBU όϯυϧɺϦϓϥΠɺελΠϧ௥Ճ /PVHBU 0SFP νϟϯωϧɺόοδ 0SFP

Slide 12

Slide 12 text

"1*MFWFM όʔδϣϯ໊ ίʔυωʔϜ ओͳػೳ *$4 *$4 +FMMZ#FBO ΞΫγϣϯɺελΠϧ௥Ճ +FMMZ#FBO +FMMZ#FBO ,JU,BU -PMMJQPQ ϚςϦΞϧσβΠϯɺϩοΫεΫϦʔϯɺ
 ϔουΞοϓɺελΠϧ௥Ճ -PMMJQPQ .BTINBMMPX /PVHBU όϯυϧɺϦϓϥΠɺελΠϧ௥Ճ /PVHBU 0SFP νϟϯωϧɺόοδ 0SFP

Slide 13

Slide 13 text

جຊతͳ࣮૷

Slide 14

Slide 14 text

ඞਢ • title • text • small icon • id

Slide 15

Slide 15 text

Small icon • എܠಁա & നృΓ • ΨΠυϥΠϯ௨Γʹ࡞͍ͬͯΕ͹໰୊ͳ͍ • https://developer.android.com/guide/practices/ ui_guidelines/icon_design_status_bar.html • ϥϯνϟʔΞΠίϯΛͦͷ··࢖͍ͬͯΔ৔߹ɺ API 21Ҏ߱Ͱ͸നృΓʹͳΔͷͰ஫ҙ

Slide 16

Slide 16 text

γϯϓϧͳ࣮૷ val notification = NotificationCompat.Builder(context, CH_ID_NORMAL) .setContentTitle("This is title") .setContentText("This is message") .setSmallIcon(R.drawable.ic_notification) .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 17

Slide 17 text

΄΅ඞਢ • color • defaults • pending intent • auto cancel • ticker (※Android 4.4·ͰͰ࢖༻)

Slide 18

Slide 18 text

ݱ࣮తͳ࣮૷ val intent = Intent(context, MainActivity::class.java) val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) val notification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) .setContentTitle("This is title") .setContentText("This is message") .setTicker("This is ticker") // for legacy Android .setSmallIcon(R.drawable.ic_notification) .setColor(ContextCompat.getColor(context, R.color.colorPrimary)) .setDefaults(Notification.DEFAULT_ALL) .setContentIntent(pendingIntent) .setAutoCancel(true) .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 19

Slide 19 text

Large icon

Slide 20

Slide 20 text

Large icon • ը૾μ΢ϯϩʔυΛؚΉ௨஌Λදࣔ͢Δͱ͖͸ Serviceਪ঑ • BroadcastReceiver͸10ඵλΠϜΞ΢τ͕
 ͋ΔͷͰɺ͕͔͔࣌ؒΔॲཧʹ͸޲͔ͳ͍ • ݸਓతʹ͸FirebaseJobDispatcherͳͲඇಉ ࣌δϣϒΛ࢖͏ͱָ

Slide 21

Slide 21 text

VIBRATE_PERMISSION • Android 4.1·Ͱ͸ඞਢ • ๨ΕΔͱSecurityException͕ൃੜ • Android 4.2Ҏ߱͸ෆཁ

Slide 22

Slide 22 text

ϚςϦΞϧσβΠϯ • API 21͔Β • ௨஌ͷσβΠϯ΋େ෯ʹมΘͬͨ

Slide 23

Slide 23 text

Android 4.1

Slide 24

Slide 24 text

Android 8.1

Slide 25

Slide 25 text

Action (API 16~)

Slide 26

Slide 26 text

Action • ௨஌ʹ෇͘Ϙλϯ • ෳ਺ઃఆՄೳ • ΞΫγϣϯ͝ͱʹIntentΛઃఆ

Slide 27

Slide 27 text

Actionͷ஫ҙࣄ߲ • ICSͰ͸࢖͑ͳ͍ʢAPI 16Ҏ߱ͷΈʣ • ΞΠίϯ͸๨Εͣʹઃఆ͠Α͏ • API 16~19: Χϥʔදࣔ • API 21~23: άϨʔදࣔ • API 24~: ΞΠίϯදࣔͳ͠ • SVG࢖͑ͳ͍ͷͰ஫ҙ

Slide 28

Slide 28 text

Action (API 16~19)

Slide 29

Slide 29 text

Action (API 21~23)

Slide 30

Slide 30 text

Action (API 24~)

Slide 31

Slide 31 text

Action val notification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setContentIntent(pendingIntent) .addAction(R.drawable.ic_action_done, "Done", donePendingIntent) .addAction(R.drawable.ic_action_close, "Close", closePendingIntent) .setAutoCancel(true) .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 32

Slide 32 text

Direct Reply • API 24Ҏ߱ • ௨஌Ϗϡʔ্ͰΞϓϦىಈͤͣʹฦ৴͢Δػ ೳ • LINE, SlackͳͲ

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Direct Reply val action = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val remoteInput = RemoteInput.Builder(KEY_REMOTE_INPUT) .setLabel("Reply Label") .build() val replyIntent = Intent(context, MyBroadcastReceiver::class.java) val replyPendingIntent = PendingIntent.getBroadcast(context, 1001, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT) NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", replyPendingIntent) .addRemoteInput(remoteInput) .build() } else { NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", pendingIntent) .build() }

Slide 35

Slide 35 text

Direct Reply val action = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val remoteInput = RemoteInput.Builder(KEY_REMOTE_INPUT) .setLabel("Reply Label") .build() val replyIntent = Intent(context, MyBroadcastReceiver::class.java) val replyPendingIntent = PendingIntent.getBroadcast(context, 1001, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT) NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", replyPendingIntent) .addRemoteInput(remoteInput) .build() } else { NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", pendingIntent) .build() } API levelͰ෼ذ

Slide 36

Slide 36 text

Direct Reply val action = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val remoteInput = RemoteInput.Builder(KEY_REMOTE_INPUT) .setLabel("Reply Label") .build() val replyIntent = Intent(context, MyBroadcastReceiver::class.java) val replyPendingIntent = PendingIntent.getBroadcast(context, 1001, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT) NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", replyPendingIntent) .addRemoteInput(remoteInput) .build() } else { NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", pendingIntent) .build() } RemoteInput࡞੒

Slide 37

Slide 37 text

Direct Reply val action = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val remoteInput = RemoteInput.Builder(KEY_REMOTE_INPUT) .setLabel("Reply Label") .build() val replyIntent = Intent(context, MyBroadcastReceiver::class.java) val replyPendingIntent = PendingIntent.getBroadcast(context, 1001, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT) NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", replyPendingIntent) .addRemoteInput(remoteInput) .build() } else { NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", pendingIntent) .build() } Reply࣌ͷIntent

Slide 38

Slide 38 text

Direct Reply val action = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val remoteInput = RemoteInput.Builder(KEY_REMOTE_INPUT) .setLabel("Reply Label") .build() val replyIntent = Intent(context, MyBroadcastReceiver::class.java) val replyPendingIntent = PendingIntent.getBroadcast(context, 1001, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT) NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", replyPendingIntent) .addRemoteInput(remoteInput) .build() } else { NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", pendingIntent) .build() } Action࡞੒

Slide 39

Slide 39 text

Direct Reply val action = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val remoteInput = RemoteInput.Builder(KEY_REMOTE_INPUT) .setLabel("Reply Label") .build() val replyIntent = Intent(context, MyBroadcastReceiver::class.java) val replyPendingIntent = PendingIntent.getBroadcast(context, 1001, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT) NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", replyPendingIntent) .addRemoteInput(remoteInput) .build() } else { NotificationCompat.Action.Builder(R.drawable.ic_action_reply, "Reply", pendingIntent) .build() } API 23ҎԼ༻ͷී௨ͷAction

Slide 40

Slide 40 text

Direct Reply val notification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .addAction(action) .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 41

Slide 41 text

Style (API 16~)

Slide 42

Slide 42 text

Style • ௨஌Ϗϡʔͷݟͨ໨Λม͑Δػೳ • styles.xmlͱ͸ؔ܎ͳ͍ • API 16Ҏ߱

Slide 43

Slide 43 text

Style • API 16~ • BigTextStyle • BigPictureStyle • InboxStyle • API 21~ • MediaStyle • API 24~ • DecoratedCustomViewStyle • DecoratedMediaCustomViewStyle • MessagingStyle

Slide 44

Slide 44 text

ΊͬͪΌଟ͍

Slide 45

Slide 45 text

Style • API 16~ • BigTextStyle • BigPictureStyle • InboxStyle • API 21~ • MediaStyle • API 24~ • DecoratedCustomViewStyle • DecoratedMediaCustomViewStyle • MessagingStyle ࠷සग़ɻೋߦҎ্ͷςΩετͰ࢖༻

Slide 46

Slide 46 text

Style • API 16~ • BigTextStyle • BigPictureStyle • InboxStyle • API 21~ • MediaStyle • API 24~ • DecoratedCustomViewStyle • DecoratedMediaCustomViewStyle • MessagingStyle ը૾ܥΞϓϦͰ࢖༻

Slide 47

Slide 47 text

Style • API 16~ • BigTextStyle • BigPictureStyle • InboxStyle • API 21~ • MediaStyle • API 24~ • DecoratedCustomViewStyle • DecoratedMediaCustomViewStyle • MessagingStyle ԻָɾಈըܥΞϓϦͰ࢖༻ com.android.support-media-compat

Slide 48

Slide 48 text

Style • API 16~ • BigTextStyle • BigPictureStyle • InboxStyle • API 21~ • MediaStyle • API 24~ • DecoratedCustomViewStyle • DecoratedMediaCustomViewStyle • MessagingStyle ௨஌ϏϡʔΛΧελϚΠζ
 ͢Δ࣌ʹ࢖༻ʢ͋ͱͰઆ໌ʣ

Slide 49

Slide 49 text

Style • API 16~ • BigTextStyle • BigPictureStyle • InboxStyle • API 21~ • MediaStyle • API 24~ • DecoratedCustomViewStyle • DecoratedMediaCustomViewStyle • MessagingStyle ϝοηʔδܥΞϓϦͰ࢖༻ ʢޙͰઆ໌͠·͢ʣ

Slide 50

Slide 50 text

Big Text Style࣮૷ val style = NotificationCompat.BigTextStyle() .setBigContentTitle("Big content title") .setSummaryText("Big text summary") .bigText("This is long text. This is long text. This is long text. This is long text. This is long text.") val notification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) .setContentTitle("This is title") .setContentText("This is message") .setTicker("This is ticker") // for legacy Android .setStyle(style) ... .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 51

Slide 51 text

Big Text Style࣮૷ val style = NotificationCompat.BigTextStyle() .setBigContentTitle("Big content title") .setSummaryText("Big text summary") .bigText("This is long text. This is long text. This is long text. This is long text. This is long text.") val notification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) .setContentTitle("This is title") .setContentText("This is message") .setTicker("This is ticker") // for legacy Android .setStyle(style) ... .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification) StyleͷΠϯελϯε࡞੒

Slide 52

Slide 52 text

Big Text Style࣮૷ val style = NotificationCompat.BigTextStyle() .setBigContentTitle("Big content title") .setSummaryText("Big text summary") .bigText("This is long text. This is long text. This is long text. This is long text. This is long text.") val notification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) .setContentTitle("This is title") .setContentText("This is message") .setTicker("This is ticker") // for legacy Android .setStyle(style) ... .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

BigTextStyleͷ
 ɾBigContentTitle ɾBigText

Slide 55

Slide 55 text

Notification.Builderͷ Title, Text

Slide 56

Slide 56 text

௕จͩͱ..Ͱলུ͞ΕΔ

Slide 57

Slide 57 text

௨஌ͷΧελϚΠζ

Slide 58

Slide 58 text

ΧελϜϨΠΞ΢τ • Notification.Builder#setContent • API 24Ҏ߱ • DecoratedCustomViewStyle, DecoratedMediaCustomViewStyle

Slide 59

Slide 59 text

Notification.Builder#setContent

Slide 60

Slide 60 text

val customView = RemoteViews(context.packageName, R.layout.custom_layout) val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setContent(customView) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notificationBuilder.build()) Notification.Builder#setContent

Slide 61

Slide 61 text

val customView = RemoteViews(context.packageName, R.layout.custom_layout) val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setContent(customView) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notificationBuilder.build()) Notification.Builder#setContent RemoteViews࡞੒

Slide 62

Slide 62 text

val customView = RemoteViews(context.packageName, R.layout.custom_layout) val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setContent(customView) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notificationBuilder.build()) Notification.Builder#setContent

Slide 63

Slide 63 text

RemoteViews • ଞϓϩηεͷϏϡʔͷ֊૚ߏ଄Λද͢Ϋϥε • ViewͷαϒΫϥεͰ͸ͳ͍ • findViewByIdͰchild viewʹΞΫηεͰ͖ͳ ͍ • RemoteViews#setString(viewId, methodName, value)
 ͳͲͰૢ࡞͢Δ

Slide 64

Slide 64 text

DecoratedCustomViewStyle • API 24Ҏ߱ • RemoteViewsΛɺΞΠίϯɺλΠτϧͳͲ
 ඪ४ͷཁૉͰϥοϓ͢ΔελΠϧ • ޙํޓ׵ੑ͋Γ • NotificationCompat.DecoratedCustomViewStyle

Slide 65

Slide 65 text

DecoratedCustomViewStyle

Slide 66

Slide 66 text

DecoratedCustomViewStyle
 (API 15)

Slide 67

Slide 67 text

DecoratedCustomViewStyle val customView = RemoteViews(context.packageName, R.layout.custom_layout) val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setCustomContentView(customView) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 68

Slide 68 text

DecoratedCustomViewStyle val customView = RemoteViews(context.packageName, R.layout.custom_layout) val notificationBuilder = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setCustomContentView(customView) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 69

Slide 69 text

Colorized • ਐߦதͷॏཁͳ௨஌ʹͷΈɺഎܠ৭Λ෇͚Δ͜ͱ͕Ͱ͖Δ • ௨࿩தɺΧʔφϏͳͲ • Foreground ServiceͱηοτͰ࢖͏ • ςΩετΧϥʔ͸എܠ৭͔ΒࣗಈͰܾ·ΔʢઃఆෆՄʣ • BLACK or WHITE • ίϯτϥετΛߟྀͨ͠എܠ৭Λઃఆ͢Δ͜ͱ • API 26Ҏ߱

Slide 70

Slide 70 text

Colorized

Slide 71

Slide 71 text

Colorized fun createColorizedNotification(service: Service): Notification { val context = service.applicationContext val intent = Intent(context, MainActivity::class.java) val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) return NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setColor(Color.DKGRAY) .setColorized(true) .setPriority(Notification.PRIORITY_HIGH) .build() } Colorized༗ޮԽ

Slide 72

Slide 72 text

Colorized: Service class SampleForegroundService : IntentService("sample") { override fun onHandleIntent(intent: Intent?) { startForeground(1, createColorizedNotification(this)) // do something... } } ForegroundϞʔυʹೖͬͯ
 ௨஌Λදࣔ

Slide 73

Slide 73 text

௨஌νϟϯωϧ (API 26~)

Slide 74

Slide 74 text

௨஌νϟϯωϧ • API 26Ҏ߱ • Ϣʔβʔ͕௨஌OFFɺԻɾόΠϒઃఆͳͲΛ੾ Γସ͑ΒΕΔ • targetSdkVersion=26Ҏ্Ͱ͸ରԠඞਢ • ࣮૷͸ࣗ෼ͰAPI levelͰ෼ذΛॻ͘

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

௨஌νϟϯωϧͷ࡞੒ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel1 = NotificationChannel(CHANNEL_ID_NORMAL, "ී௨ͷνϟϯωϧ", NotificationManager.IMPORTANCE_DEFAULT) val channel2 = NotificationChannel(CHANNEL_ID_IMPORTANT, "ॏཁͳνϟϯω ϧ", NotificationManager.IMPORTANCE_HIGH) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.createNotificationChannel(channel1) nm.createNotificationChannel(channel2) }

Slide 77

Slide 77 text

௨஌νϟϯωϧͷ࡞੒ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel1 = NotificationChannel(CHANNEL_ID_NORMAL, "ී௨ͷνϟϯωϧ", NotificationManager.IMPORTANCE_DEFAULT) val channel2 = NotificationChannel(CHANNEL_ID_IMPORTANT, "ॏཁͳνϟϯω ϧ", NotificationManager.IMPORTANCE_HIGH) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.createNotificationChannel(channel1) nm.createNotificationChannel(channel2) } API 26Ҏ߱ͷΈ࣮ߦ

Slide 78

Slide 78 text

௨஌νϟϯωϧͷ࡞੒ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel1 = NotificationChannel(CHANNEL_ID_NORMAL, "ී௨ͷνϟϯωϧ", NotificationManager.IMPORTANCE_DEFAULT) val channel2 = NotificationChannel(CHANNEL_ID_IMPORTANT, "ॏཁͳνϟϯω ϧ", NotificationManager.IMPORTANCE_HIGH) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.createNotificationChannel(channel1) nm.createNotificationChannel(channel2) }

Slide 79

Slide 79 text

௨஌νϟϯωϧͷ࡞੒ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel1 = NotificationChannel(CHANNEL_ID_NORMAL, "ී௨ͷνϟϯωϧ", NotificationManager.IMPORTANCE_DEFAULT) val channel2 = NotificationChannel(CHANNEL_ID_IMPORTANT, "ॏཁͳνϟϯω ϧ", NotificationManager.IMPORTANCE_HIGH) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.createNotificationChannel(channel1) nm.createNotificationChannel(channel2) } IDॱͰιʔτ͞ΕΔ

Slide 80

Slide 80 text

௨஌νϟϯωϧͷ࡞੒ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel1 = NotificationChannel(CHANNEL_ID_NORMAL, "ී௨ͷνϟϯωϧ", NotificationManager.IMPORTANCE_DEFAULT) val channel2 = NotificationChannel(CHANNEL_ID_IMPORTANT, "ॏཁͳνϟϯω ϧ", NotificationManager.IMPORTANCE_HIGH) val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.createNotificationChannel(channel1) nm.createNotificationChannel(channel2) }

Slide 81

Slide 81 text

௨஌νϟϯωϧͷࢦఆ val notification = NotificationCompat.Builder(context, CH_ID_NORMAL) .setContentTitle("This is title") .setContentText("This is message") .setSmallIcon(R.drawable.ic_notification) .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification) νϟϯωϧIDΛࢦఆ

Slide 82

Slide 82 text

ϝλσʔλ

Slide 83

Slide 83 text

ϝλσʔλ • ௨஌ʹඥͮ͘ϝλσʔλɻ௨஌ͷදࣔॱংʹӨڹ ͢Δ • setPriority • setCategory • addPerson • API 26͔Β͸௨஌νϟϯωϧ͕࢖ΘΕΔ

Slide 84

Slide 84 text

Priority vs Importance • Priority…௨஌ͷ༏ઌ౓ • Importance…νϟϯωϧͷॏཁ౓ • ։ൃऀ͸ॳظ஋Λڭ͑Δ͚ͩͰɺ͋ͱͰϢʔ βʔ͕มߋՄೳ • ޓ׵ੑͷͨΊʹ྆ํઃఆ͠·͠ΐ͏

Slide 85

Slide 85 text

ϔουΞοϓ௨஌
 (API 21~)

Slide 86

Slide 86 text

ϔουΞοϓ • API 21Ҏ߱ • ΞϓϦʹ͔Ϳͤͯදࣔ͞ΕΔɺ༏ઌ౓ͷߴ͍௨஌ • දࣔϩδοΫ͕όʔδϣϯ͝ͱʹҧ͏ • API 21 ~ 25 • ௨஌ͷpriority • API 26~ • ௨஌νϟϯωϧͷઃఆ

Slide 87

Slide 87 text

ϔουΞοϓ

Slide 88

Slide 88 text

ϔουΞοϓ࣮૷ val notification = NotificationCompat.Builder(context, CHANNEL_ID_IMPORTANT) ... .setPriority(Notification.PRIORITY_HIGH) .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification) API 26Ҏ߱ API 25ҎԼ

Slide 89

Slide 89 text

ϩοΫը໘௨஌ (API 21~)

Slide 90

Slide 90 text

ϩοΫը໘௨஌ • API 21Ҏ߱ • ϩοΫը໘ʹ௨஌Λදࣔ • ϓϥΠϕʔτͳ಺༰ΛӅ͢͜ͱ΋Մೳ • ୺຤ͷ௨஌ઃఆͷઃఆ࣍ୈ

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

No content

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

PublicʢϩοΫը໘༻ʣ val publicNotification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) .setContentTitle("This is public title") .setContentText("This is public message") ... .build()

Slide 95

Slide 95 text

PrivateʢඇϩοΫ࣌༻ʣ val notification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) .setContentTitle("This is private title") .setContentText("This is private message") ... .setVisibility(NotificationCompat.VISIBILITY_PRIVATE) .setPublicVersion(publicNotification) .build() val nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager nm.notify(1, notification)

Slide 96

Slide 96 text

όϯυϧ௨஌

Slide 97

Slide 97 text

όϯυϧ௨஌ • εϚϗ͸API 24Ҏ߱ • ෳ਺ͷ௨஌Λ·ͱΊͯදࣔ͢Δػೳ • ϝʔϧɺϝοηϯδϟʔɺχϡʔεΞϓϦͰ සग़

Slide 98

Slide 98 text

όϯυϧ௨஌

Slide 99

Slide 99 text

όϯυϧ௨஌ͷ᠘ • WearͰAPI௥Ճ͞ΕͨͷͰɺεϚϗʗλϒ ϨοτͰ࢖͑Δͷ͸24͔Β • ࣮૷ʹ͸APIϨϕϧͷ෼ذඞཁ

Slide 100

Slide 100 text

αϚϦʔ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val summaryNotification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setGroupSummary(true) .setGroup(GROUP_KEY) .setAutoCancel(true) .build() nm.notify(1, summaryNotification) }

Slide 101

Slide 101 text

αϚϦʔ API 24Ҏ߱ͰͷΈදࣔ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val summaryNotification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setGroupSummary(true) .setGroup(GROUP_KEY) .setAutoCancel(true) .build() nm.notify(1, summaryNotification) }

Slide 102

Slide 102 text

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val summaryNotification = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) ... .setGroupSummary(true) .setGroup(GROUP_KEY) .setAutoCancel(true) .build() nm.notify(1, summaryNotification) } αϚϦʔ

Slide 103

Slide 103 text

ݸผͷ௨஌ // ֤௨஌͸લόʔδϣϯڞ௨Ͱग़͢ val notification1 = NotificationCompat.Builder(context, CHANNEL_ID_NORMAL) .setGroup(GROUP_KEY) .setContentTitle("This is title 1") .setContentText("This is message 1") ... .build() val notification2 = ... nm.notify(2, notification1) nm.notify(2, notification2)

Slide 104

Slide 104 text

ϝοηʔδͬΆ͍Style • Inbox style (API 16~) • Messaging style (API 24~) • όϯυϧ௨஌ (API 24~) • ݁ہͲΕΛ࢖͑͹͍͍ͷʁ

Slide 105

Slide 105 text

Inbox Style

Slide 106

Slide 106 text

Messaging Style

Slide 107

Slide 107 text

όϯυϧ௨஌

Slide 108

Slide 108 text

࢖͍෼͚ʢࢲݟʣ • ݪଇόϯυϧ௨஌Λ࢖͏ • API 23ҎԼͰ͸ɺΧελϜϏϡʔΛ࣮૷͢Δ • Ͱ΋໘౗ͳΒී௨ͷ௨஌Ͱ΋OK?

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

௨஌Λ࣮૷͢Δ্Ͱͷ
 ϙΠϯτ

Slide 111

Slide 111 text

No content

Slide 112

Slide 112 text

υΩϡϝϯτ • ඞͣӳޠ൛ΛݟΔ͜ͱ • ޓ׵ੑ·Ͱ͸ॻ͍ͯ͘Εͯͳ͍ͷͰɺͪΌΜ ͱओཁͳόʔδϣϯͰಈ࡞֬ೝ͠·͠ΐ͏

Slide 113

Slide 113 text

ಈ࡞֬ೝ • αϙʔτͷ্ݶͱԼݶ͸ඞͣ֬ೝ • ϚςϦΞϧσβΠϯ͔ͭNougatલ΋஫ҙ • ୺຤ϝʔΧʔʹΑͬͯ͸ΧελϚΠζ͞Ε͍ͯ ΔͷͰɺNexus/Pixelਪ঑ • ྫ: Huawei

Slide 114

Slide 114 text

No content

Slide 115

Slide 115 text

No content

Slide 116

Slide 116 text

·ͱΊ

Slide 117

Slide 117 text

·ͱΊ • ௨஌APIͷྺ࢙ΛৼΓฦΓɺ֤ػೳΛޓ׵ੑΛ ߟྀ࣮ͯ͠૷͢Δࡍͷ஫ҙ఺Λ঺հͨ͠ • ͪΌΜͱυΩϡϝϯτͱಡΜͰಈ࡞֬ೝ͠ɺ Ϣʔβʔʹͱͬͯշదͳ௨஌Λ࣮૷͠Α͏

Slide 118

Slide 118 text

αϯϓϧίʔυ • ࠓ೔ͷ࣮૷͸GitHubʹ্͛·ͨ͠ • https://github.com/kobakei/ AndroidNotificationShowcase

Slide 119

Slide 119 text

and one more thing…

Slide 120

Slide 120 text

ͳΔ΄ͲɺAndroid 4ܥ
 αϙʔτ͍ͯ͘͠ͷਏ͍ͧ

Slide 121

Slide 121 text

Kyashͷbuild.gradle

Slide 122

Slide 122 text

No content

Slide 123

Slide 123 text

No content

Slide 124

Slide 124 text

We are hiring!!!

Slide 125

Slide 125 text

Thanks!