質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

1回答

1338閲覧

firebaseでリッチプッシュを送りたい

falconHM

総合スコア6

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/06/07 12:26

Firebaseを使ってリッチプッシュを送りたいと思っています。
テストプロジェクトでPHPからPUSH送信して受信までは出来ているのですが、
リッチプッシュの確認が出来ません。

下記を参考にNotificationService.swiftを作成したのですがうまくいきません。。。
Firebase Cloud Messagingで画像つきプッシュ通知を送信する

下記ソースですが、これでPUSH送信しても通常のPUSHが受信される状態です。
NotificationService.swiftとAppDelegate.swiftの挙動に関してそこまで詳しくないので、
何か足りないものがあるのかと思うのですが。。。
それともPHP側で送る内容に不備があるのか不明な状況です。。。
※PHPファイルに「mutable_content」と「image_url」が多いのは色々試していたためですm(_ _)m

NotificationService.swift

import UserNotifications class NotificationService: UNNotificationServiceExtension { let imageKey = AnyHashable("gcm.notification.image_url") 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) } if let imageUrl = request.content.userInfo[imageKey] as? String { let session = URLSession(configuration: URLSessionConfiguration.default) let task = session.dataTask(with: URL(string: imageUrl)!, completionHandler: { [weak self] (data, response, error) in if let data = data { do { let writePath = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("push.png") try data.write(to: writePath) guard let wself = self else { return } if let bestAttemptContent = wself.bestAttemptContent { let attachment = try UNNotificationAttachment(identifier: "nnsnodnb_demo", url: writePath, options: nil) bestAttemptContent.attachments = [attachment] contentHandler(bestAttemptContent) } } catch let error as NSError { print(error.localizedDescription) guard let wself = self else { return } if let bestAttemptContent = wself.bestAttemptContent { contentHandler(bestAttemptContent) } } } else if let error = error { print(error.localizedDescription) } }) task.resume() } else { if let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } } override func serviceExtensionTimeWillExpire() { modified content, otherwise the original push payload will be used. if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } }

PHP側の処理

$api_key = 'APIKEY'; $base_url = "https://fcm.googleapis.com/fcm/send"; $title = 'test'; $body = 'body'; $token_key = 'TOKENKEY'; $data = array( "registration_ids" => $token_key ,"mutable_content" => True ,"priority" => "high" ,"notification" => array( "title" => $title ,"body" => $body ,"badge" => 1 ,"mutable_content" => True ,"image_url" => "画像URL" ) ,"data" => array( "title" => $title ,"body" => $body ,"badge" => 1 ,"image_url" => "画像URL" ,"mutable_content" => True ) ); $header = array( "Content-Type:application/json" ,"Authorization:key=".$api_key ); $context = stream_context_create(array( 'http' => array( 'method' => 'POST' ,'header' => implode("\r\n",$header) ,'content'=> json_encode($data) ) )); file_get_contents($base_url,false,$context);

AppDelegate.swift

import UIKit import UserNotifications import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? let gcmMessageIDKey = "gcm.message_id" func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() Messaging.messaging().delegate = self if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: {_, _ in }) UIApplication.shared.registerForRemoteNotifications() } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() return true } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) { if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: (messageID)") } } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print("Unable to register for remote notifications: (error.localizedDescription)") } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: (messageID)") } completionHandler(UIBackgroundFetchResult.newData) } // ~~~~ func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { print("APNs token retrieved: (deviceToken)") let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined() print("deviceToken!! = (token)") } } // [START ios_10_message_handling] @available(iOS 10, *) extension AppDelegate : UNUserNotificationCenterDelegate { // Receive displayed notifications for iOS 10 devices. func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo // With swizzling disabled you must let Messaging know about the message, for Analytics // Messaging.messaging().appDidReceiveMessage(userInfo) // Print message ID. if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: (messageID)") } // Print full message. print(userInfo) // Change this to your preferred presentation option completionHandler([]) } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo // Print message ID. if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: (messageID)") } // Print full message. print(userInfo) completionHandler() } } // [END ios_10_message_handling] extension AppDelegate : MessagingDelegate { // [START refresh_token] func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) { print("Firebase registration token: (fcmToken)") // TODO: If necessary send token to application server. // Note: This callback is fired at each app startup and whenever a new token is generated. } // [END refresh_token] // [START ios_10_data_message] // Receive data messages on iOS 10+ directly from FCM (bypassing APNs) when the app is in the foreground. // To enable direct data messages, you can set Messaging.messaging().shouldEstablishDirectChannel to true. func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) { print("Received data message: (remoteMessage.appData)") } // [END ios_10_data_message] }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

