プッシュ通知(iOS)¶
プッシュ通知の設定¶
APNs証明書の設定 (iOS) を参照し、設定してください。
バッジを消す処理の実装¶
プッシュ通知作成フォームから 「バッジを表示する」をオン にして送信すると、プッシュ通知を受信したアプリのアイコンにバッジが自動で表示されます。
表示されたバッジを消すためには UIApplication
クラスの applicationIconBadgeNumber に0をセットする必要があります。アプリの仕様に合わせて任意のタイミングで applicationIconBadgeNumber
に0をセットしてください。
例えば、アプリがActiveになったタイミングでバッジを消す場合は UIApplicationDelegate
の applicationDidBecomeActive: で applicationIconBadgeNumber
に0をセットします。
// AppDelegate.m
@implementation AppDelegate
- (void)applicationDidBecomeActive:(UIApplication *)application
...
application.applicationIconBadgeNumber = 0;
...
// AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func applicationDidBecomeActive(_ application: UIApplication) {
...
application.applicationIconBadgeNumber = 0
...
注釈
「バッジを表示する」をオン にしたプッシュ通知を送信する場合は、必ずバッジクリア処理を実装してください。
デバイストークンをReproに送信¶
プッシュ通知の宛先を指定するためにデバイストークンをReproに送信します。
XcodeのCapabilitiesにてPush NotificationsをONにします。
次に下記のコードを追加してください。
// AppDelegate.m
#import <Repro/Repro.h>
#import <UserNotifications/UserNotifications.h>
...
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
[[UIApplication sharedApplication] registerForRemoteNotifications];
} else {
UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
return YES;
}
// AppDelegate.swift
import Repro
import UserNotifications
...
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
...
if #available (iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.sound, .alert, .badge], completionHandler: { (granted, error) in
})
application.registerForRemoteNotifications()
} else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
UIApplication.shared.registerForRemoteNotifications()
}
return true
}
// AppDelegate.m
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[Repro setPushDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
NSLog(@"Remote Notification Error: %@", error);
}
// AppDelegate.swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Repro.setPushDeviceToken(data: deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Remote Notification Error: \(error)")
}
デバイストークンの取得に成功した場合は application:didRegisterForRemoteNotificationsWithDeviceToken:
メソッドが呼び出されるので、その中でReproにデバイストークンを渡します。
デバイストークンの取得に失敗した場合は application:didFailToRegisterForRemoteNotificationsWithError:
メソッドが呼び出されるので、エラーの内容を見て適宜対処します。
以上の実装をした後にアプリを起動すると、下記のようなプッシュ通知の許諾ダイアログが表示されます。
このダイアログにて OK を選択すると application:didRegisterForRemoteNotificationsWithDeviceToken:
メソッドが呼び出され、Reproにデバイストークンが設定されます。
以上でプッシュ通知の受信準備は完了です。
オプション:リッチ通知の受信準備¶
iOS 10から画像や動画、音声ファイルなどを通知に利用することができるリッチ通知機能が追加されました。リッチ通知を受信するためには下記の手順が必要です。
Notification Service Extensionの作成¶
Xcodeのメニューの File -> New -> Target... をクリックします。
iOS -> Notification Service Extension -> Next をクリックします。
任意のProduct Nameを入力してFinishをクリックします。
下記のようなダイアログが出てきたら Activate
をクリックします。
Notification Service Extensionの実装¶
Notification Service Extension
に下記の記述をします。
#import <UserNotifications/UserNotifications.h>
...
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
NSDictionary *attachment = request.content.userInfo[@"rpr_attachment"];
if (!attachment) {
contentHandler(self.bestAttemptContent);
return;
}
NSString *urlStr = attachment[@"url"];
NSString *type = attachment[@"type"];
NSURL *url = [NSURL URLWithString:urlStr];
[[[NSURLSession sharedSession] downloadTaskWithURL:url
completionHandler:^(NSURL * _Nullable location,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
if (error) {
contentHandler(self.bestAttemptContent);
return;
}
NSString *fileName = [NSString stringWithFormat:@"%@.%@", [[NSUUID UUID]UUIDString], type];
NSURL *fileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:fileName]];
[[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:nil];
NSError *attachError = nil;
UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:@"IDENTIFIER" URL:fileURL options:nil error:&attachError];
if (!attachError) {
self.bestAttemptContent.attachments = @[attachment];
}
contentHandler(self.bestAttemptContent);
}] resume];
}
import UserNotifications
...
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 attachment = request.content.userInfo["rpr_attachment"] as? [String: String] {
if let urlString = attachment["url"], let fileURL = URL(string: urlString), let type = attachment["type"] {
URLSession.shared.downloadTask(with: fileURL) { (location, response, error) in
if let location = location {
let fileName = UUID().uuidString + "." + type
let tmpFile = "file://".appending(NSTemporaryDirectory()).appending(fileName)
let tmpUrl = URL(string: tmpFile)!
try? FileManager.default.moveItem(at: location, to: tmpUrl)
if let attachment = try? UNNotificationAttachment(identifier: "IDENTIFIER", url: tmpUrl, options: nil) {
self.bestAttemptContent?.attachments = [attachment]
}
}
contentHandler(self.bestAttemptContent!)
}.resume()
}
} else {
contentHandler(self.bestAttemptContent!)
}
}
上記の実装が終わったら、 プッシュ通知作成画面 をご覧ください。
オプション:ユニバーサルリンクを使用する¶
端末に表示されたプッシュ通知およびアプリ内メッセージに設定されたリンクをタップした際に実行されるURLには、ユニバーサルリンク(またはアプリリンクと呼ばれる)を指定することが可能です。 (簡単のため、以下ではこれらをユニバーサルリンクと呼びます)
アプリにてユニバーサルリンクの実行時の処理を追加するには、以下の通り実装を行う必要があります。 (ここで設定された動作は、プッシュ通知およびアプリ内メッセージ対し有効となります。)
ユニバーサルリンクのURLパターンを登録する¶
ユニバーサルリンクを利用するためには、まずユニバーサルリンクのURLのパターン(正規表現)を指定する必要があります。
この指定は、iOSの場合は AppDelegate
または .plist
ファイル、Androidの場合は Application
継承クラス または AndroidManifest.xml
ファイルのどちらか一方に記述することで行うことができます。
// AppDelegate.m
#import <Repro/Repro.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[Repro addOpenUrlFilterRegEx:@"https://example\\.com/page/"];
[Repro addOpenUrlFilterRegEx:@"your-domain\\.com/.+\?universal=true"];
...
}
// .plist file
/*
<dict>
<key>RPROpenUrlFilterRegExList</key>
<array>
<string>https://example\.com/page/</string>
<string>your-domain\.com/.+\?universal=true</string>
</array>
...
</dict>
*/
// MyApplication.java
import io.repro.android.Repro;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Repro.addOpenUrlFilterRegEx("https://example\\.com/page/");
Repro.addOpenUrlFilterRegEx("your-domain\\.com/.+\\?universal=true");
...
}
...
}
// AndroidManifest.xml
// To specify multiple URL patterns, enter them separated by commas.
<application>
...
<meta-data
android:name="io.repro.android.OpenUrlFilterRegExList"
android:value="https://example\\.com/page/;your-domain\\.com/.+\\?universal=true">
</meta-data>
</application>
// AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
Repro.add(openUrlFilterRegEx: "https://example\\.com/page/")
Repro.add(openUrlFilterRegEx: "your-domain\\.com/.+\\?universal=true")
...
}
// .plist file
/*
<dict>
<key>RPROpenUrlFilterRegExList</key>
<array>
<string>https://example\.com/page/</string>
<string>your-domain\.com/.+\?universal=true</string>
</array>
...
</dict>
*/
Please follow native iOS and Android instructions in order to add the filters
to the plist/AndroidManifest files or the main AppDelegate/Application classes.
Please follow native iOS and Android instructions in order to add the filters
to the plist/AndroidManifest files or the main AppDelegate/Application classes.
// YourAppNameScene.cpp
bool YourAppName::init() {
ReproCpp::addOpenUrlFilterRegEx("https://example\\.com/page/");
ReproCpp::addOpenUrlFilterRegEx("your-domain\\.com/.+\\?universal=true");
...
}
Please follow native iOS and Android instructions in order to add the filters
to the plist/AndroidManifest files or the main AppDelegate/Application classes.
Please follow native iOS and Android instructions in order to add the filters
to the plist/AndroidManifest files or the main AppDelegate/Application classes.
ユニバーサルリンク実行時の処理を登録する¶
次に、ユニバーサルリンクが実行された際に動作するコールバック処理を実装します。 処理内には、例えばURLのパターンに応じて画面遷移を行う動作などを記述します。
#import <Repro/Repro.h>
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[Repro setOpenUrlCallback:^(NSURL *url) {
if ([url.host isEqualToString:@"example.com"]) {
// In case of your universal link perform navigation, present content, ...
handleUniversalLink(url);
}
}];
...
[Repro setup:@"YOUR_APP_TOKEN"];
...
}
// Set a callback that is executed everytime an URL is about to be opened
Repro.setOpenUrlCallback { url in
if url.host == "example.com" {
// In case of your universal link perform navigation, present content, ...
handleUniversalLink(url)
}
}
...
Repro.setup(token: "YOUR_APP_TOKEN")
...
import io.repro.android.Repro;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// In order to execute a callback when a push notification is tapped,
// the callback must be set in Application, not Activity.
Repro.setOpenUrlCallback(new Repro.OpenUrlCallback() {
// ** This callback method is executed in the main thread **
@Override
public void onOpened(Uri uri) {
if ("example.com".equals(uri.getHost())) {
// In case of your universal link perform navigation, present content, ...
}
}
});
...
Repro.setup(this, YOUR_APP_TOKEN);
...
}
...
}
Repro.setOpenUrlCallback((uri) { // uri is of type Uri
debugPrint("Universal Link Callback Handler received: " + uri.toString());
});
// Somewhere before Repro.Setup(...)
Repro.SetOpenUrlCallback(uri => // uri is of type Uri
{
Debug.Log("Universal Link Callback Handler received: " + uri.ToString());
});
bool YourAppName::init() {
ReproCpp::addOpenUrlFilterRegEx(...);
ReproCpp::setOpenUrlCallback([](const char *url) {
if (strcmp(url, "example.com") == 0) {
// In case of your universal link perform navigation, present content, ...
}
});
ReproCpp::setup("YOUR_APP_TOKEN")
...
}
Repro.setOpenUrlCallback(function(url) { // url is of type String
alert('Universal Link Callback Handler received: ' + url);
if (url.includes("http://example.org")) {
// In case of your universal link perform navigation, present content, ...
}
});
Repro.setOpenUrlCallback( (url) => { // url is of type String
console.log('Universal Link Callback Handler received: ' + url);
if (url.includes("http://example.org")) {
// In case of your universal link perform navigation, present content, ...
}
});