푸시 메시지 연동
타 푸시 솔루션과 함께 사용할 수 있습니다
타 푸시 솔루션과 함께 사용하려면 타 푸시 솔루션의 Swizzling 옵션을 비활성화해야 합니다.
Swizzling 비활성화 후, 해당 솔루션의 가이드를 참고하여 푸시 알림 처리를 수동으로 설정해 주세요.
FCM을 통한 iOS 푸시 메시지를 지원하지않습니다
iOS 푸시 메시지 사용을 위해서 APNs를 연동해주세요.
1. APNs 설정하기
iOS 앱에서 푸시 메시지를 사용하기 위해서는 핵클 워크스페이스와 APNs 연동 설정이 필요합니다.
자세한 내용은 Apple Push Notification Service 설정을 참고하세요.
2. 앱에 PushNotification Capability 추가
Xcode 프로젝트 설정의 Signing & Capabilities
탭에서 + Capability
를 아래와 같이 클릭해주세요.
Push Notifications
과 Background Modes
를 추가해주세요.
그리고 Background Modes
의 Remote notifications
를 활성화해 주세요.
3. 핵클 SDK와 연동하기
푸시 메시지 연동을 위해서는 AppDelegate가 필요합니다.
핵클에서 iOS 앱이 설치된 기기에 푸시 메시지를 전달할수 있도록 아래의 설정을 완료합니다.
class AppDelegate: NSObject, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
) -> Bool {
return true
}
}
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@end
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
만약 SwiftUI
의 경우 아래와 같이 AppDelegate
를 SwiftUI
에 등록해 주세요.
import SwiftUI
@main
struct sampleApp: App {
...
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
...
}
푸시 토큰 수집
AppDelegate
에 아래과 같이 setPushToken
메소드를 추가합니다.
import Hackle
class AppDelegate: NSObject, UIApplicationDelegate {
...
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// iOS 앱에서 푸시 권한 요청
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { _, _ in }
)
UNUserNotificationCenter.current().delegate = self
application.registerForRemoteNotifications()
// 핵클 SDK 초기화
Hackle.initialize(sdkKey: YOUR_APP_SDK_KEY)
return true
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
// 핵클 서버로 APNs 푸시 토큰 전달
Hackle.app()?.setPushToken(deviceToken)
}
...
}
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
@import Hackle;
@interface AppDelegate : UIResponder <UIApplicationDelegate, UNUserNotificationCenterDelegate>
@end
#import "AppDelegate.h"
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// iOS 앱에서 푸시 권한 요청
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound)
completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
center.delegate = self;
[[UIApplication sharedApplication] registerForRemoteNotifications];
// 핵클 SDK 초기화
[Hackle initializeWithSdkKey:@"YOUR_APP_SDK_KEY"
config:[HackleConfig DEFAULT]];
return YES;
}
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
// 핵클 서버로 APNs 푸시 토큰 전달
[[Hackle app] setPushToken:deviceToken];
}
푸시 메시지 표시
포그라운드 푸시 메시지 표시
포그라운드 푸시 메시지 표시를 위해 userNotificationCenter
메소드를 추가합니다.
import Hackle
extension AppDelegate: UNUserNotificationCenterDelegate {
// Foreground push message
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions
) -> Void) {
if Hackle.userNotificationCenter(
center: center, willPresent: notification, withCompletionHandler: completionHandler
) {
// Succefully processed notification
// Automatically consumed completion handler
return
} else {
// Received not hackle notification or error
print("Do something")
if #available(iOS 14.0, *) {
completionHandler([.list, .banner])
} else {
completionHandler([.alert])
}
}
}
}
// Foreground push message
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
if ([Hackle userNotificationCenterWithCenter:center
willPresent:notification
withCompletionHandler:completionHandler]) {
// Succefully processed notification
// Automatically consumed completion handler
return;
} else {
// Received not hackle notification or error
NSLog(@"Do something");
completionHandler(UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner);
}
}
핵클에서 송신한 푸시가 아닌 경우 false가 리턴됩니다.
푸시 클릭 처리
푸시 클릭 처리를 위해 handleNotification
메소드를 추가합니다.
핵클에서 제공하는 푸시 클릭 처리 함수를 호출하지 않으면 푸시가 정상적으로 처리되지 않습니다.
또한, 푸시 클릭 이벤트가 수집되지 않고 푸시 클릭률 지표를 이용할 수 없습니다.
import Hackle
extension AppDelegate: UNUserNotificationCenterDelegate {
// push click
public func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
if let _ = Hackle.handleNotification(response: response) {
// process hackle notification
} else {
// not hackle notification or error
print("do something")
}
// handleNotification 에서 completionHandler를 호출하지 않으니
// 핵클 푸시 여부에 관계없이 반드시 completionHandler를 호출해야 합니다.
completionHandler()
}
}
// push click
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
if ([Hackle handleNotificationWithResponse:response] != nil) {
// process hackle notification
} else {
// not hackle notification or error
NSLog(@"do something");
}
// handleNotification 에서 completionHandler를 호출하지 않으니
// 핵클 푸시 여부에 관계없이 반드시 completionHandler를 호출해야 합니다.
completionHandler();
}
푸시 클릭 함수는 아래 순서로 처리를 합니다.
- 핵클에서 송신한 푸시인지 확인
- 푸시 클릭 이벤트를 핵클 서버로 송신
- (deep link push인 경우) deep link 처리
핵클에서 송신한 푸시가 아닌 경우 nil이 리턴됩니다.
푸시 클릭 커스텀 딥링크 처리
앱 내에서 핵클에서 전달한 링크의 재가공이 필요한 경우 handleNotification
의 handleAction
파라미터를 false로 선언해서 사용하면 됩니다.
handleAction 파라미터가 false인 경우
- Hackle SDK는 푸시 클릭 이벤트를 핵클 서버로 송신합니다.
- deep link 처리를 하지 않습니다.
import Hackle
extension AppDelegate: UNUserNotificationCenterDelegate {
// push click
public func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
if let notification = Hackle.handleNotification(response: response, handleAction: false) {
// 푸시 메시지 Action Type
print("\(notifiaction.actionType)")
// 푸시 메시지에 등록된 link
print("\(notifiaction.link)")
} else {
// not hackle notification or error
print("do something")
}
// handleNotification 에서 completionHandler를 호출하지 않으니
// 핵클 푸시 여부에 관계없이 반드시 completionHandler를 호출해야 합니다.
completionHandler()
}
}
// push click
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
id notification = [Hackle handleNotificationWithResponse:response handleAction:NO];
if (notification != nil) {
// process hackle notification
NSLog(@"%@", [notification valueForKey:@"actionType"]);
NSLog(@"%@", [notification valueForKey:@"link"]);
} else {
// not hackle notification or error
NSLog(@"do something");
}
// handleNotification 에서 completionHandler를 호출하지 않으니
// 핵클 푸시 여부에 관계없이 반드시 completionHandler를 호출해야 합니다.
completionHandler();
}
푸시 메시지의 actionType
은 아래와 같습니다.
actionType | 설명 |
---|---|
appOpen | 앱 실행 |
link | 앱 실행 후 링크로 이동 |
actionType
이 appOpen
인 경우 link
는 nil 입니다.
4. 푸시 메시지 테스트
토큰 확인
사용자 식별자 확인하기 가이드 를 통해 iOS 기기에 설정된 토큰을 확인합니다.
테스트
푸시 메시지 테스트 발송 가이드 를 참고하여 푸시 메시지를 iOS 기기에서 확인합니다.
5. 푸시 메시지 수신
iOS는 빌드 환경에 따라 푸시 메시지 수신 여부가 다릅니다.
APNs Key의 Environment을
Sandbox & Production
으로 설정한 경우에도 아래와 같이 핵클 환경 및 앱 빌드 환경별로 푸시 메시지를 수신받을 수 있는 범위가 다릅니다.
핵클 환경 | APNs Environment | 설명 | 빌드 환경 |
---|---|---|---|
개발 환경, 개발/운영 테스트 푸시 | Sandbox | 테스트 용 | Xcode에서 직접 실행, 개발용 프로비지닝 |
운영 환경 | Production | 운영 용 | TestFlight, Ad Hoc, App Store 배포 |
(Advanced) 딥링크 이동
핵클 푸시 메시지는 클릭 시 딥링크 이동을 지원합니다.
푸시 메시지를 통해 해당 앱이 열리는 경우 아래의 설정을 통해 열린 딥링크 정보를 확인할수 있습니다.
iOS 딥링크에 대한 자세한 사항은 iOS 딥링크 가이드 에서 확인 가능합니다.
푸시 클릭 커스텀 딥링크 처리 를 한 경우에는 아래와 같이 딥링크 정보가 전달되지 않습니다.
import SwiftUI
@main
struct sampleApp: App {
...
var body: some Scene {
WindowGroup {
ContentView()
.onOpenURL(perform: { url in
// Handle opened url
print("\(url.absoluteString) opened.")
})
}
}
...
}
class AppDelegate: NSObject, UIApplicationDelegate {
...
func application(_ application: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:] ) -> Bool {
// Handle opened url
print("\(url.absoluteString) opened.")
}
...
}
SwiftUI
와Storyboard
에서의 딥링크 처리는 각각 독립적이기 때문 해당 iOS 앱 프로젝트에 맞도록 설정해 주세요
Updated 1 day ago