まず、NotificationServiceExtentionが呼ばれているかを確認してください。

呼ばれている場合は、何も手を加えていない初期状態のNotificationServiceで、
(bestAttemptContent.title) →(bestAttemptContent.title) [modified]
と、プッシュ通知のタイトル末尾に[modified]が表示されているはずです。

プッシュ通知自体が受信できているとのことなので、[modified]が表示されていないのであれば、プロビジョニングの設定ができていないのではないかと思います。App本体と別に、プロビジョニングプロファイルの設定を行う必要があります。

その場合、Developerサイトにて以下の作業をしてください。
0. App ID取得
※App ServicesでPush Notificationsをオンにしなくていいです
※Bundle IDはアプリ本体の下の階層になるように設定してください
(例)[本体]com.hogehoge.Fuga -> [今回]com.hogehoge.Fuga.NotificationSerivce
0. そのApp IDでProvisioning Profilesを取得
0. ダウンロードしたファイルをダブルクリックで登録
0. XcodeでNotificationSerivceのターゲットを選んで、プロビジョニングファイルを設定する

これでNotificationServiceExtentionが呼ばれるようになったら、「mutable_content」と「image_url」の話に移ります。

実際にPHPで試してないのでわかりませんが、
payload > data 内に

data

1“image”=> ”https://sample.com/image/sample.png”,

payload > notification内に

notification

1"mutable_content"=>true,

と記載すればいけるかと思います。

AppDelegateのdidReceiveRemoteNotification内で、print(userInfo)をしたときに、Xcodeのログで

[AnyHashable("image"): https://sample.com/image/sample.png, AnyHashable("aps"): { alert = { body = “bodyが入る”; title = “titleが入る”; }; "mutable-content" = 1; }]]

という感じで表示されていたら成功です(今回関係ない項目は割愛しています)。

NotificationServiceのコードについては、質問に書いていただいた参考リンクの中で、

if let imageUrl = request.content.userInfo[imageKey] as? String

としている箇所があると思いますが、今回私が回答した構成ですと、

if let imageUrl = request.content.userInfo[“image”] as? String

にする必要があります。あとはリンク先のコードままでいけるように思います。

投稿2018/06/19 09:58

taka_jun

総合スコア160

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

falconHM

2018/06/23 02:59

大変ご丁寧に回答頂きありがとうございます! プロビジョニングの設定必要なんですね!! (Developerサイトの説明まで!泣) これは知りませんでした。。。 PUSH通知の確認方法までご丁寧にありがとうございます! 早速確認してみようと思います!
falconHM

2018/06/25 10:58

確認して見ました! まず、NotificationServiceを通っていることの確認が出来ました! ですが、どうやら下記の部分でこけてしまっているようです。 let task = session.dataTask(with: URL(string: imageUrl)!, completionHandler: { [weak self] (data, response, error) in imageUrlにもきちんとした値が入っているのですが。。。 何か良い確認方法はないでしょうか?
taka_jun

2018/06/26 00:09

URLは受け取れたとのことで、あと少しですね! やはり元のコードを見る限り、useInfoのソースを変えるだけで通るように見えます。 ちょっとこれだけでは分からないので、XcodeのログやdataTask関数でエラーをprintしている箇所などを見て対処してください。 アップロード完了前にPUSHが届いたりはしてないですよね?
falconHM

2018/07/03 02:00

ご連絡遅くなりました!ちょっと別件作業がとても忙しくてみれていない状況です。。。「アップロード完了前にPUSHが届いたりはしてないですよね?」のアップロード完了とは端末に画像をアップロードする。という認識で合っていますでしょうか?それならばアップロードの処理に到達(if文を通っていない)していない状況になります! 来週には時間作れると思うのでログを出しながらじっくり追ってみます!
falconHM

2018/07/03 10:17 編集

少し時間が出来たので確認してみました! ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー let task = session.dataTask(with: URL(string: imageUrl)!, completionHandler: { [weak self] (data, response, error) in ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー こちらが通らない状況です。 imageUrlにはきちんとセットした画像のURLが届いていますし、 試しにimageUrlをNotificationService.swift内でURL上書きしても通らない状況です。 ViewController.swiftであれば問題なく通るんですが、もしかして何かXcodeで設定しないとNotificationService.swiftではHTTP通信出来ない等ありますでしょうか???
falconHM

2018/07/03 10:43

NotificationService.swift内のprint()ログを表示させる方法ってありますでしょうか。。。?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問