SlideShare a Scribd company logo
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Feb 10, 2017
Akifumi Fukaya
Development Dept. 1
IP Platform Div.
DeNA Co., Ltd.
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Feb 10, 2017
Akifumi Fukaya
Development Dept. 1
IP Platform Div.
DeNA Co., Ltd.
マンガボックス
iOS10プッシュ通知
導入事例
1
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
自己紹介
• 深谷 哲史(ふかや あきふみ)
• 2014年度 新卒入社
• IPプラットフォーム事業部開発一部 所属
• マンガボックス
• iOS/Androidエンジニア
2
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
背景
• 2016年9月にiOS10がリリース
• マンガボックスでは、新しい技術を積極的に導入しよう
と実装を検討
• iOS10の新機能
• User Notifications
• iMessage App
• Siri Kit
3
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
背景
• 2016年9月にiOS10がリリース
• マンガボックスでは、新しい技術を積極的に導入しよう
と実装を検討
• iOS10の新機能
• User Notifications
• iMessage App
• Siri Kit
4
マンガボックスと相性が良さそう!
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
iOS10の通知
Advanced Notifications - WWDC 2016より引用
https://developer.apple.com/videos/play/wwdc2016/708/
5
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
WWDC 2016 ビデオ
https://developer.apple.com/videos/play/wwdc2016/707/
https://developer.apple.com/videos/play/wwdc2016/708/
6
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
マンガボックスでの導入事例
7
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
マンガボックスでの導入事例
8
Episode
Notification
Content
Extension
Notification Service
Extension
Comics
Notification
Content
Extension
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Notification Service Extensionの導入
• 通知表示前にペイロードを受け取り、表示内容
を操作できる
• アタッチメント画像のダウンロードと表示
• 暗号化文字列の復号化
9
APNs
Payload
Notification Service
Extension
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Notification Service Extensionの導入
10
APNs
Payload
Notification Service
Extension
{
"aps": {
"alert": {},
"mutable-content": 1
},
"attachment_image_url": "https://example.com/photo.jpg"
}
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Notification Service Extensionの追加
11
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
NotificationService.swift
12
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping
(UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent
= (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload
will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
NotificationService.swift
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping
(UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent
= (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "(bestAttemptContent.title) [modified]"
contentHandler(bestAttemptContent)
}
}
override func serviceExtensionTimeWillExpire() {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload
will be used.
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Notification Contentの導入
14
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
Notification Contentの追加
15
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
NotificationViewController.swift
import UIKit
import UserNotifications
import UserNotificationsUI
class NotificationViewController: UIViewController, UNNotificationContentExtension {
@IBOutlet var label: UILabel?
override func viewDidLoad() {
super.viewDidLoad()
// Do any required interface initialization here.
}
func didReceive(_ notification: UNNotification) {
self.label?.text = notification.request.content.body
}
}
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
MainInterface.storyboard
17
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
ハマった点の紹介
• アタッチメント画像がクリッピングされてしまう
• NotificationService#didReceive(_:withContentHandler:) で時間の
かかる処理を実行すると、Extensionの正常終了されてしまう
• mutable-content:1を含むペイロードのプッシュ通知が届かない
端末が出現
• Content Extensionの中身が真っ白
18
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
ハマった点の紹介
• アタッチメント画像がクリッピングされてしまう
• NotificationService#didReceive(_:withContentHandler:) で時間の
かかる処理を実行すると、Extensionの正常終了されてしまう
• mutable-content:1を含むペイロードのプッシュ通知が届かない
端末が出現
• Content Extensionの中身が真っ白
19
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
アタッチメント画像がクリッピングされてしまう
20
APNs
Payload
Notification Service
Extension
送信元画像 表示画像
クリッピングされてしまう
※ iOS 10.0で検証
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
アタッチメント画像がクリッピングされてしまう
let attachment = try UNNotificationAttachment(identifier: "image",
url: path,
options: nil)
bestAttemptContent.attachments = [attachment]
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
アタッチメント画像がクリッピングされてしまう
22
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
アタッチメント画像がクリッピングされてしまう
23
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
アタッチメント画像がクリッピングされてしまう
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
let dicRep = rect.dictionaryRepresentation
let options =
[UNNotificationAttachmentOptionsThumbnailClippingRectKey:dicRep]
let attachment = try UNNotificationAttachment(identifier: "image",
url: path,
options: options)
bestAttemptContent.attachments = [attachment]
拡大できるが縮小はできない
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
アタッチメント画像がクリッピングされてしまう
25
iOS 10.0 iOS 10.2
iOS 10.2で直ってました!
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
ハマった点の紹介
• アタッチメント画像がクリッピングされてしまう
• NotificationService#didReceive(_:withContentHandler:) で時
間のかかる処理を実行すると、Extensionの正常終了されてし
まう
• mutable-content:1を含むペイロードのプッシュ通知が届かない
端末が出現
• Content Extensionの中身が真っ白
26
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
ハマった点の紹介
• アタッチメント画像がクリッピングされてしまう
• NotificationService#didReceive(_:withContentHandler:) で時間の
かかる処理を実行すると、Extensionの正常終了されてしまう
• mutable-content:1を含むペイロードのプッシュ通知が届かない
端末が出現
• Content Extensionの中身が真っ白
27
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
プッシュ通知が届かない端末が出現
28
マンガボックス
iOS10対応版 リリース
v2.9.1 v2.10.0
iOS 9 iOS 10
通知が届かないケース
9/12 9/14
iOS 10リリース
プッシュ通知が届かない!
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
プッシュ通知が届かない端末が出現
29
v2.9.1 v2.10.0
iOS 9 iOS 10
9/12 9/14
通知が届くケース
iOS 10リリースマンガボックス
iOS10対応版 リリース
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
プッシュ通知が届かない端末が出現
30
v2.9.1 v2.10.0
iOS 9 iOS 10
通知が届かないケース
9/12 9/14 プッシュ通知が届かない!
iOS 9では通知エクステンションが
含まれていないのでは
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
プッシュ通知が届かない端末が出現
• 現象
• 届かないケース
• iOS 9で通知エクステンションを含むアプリをインストールし、iOS 10にアップ
デート後、プッシュ通知にmutable-content: 1が含まれる場合
• 届くケース
• iOS 10にOSをアップデート後、エクステンションを含むアプリをインストール
or アップデート
• mutable-content: 1をペイロードから削除
• 考えられる要因
• iOS 9でインストールされるアプリには、通知エクステンションが含ま
れていないのでは
31
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
ハマった点の紹介
• アタッチメント画像がクリッピングされてしまう
• NotificationService#didReceive(_:withContentHandler:) で時間の
かかる処理を実行すると、Extensionの正常終了されてしまう
• mutable-content:1を含むペイロードのプッシュ通知が届かない
端末が出現
• Content Extensionの中身が真っ白
32
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
プッシュ通知試してください!
33
Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved.
ありがとうございました
34

More Related Content

PPTX
DeNA private cloudのその後 #denatechcon
PDF
サービスの成長を支えるフロントエンド開発 #denatechcon
PPTX
アバター着せ替えアプリ開発におけるフロントエンド技術(Vue.js活用事例) #denatechcon
PPTX
DeNA内製ゲームエンジンの現状と目指す未来 #denatechcon
PDF
Unityアバターアプリ開発パッケージのご提案
PDF
Mobage/AndAppのSDK開発事例とSDKを作る際に知っておくべきこと #denatechcon
PPTX
DeNAtechcon_DeNAのセキュリティの取り組みと、スマートフォンセキュリティ(same-origin policy)
PPTX
AndApp開発における全て #denatechcon
DeNA private cloudのその後 #denatechcon
サービスの成長を支えるフロントエンド開発 #denatechcon
アバター着せ替えアプリ開発におけるフロントエンド技術(Vue.js活用事例) #denatechcon
DeNA内製ゲームエンジンの現状と目指す未来 #denatechcon
Unityアバターアプリ開発パッケージのご提案
Mobage/AndAppのSDK開発事例とSDKを作る際に知っておくべきこと #denatechcon
DeNAtechcon_DeNAのセキュリティの取り組みと、スマートフォンセキュリティ(same-origin policy)
AndApp開発における全て #denatechcon

What's hot (20)

PPTX
DeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組み
PDF
DeNAインフラの今とこれから - 今編 -
PDF
DeNAの動画配信サービスを支えるインフラの内部 #denatechcon
PDF
爆速でAndroidアプリを ビルドするための仕組み DeNA TechCon #denatechcon
PDF
B2B2Cなヘルスケアサービスの作り方
PDF
20180123 rancher meetupyokohama_minehiko_nohara
PPT
セキュリティ業務の内製とチームメンバー育成
PDF
DeNAのゲーム開発を支える技術 (クライアントサイド編)
PPTX
DebugHeadを使ったiOSアプリ開発手法 #denatechcon
PDF
DeNAオリジナル ゲーム専用プラットフォーム Sakashoについて
PDF
DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)
PDF
商用ミドルウェアのPuppet化で気を付けたい5つのこと
PPTX
エンプラに Kubernetes を 導入してみて分かった 4つの Lessons Learned
PDF
DeNA流cocos2d xとの付き合い方
PDF
チラシルiOSでの広告枠開発
PDF
これからの Microservices
PDF
iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜
PPTX
OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)
PPTX
DeNAが取り組む Software Engineer in Test
PDF
20170111 macnica networks-nohara_rancher_usecase
DeNA_Techcon2017_DeNAでのチート・脆弱性診断への取り組み
DeNAインフラの今とこれから - 今編 -
DeNAの動画配信サービスを支えるインフラの内部 #denatechcon
爆速でAndroidアプリを ビルドするための仕組み DeNA TechCon #denatechcon
B2B2Cなヘルスケアサービスの作り方
20180123 rancher meetupyokohama_minehiko_nohara
セキュリティ業務の内製とチームメンバー育成
DeNAのゲーム開発を支える技術 (クライアントサイド編)
DebugHeadを使ったiOSアプリ開発手法 #denatechcon
DeNAオリジナル ゲーム専用プラットフォーム Sakashoについて
DeNA の新しいネイティブ開発(パズル戦隊デナレンジャー)
商用ミドルウェアのPuppet化で気を付けたい5つのこと
エンプラに Kubernetes を 導入してみて分かった 4つの Lessons Learned
DeNA流cocos2d xとの付き合い方
チラシルiOSでの広告枠開発
これからの Microservices
iOSレガシーコード改善ガイド〜マンガボックス開発における事例〜
OpenJDKは使い物になるか?OpenJDKの実際と今後 (NTTデータ オープンソースDAY 2015 Autumn 講演資料)
DeNAが取り組む Software Engineer in Test
20170111 macnica networks-nohara_rancher_usecase
Ad

Viewers also liked (20)

PDF
自動運転に向けた取り組みと安全管理
PDF
リーンスタートアップにおける、実装やライブ配信基盤の共通化 村田紘司
PPTX
その後のDeNAのネイティブアプリ開発 #denatechcon
PDF
ログ分析で支えるゲームパラメータ設計 #denatechcon
PDF
DeNAのAIとは #denatechcon
PDF
HTTP/2の課題と将来
PPTX
DeNAのプログラミング教育の取り組み #denatechcon
PDF
TLS 1.3 と 0-RTT のこわ〜い話
PPTX
強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon
PPTX
DeNAのゲームを支えるプラットフォーム Sakasho #denatechcon
PDF
Reorganizing Website Architecture for HTTP/2 and Beyond
PDF
深層学習による機械とのコミュニケーション
PDF
実世界の人工知能@DeNA TechCon 2017
PDF
Anyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechcon
PDF
DATADOG TIPS #1
PDF
SafetyNetを使ってゲームを守る #denatechcon
PDF
マイクロサービスっぽい感じの話
PPTX
はじめての datadog
PDF
ボケてが300万DL到達までに行ったグロースハックを少し紹介
PPTX
【初心者向け】Go言語勉強会資料
自動運転に向けた取り組みと安全管理
リーンスタートアップにおける、実装やライブ配信基盤の共通化 村田紘司
その後のDeNAのネイティブアプリ開発 #denatechcon
ログ分析で支えるゲームパラメータ設計 #denatechcon
DeNAのAIとは #denatechcon
HTTP/2の課題と将来
DeNAのプログラミング教育の取り組み #denatechcon
TLS 1.3 と 0-RTT のこわ〜い話
強化学習を利用した自律型GameAIの取り組み ~高速自動プレイによるステージ設計支援~ #denatechcon
DeNAのゲームを支えるプラットフォーム Sakasho #denatechcon
Reorganizing Website Architecture for HTTP/2 and Beyond
深層学習による機械とのコミュニケーション
実世界の人工知能@DeNA TechCon 2017
Anyca(エニカ)のC2Cビジネスを支えるシステムと運用 #denatechcon
DATADOG TIPS #1
SafetyNetを使ってゲームを守る #denatechcon
マイクロサービスっぽい感じの話
はじめての datadog
ボケてが300万DL到達までに行ったグロースハックを少し紹介
【初心者向け】Go言語勉強会資料
Ad

Similar to マンガボックスのiOS10プッシュ通知導入事例 (20)

PDF
[db analytics showcase Sapporo 2017] B27:世界最速のAnalytic DBはHadoopの夢を見るか by 株式会...
PPT
Titanium Mobile
PPTX
Reactor によるデータインジェスチョン
PDF
2015 0807 ConoHa I am the bone of the OpenStack API CLI tool
PDF
Deno を aws fargate で動かす
PDF
Aerospike deep dive LDTs
PDF
plusbenlly meetiup how-to-use
PDF
20180313 Amazon Container Services アップデート
PDF
[db tech showcase Tokyo 2017] C25: 世界最速のAnalytic DBがHadoopとタッグを組んだ! ~スケールアウト検...
PDF
【18-C-4】Google App Engine - 無限の彼方へ
ODP
BPStudy #40 - Google Appengine 1.4.0
PDF
半日でわかる コンテナー技術 (入門編)
PDF
20180613 AWS Black Belt Online Seminar AWS Cloud9 入門
PDF
[Cloud OnAir] 【Anthos 演習】 解説を聞きながら Anthos を体験しよう 2020年11月5日 放送
PDF
Airflowを広告データのワークフローエンジンとして運用してみた話
PDF
Spring Boot on Kubernetes : Yahoo!ズバトク事例 #jjug_ccc
PDF
Deno の node 互換モードと ソケット
PDF
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
PPTX
fastlane x iOSアプリのCI
PPTX
20181228 ncf to_azure_batch
[db analytics showcase Sapporo 2017] B27:世界最速のAnalytic DBはHadoopの夢を見るか by 株式会...
Titanium Mobile
Reactor によるデータインジェスチョン
2015 0807 ConoHa I am the bone of the OpenStack API CLI tool
Deno を aws fargate で動かす
Aerospike deep dive LDTs
plusbenlly meetiup how-to-use
20180313 Amazon Container Services アップデート
[db tech showcase Tokyo 2017] C25: 世界最速のAnalytic DBがHadoopとタッグを組んだ! ~スケールアウト検...
【18-C-4】Google App Engine - 無限の彼方へ
BPStudy #40 - Google Appengine 1.4.0
半日でわかる コンテナー技術 (入門編)
20180613 AWS Black Belt Online Seminar AWS Cloud9 入門
[Cloud OnAir] 【Anthos 演習】 解説を聞きながら Anthos を体験しよう 2020年11月5日 放送
Airflowを広告データのワークフローエンジンとして運用してみた話
Spring Boot on Kubernetes : Yahoo!ズバトク事例 #jjug_ccc
Deno の node 互換モードと ソケット
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
fastlane x iOSアプリのCI
20181228 ncf to_azure_batch

マンガボックスのiOS10プッシュ通知導入事例

  • 1. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Feb 10, 2017 Akifumi Fukaya Development Dept. 1 IP Platform Div. DeNA Co., Ltd. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Feb 10, 2017 Akifumi Fukaya Development Dept. 1 IP Platform Div. DeNA Co., Ltd. マンガボックス iOS10プッシュ通知 導入事例 1
  • 2. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 自己紹介 • 深谷 哲史(ふかや あきふみ) • 2014年度 新卒入社 • IPプラットフォーム事業部開発一部 所属 • マンガボックス • iOS/Androidエンジニア 2
  • 3. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 背景 • 2016年9月にiOS10がリリース • マンガボックスでは、新しい技術を積極的に導入しよう と実装を検討 • iOS10の新機能 • User Notifications • iMessage App • Siri Kit 3
  • 4. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 背景 • 2016年9月にiOS10がリリース • マンガボックスでは、新しい技術を積極的に導入しよう と実装を検討 • iOS10の新機能 • User Notifications • iMessage App • Siri Kit 4 マンガボックスと相性が良さそう!
  • 5. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. iOS10の通知 Advanced Notifications - WWDC 2016より引用 https://developer.apple.com/videos/play/wwdc2016/708/ 5
  • 6. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. WWDC 2016 ビデオ https://developer.apple.com/videos/play/wwdc2016/707/ https://developer.apple.com/videos/play/wwdc2016/708/ 6
  • 7. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. マンガボックスでの導入事例 7
  • 8. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. マンガボックスでの導入事例 8 Episode Notification Content Extension Notification Service Extension Comics Notification Content Extension
  • 9. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Notification Service Extensionの導入 • 通知表示前にペイロードを受け取り、表示内容 を操作できる • アタッチメント画像のダウンロードと表示 • 暗号化文字列の復号化 9 APNs Payload Notification Service Extension
  • 10. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Notification Service Extensionの導入 10 APNs Payload Notification Service Extension { "aps": { "alert": {}, "mutable-content": 1 }, "attachment_image_url": "https://example.com/photo.jpg" }
  • 11. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Notification Service Extensionの追加 11
  • 12. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. NotificationService.swift 12 class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) if let bestAttemptContent = bestAttemptContent { // Modify the notification content here... bestAttemptContent.title = "(bestAttemptContent.title) [modified]" contentHandler(bestAttemptContent) } } override func serviceExtensionTimeWillExpire() { // Called just before the extension will be terminated by the system. // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } }
  • 13. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. NotificationService.swift class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) if let bestAttemptContent = bestAttemptContent { // Modify the notification content here... bestAttemptContent.title = "(bestAttemptContent.title) [modified]" contentHandler(bestAttemptContent) } } override func serviceExtensionTimeWillExpire() { // Called just before the extension will be terminated by the system. // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } }
  • 14. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Notification Contentの導入 14
  • 15. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. Notification Contentの追加 15
  • 16. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. NotificationViewController.swift import UIKit import UserNotifications import UserNotificationsUI class NotificationViewController: UIViewController, UNNotificationContentExtension { @IBOutlet var label: UILabel? override func viewDidLoad() { super.viewDidLoad() // Do any required interface initialization here. } func didReceive(_ notification: UNNotification) { self.label?.text = notification.request.content.body } }
  • 17. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. MainInterface.storyboard 17
  • 18. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ハマった点の紹介 • アタッチメント画像がクリッピングされてしまう • NotificationService#didReceive(_:withContentHandler:) で時間の かかる処理を実行すると、Extensionの正常終了されてしまう • mutable-content:1を含むペイロードのプッシュ通知が届かない 端末が出現 • Content Extensionの中身が真っ白 18
  • 19. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ハマった点の紹介 • アタッチメント画像がクリッピングされてしまう • NotificationService#didReceive(_:withContentHandler:) で時間の かかる処理を実行すると、Extensionの正常終了されてしまう • mutable-content:1を含むペイロードのプッシュ通知が届かない 端末が出現 • Content Extensionの中身が真っ白 19
  • 20. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. アタッチメント画像がクリッピングされてしまう 20 APNs Payload Notification Service Extension 送信元画像 表示画像 クリッピングされてしまう ※ iOS 10.0で検証
  • 21. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. アタッチメント画像がクリッピングされてしまう let attachment = try UNNotificationAttachment(identifier: "image", url: path, options: nil) bestAttemptContent.attachments = [attachment]
  • 22. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. アタッチメント画像がクリッピングされてしまう 22
  • 23. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. アタッチメント画像がクリッピングされてしまう 23
  • 24. Copyright (C) DeNA Co.,Ltd. All Rights Reserved. アタッチメント画像がクリッピングされてしまう let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0) let dicRep = rect.dictionaryRepresentation let options = [UNNotificationAttachmentOptionsThumbnailClippingRectKey:dicRep] let attachment = try UNNotificationAttachment(identifier: "image", url: path, options: options) bestAttemptContent.attachments = [attachment] 拡大できるが縮小はできない
  • 25. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. アタッチメント画像がクリッピングされてしまう 25 iOS 10.0 iOS 10.2 iOS 10.2で直ってました!
  • 26. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ハマった点の紹介 • アタッチメント画像がクリッピングされてしまう • NotificationService#didReceive(_:withContentHandler:) で時 間のかかる処理を実行すると、Extensionの正常終了されてし まう • mutable-content:1を含むペイロードのプッシュ通知が届かない 端末が出現 • Content Extensionの中身が真っ白 26
  • 27. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ハマった点の紹介 • アタッチメント画像がクリッピングされてしまう • NotificationService#didReceive(_:withContentHandler:) で時間の かかる処理を実行すると、Extensionの正常終了されてしまう • mutable-content:1を含むペイロードのプッシュ通知が届かない 端末が出現 • Content Extensionの中身が真っ白 27
  • 28. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. プッシュ通知が届かない端末が出現 28 マンガボックス iOS10対応版 リリース v2.9.1 v2.10.0 iOS 9 iOS 10 通知が届かないケース 9/12 9/14 iOS 10リリース プッシュ通知が届かない!
  • 29. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. プッシュ通知が届かない端末が出現 29 v2.9.1 v2.10.0 iOS 9 iOS 10 9/12 9/14 通知が届くケース iOS 10リリースマンガボックス iOS10対応版 リリース
  • 30. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. プッシュ通知が届かない端末が出現 30 v2.9.1 v2.10.0 iOS 9 iOS 10 通知が届かないケース 9/12 9/14 プッシュ通知が届かない! iOS 9では通知エクステンションが 含まれていないのでは
  • 31. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. プッシュ通知が届かない端末が出現 • 現象 • 届かないケース • iOS 9で通知エクステンションを含むアプリをインストールし、iOS 10にアップ デート後、プッシュ通知にmutable-content: 1が含まれる場合 • 届くケース • iOS 10にOSをアップデート後、エクステンションを含むアプリをインストール or アップデート • mutable-content: 1をペイロードから削除 • 考えられる要因 • iOS 9でインストールされるアプリには、通知エクステンションが含ま れていないのでは 31
  • 32. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ハマった点の紹介 • アタッチメント画像がクリッピングされてしまう • NotificationService#didReceive(_:withContentHandler:) で時間の かかる処理を実行すると、Extensionの正常終了されてしまう • mutable-content:1を含むペイロードのプッシュ通知が届かない 端末が出現 • Content Extensionの中身が真っ白 32
  • 33. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. プッシュ通知試してください! 33
  • 34. Copyright (C) DeNA Co.,Ltd. All Rights Reserved.Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ありがとうございました 34

Editor's Notes

  • #4: iOS10がリリースされた マンガボックスチームもボトムアップで、新しい機能を実装しようとなった。 iOS10から入った、リッチな表現ができるプッシュ通知が、マンガボックスと一番相性が良いのではないかと思い、実装をすることにしました。
  • #5: iOS10がリリースされた マンガボックスチームもボトムアップで、新しい機能を実装しようとなった。 iOS10から入った、リッチな表現ができるプッシュ通知が、マンガボックスと一番相性が良いのではないかと思い、実装をすることにしました。
  • #7: 詳しくはWWDC2016のこの2つの試料を参照していただければと思います。
  • #8: マンガボックスでの導入事例ですが、 プッシュ通知をスライドの画像のそうに表示するようにしました。 3つのパターンの導入を行いました。 左側の画像は、通常通りのアタッチメント画像を付けるもの。 真ん中の画像は、その日の連載作品の1ページ目を表示するもの。 右側の画像は、その日の無料コミックスを表示するようになっています。
  • #9: 構成ですが、アプリ本体に3つのエクステンションが付属する形です。 Notification Service Extensionでアタッチメント画像を付与。 連載作品通知用と無料コミックス通知用で2つのNotification Content Extensionを作成しました。 簡単に、Notification Service ExtensionとNotification Content Extensionの説明をしようと思います。
  • #10: ペイロードを表示前に受け取り、表示をハンドリングできる アタッチメント画像の取得と表示 暗号化文字列の復号化
  • #11: payloadに mutable-content: 1 を入れることで、通知を表示する前にハンドリングすることができます。
  • #13: mutable-content: 1を含むペイロードを端末が受信すると、通知を表示する前にこのクラスのdidReceive()メソッドが呼ばれます。 didReceive()メソッド内で処理を行うことで、通知を表示する前に処理を行うことができます。
  • #14: この部分が主な処理を行う部分です。 ここの部分の実装を変えることで、プッシュ通知に表示する内容を変えることができます。
  • #15: Notification Contentエクステンションは、自由なUIでプッシュ通知の情報を表示することができます。 マンガボックスでは、2種類のエクステンションを追加しました。 左側は、その日の連載マンガの1ページ目を表示するエクステンション。 右側は、その日の無料コミックスをお知らせするエクステンション。 としました。
  • #17: 普通のViewControllerとStoryboard同様に、ここをカスタマイズすることによって、通知を開いた際の画面をカスタマイズできます
  • #18: 普通のViewControllerとStoryboard同様に、ここをカスタマイズすることによって、通知を開いた際の画面をカスタマイズできます
  • #19: ここから今回の発表のメインになるのですが、導入の際にハマった点を共有したいと思います。 今回4つハマった点を共有します。 一つずつ説明しようと思います。 当時iOS10.0を元に実装したので、iOS10.0のときの知見を共有します。 アタッチメント画像の中心がクリッピングされてしまう NotificationService#didReceive() で時間のかかる処理を実行すると、Extensionが正常終了されてしまう NotificationContentでジェスチャーのハンドリングができない プッシュ通知が届かない端末が出現
  • #20: ここから今回の発表のメインになるのですが、導入の際にハマった点を共有したいと思います。 今回4つハマった点を共有します。 一つずつ説明しようと思います。
  • #21: アタッチメント画像がクリッピングされてしまう デフォルトの状態で、UNNotificationAttachmentオブジェクトを作成するとクリッピングされてしまう。 UNNotificationAttachmentOptionsThumbnailClippingRectKey でクリッピングの範囲は指定できるが、画像全体を表示することができない。
  • #22: 画像データからUNNotificationAttachmentのインスタンスを作成し、attachmentsに追加することで通知に画像を追加することができます。 コードで言うと赤枠の中です。 しかし、この実装をするとアタッチメント画像が自動でクリッピングされてしまいます。 UNNotificationAttachmentのイニシャライザの引数のoptionsが気になったので、ドキュメントを見てみました。
  • #23: optionsにAttachment Attributesのリンクがあるので、さらに深掘ります。
  • #24: いくつかオプションの種類があります。その中に、 UNNotificationAttachmentOptionsThumbnailClippingRectKey というオプションがあります。 0.0 ~ 1.0までの値を持つCGRectをDictionary型に正規化した値を渡すというものです。
  • #25: パラメータを変えて試したものの画像全体を表示することはできなかった。 (iOS10 Betaの頃に、Appleのバグレポートを送ったのですが、未だにOpenのままなので) iOS 10.2で修正された
  • #27: こちらですが、先程のアタッチメント画像がクリッピングされてしまう問題を違う方法で解決できないかと考えました。 実際にはCoreGraphicsを使用して、画像データを縮小してからUNNotificationAttachmentに渡すという方法です。 結果ですが、元画像のサイズに小さければうまく表示されますが、元画像が大きい画像だと実行二時間がかかり、プロセスが正常終了されてしまいます。
  • #28: こちらですが、先程のアタッチメント画像がクリッピングされてしまう問題を違う方法で解決できないかと考えました。 実際にはCoreGraphicsを使用して、画像データを縮小してからUNNotificationAttachmentに渡すという方法です。 結果ですが、元画像のサイズに小さければうまく表示されますが、元画像が大きい画像だと実行二時間がかかり、プロセスが正常終了されてしまいます。
  • #29: マンガボックスは、GM版で申請を行い、iOS10対応アプリをiOS10が出る前にリリースしました。 9/12にアプリをリリースし、9/14にiOS10がリリースされました。 Payloadに、mutable-content: 1 を含む。NotificationServiceに対応したプッシュ通知の場合。 スライドのようなケースでプッシュ通知が届かない減少が発生しました。 なので、時系列はスライドのようになっています。 プッシュ通知が届かない端末が出現
  • #30: プッシュ通知が届かない端末が出現 Payloadに、mutable-content: 1 を含む。
  • #31: マンガボックスは、GM版で申請を行い、iOS10対応アプリをiOS10が出る前にリリースしました。 9/12にアプリをリリースし、9/14にiOS10がリリースされました。 Payloadに、mutable-content: 1 を含む。NotificationServiceに対応したプッシュ通知の場合。 スライドのようなケースでプッシュ通知が届かない減少が発生しました。 なので、時系列はスライドのようになっています。 プッシュ通知が届かない端末が出現
  • #33: マンガボックスにiOS10プッシュ通知を導入した際に、遭遇した問題点を共有させていただきました。 開発者のみなさまのためになれば良いなと思います。 いろいろな問題に直面しながら、iOS10プッシュ対応を行いました。 (新しい機能の実装は、時間が短い中で様々な問題点に遭遇しながら実装することにになりますが、新しい体験をユーザーに与えることができると思います。ぜひ、前のめりに調整していきましょう!)
  • #34: 是非マンガボックスをインストールして、試してみてもらえればと思います!