FlutterFlowでonesignalを用いてpush通知を実装した際のiOSビルドエラーを解消した時の話

に公開

導入

こんにちは。暇なのでタイトルについて書きます。

FlutterFlowではonesignalが標準でサポートされていますが、メールやSMS通知しかサポートされていません。また最近ではsupabaseをメインのデータベースとして用いて開発するプロジェクトが多々あります。FlutterFlow標準の通知機能ではfirebaseに接続するのが必須でそれだけのために接続するのは好ましくありません。そこでsupabaseのみを用いてonesignalで通知機能を実装しiOSでビルドしようとしたらエラーがわんさか出ました。FlutterFlowも結局はFlutterのコードなので、頑張れば出来ると思っていたらビルドエラーの解消には9時間を費やしました。3,4ヶ月前の話なので今動くかどうかは保証はできませんしバグも解消されているかもしれません。自動化スクリプトも書いたのですが、それは数週間前は動いていました。下の手順は半分ぐらい公式のドキュメントの手順も含まれています。今見たらonesignal公式のFlutterのドキュメントがアップデートされてiOSのビルドエラーについて触れていました。 大体そこに書かれているエラーがでていたのですが、build phaseに関しては自分のやり方と違ったのでドキュメントを参照したほうがいいかもしれません。 onesignal documentation

手順

1.FlutterFlowのコードをダウンロードする
2. flutter pub add collection:^1.19.0 をする(注意:3,4ヶ月前の依存関係なので今いらないかも)
3. /ios/Runner.xcworkspaceを開く
4. 右端にあるproject document内のXcodeのバージョンを16.0(もしくは最新のやつ)にする
5.Files→New→Targetからnotification service extensionをOneSignalNotificationServiceExtensionの名前で追加する
6.出てきたポップアップはDon’t activateをクリック
7.Targets→Runner→BuildPhase→Thin Binaryを最後に移動する(ここだけ公式と違う)
8.Targets→OneSignalNotificationServiceExtension→Minimum Deploymentsを14.0.0 or Targets→Runner→Minimum Deploymentsと同じにする
9.Targets→Runner→Signing & Capabilities→teamを自分のチームに設定する
10.Targets→OneSignalNotificationServiceExtension→Signing & Capabilities→teamも自分のチームにする
11.Targets→Runner→Signing & Capabilities→+Capability→push notificationを追加する
12.Targets→Runner→Signing & Capabilities→+Capability→Background Modesを追加してremote notificationsにチェックする
13.Targets→Runner→Signing & Capabilities→+Capability→App Groupsをgroup.(budle id).onesignalの名前で追加する(bundle idは自身のアプリのバンドルID)
14.Targets→OneSignalNotificationServalliceExtension→Signing & Capabilities→+Capability→App Groupsでも13と同じことをする
15.Pods→Podfileの最後にこれをコピペ

target 'OneSignalNotificationServiceExtension' do
  use_frameworks! :linkage => :static
  pod 'OneSignalXCFramework', '>= 5.0.0', '< 6.0'
end
  1. iOSフォルダーに移動してpod installをする
  2. 左端→Runner→OneSignalNotificationServiceExtensionフォルダのNotificationService.swiftを下のコードに置き換える
NotificationService.swift
import UserNotifications

import OneSignalExtension

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var receivedRequest: UNNotificationRequest!
    var bestAttemptContent: UNMutableNotificationContent?
    
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.receivedRequest = request
        self.contentHandler = contentHandler
        self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            /* DEBUGGING: Uncomment the 2 lines below to check this extension is executing
                          Note, this extension only runs when mutable-content is set
                          Setting an attachment or action buttons automatically adds this */
            // print("Running NotificationServiceExtension")
            // bestAttemptContent.body = "[Modified] " + bestAttemptContent.body
            
            OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler)
        }
    }
    
    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 {
            OneSignalExtension.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent)
            contentHandler(bestAttemptContent)
        }
    }  
}
  1. これで他にエラーがなかったらビルドが通るはずです。

最後に

この記事が役に立ったと思ったら僕が開発に参加しているプロジェクトの@Fillitをインストールしてフィードバックをください。案件も下さい。

Discussion