Code Monkey home page Code Monkey logo

ctnotificationcontent's Introduction

CTNotificationContent

Version SwiftPM compatible Platform iOS 10.0+ License

A Notification Content Extension class to display custom content interfaces for iOS 10 push notifications

Starting with iOS 10 you can add custom content views to iOS push notifications. This library provides a class to accomplish that. It provides a default Image Slideshow view and is designed to be easily extensible to display additional view types.

Custom push notification content interfaces are enabled in iOS 10 via a Notification Content Extension, a separate and distinct binary embedded in your app bundle.

Table of contents

๐ŸŽ‰ Installation

(Back to top)

Your Podfile should look something like this:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'

use_frameworks!

target 'YOUR_NOTIFICATION_CONTENT_TARGET_NAME' do  
    pod 'CTNotificationContent'  
end     

Then run pod install

See example Podfile here.

Swift Package Manager

Swift Package Manager is an Xcode tool that installs project dependencies. To use it to install CTNotificationContent SDK, follow these steps:

  • In Xcode, navigate to File -> Swift Package Manager -> Add Package Dependency.
  • Enter https://github.com/CleverTap/CTNotificationContent.git when choosing package repo and Click Next.
  • On the next screen, Select an SDK version (by default, Xcode selects the latest stable version). Click Next.
  • Click Finish and ensure that the CTNotificationContent has been added to the appropriate target.

๐Ÿš€ Setup

(Back to top)

Configure your app for Push and add a Notification Content Extension target

Enable push notifications in your main app.

Create a Notification Content Extension in your project. To do that in your Xcode project, select File -> New -> Target and choose the Notification Content Extension template.

notification content extension

Configure your Notification Content Extension to use the CTNotificationViewController class

Change the superclass of your NotificationViewController to CTNotificationViewController. You should not implement any of the UNNotificationContentExtension protocol methods in your NotificationViewController class, those will be handled by CTNotificationViewController. See Objective-C example here and Swift example here.

Edit the Maininterface.storyboard in your NotificationContent target to a plain UIView, see example here.

In your AppDelegate, register the Notification category and actions:

Swift:

    // register category with actions
    let action1 = UNNotificationAction(identifier: "action_1", title: "Back", options: [])
    let action2 = UNNotificationAction(identifier: "action_2", title: "Next", options: [])
    let action3 = UNNotificationAction(identifier: "action_3", title: "View In App", options: [])
    let category = UNNotificationCategory(identifier: "CTNotification", actions: [action1, action2, action3], intentIdentifiers: [], options: [])
    UNUserNotificationCenter.current().setNotificationCategories([category])

Objective-C:

    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    UNNotificationAction *action1 = [UNNotificationAction actionWithIdentifier:@"action_1" title:@"Back" options:UNNotificationActionOptionNone];
    UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:@"action_2" title:@"Next" options:UNNotificationActionOptionNone];
    UNNotificationAction *action3 = [UNNotificationAction actionWithIdentifier:@"action_3" title:@"View In App" options:UNNotificationActionOptionNone];
    UNNotificationCategory *cat = [UNNotificationCategory categoryWithIdentifier:@"CTNotification" actions:@[action1, action2, action3] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];
    [center setNotificationCategories:[NSSet setWithObjects:cat, nil]];

See Objective-C example here and Swift example here.

Then configure your Notification Content target Info.plist to reflect the category identifier you registered: NSExtension -> NSExtensionAttributes -> UNNotificationExtensionCategory. In addition, set the UNNotificationExtensionInitialContentSizeRatio -> 0.1 and UNNotificationExtensionDefaultContentHidden -> true.

Also, If you plan on downloading non-SSL urls please be sure to enable App Transport Security Settings -> Allow Arbitrary Loads -> true in your plist. See plist example here.

Dashboard Usage

(Back to top) While creating a Push Notification campaign on CleverTap, just follow the steps below -

  1. On the "WHAT" section pass the desired required values in the "title" and "message" fields (NOTE: These are iOS alert title and body). Dashboard alert
  2. Click on "Advanced" and then click on "Rich Media" and select Single or Carousel template. Dashboard Rich Media
  3. For adding custom key-value pair, add the template Keys individually or into one JSON object and use the pt_json key to fill in the values. Dashboard Custom Key individual Dashboard Custom Key JSON
  4. Send a test push and schedule!

Template Types

(Back to top)

Rich Media

Single Media

Single media is for basic view with single image. Single Media

Content Slider

Content Slider is for image slideshow view where user can add multiple images with different captions, sub-captions, and actions.

Content slider

Custom key-value pair

Basic Template

Basic Template is the basic push notification received on apps where user can also update text colour, background colour.

Custom Basic template

Auto Carousel Template

Auto carousel is an automatic revolving carousel push notification where user can also update text colour, background colour.

Auto carousel

Manual Carousel Template

This is the manual version of the carousel. The user can navigate to the next/previous image by clicking on the Next/Back buttons.

NOTE:

For iOS 12 and above, you need to configure your Notification Content target Info.plist to reflect the category identifier you registered: NSExtension -> NSExtensionAttributes -> UNNotificationExtensionCategory. In addition, set the UNNotificationExtensionInitialContentSizeRatio -> 0.1 , UNNotificationExtensionDefaultContentHidden -> true and UNNotificationExtensionUserInteractionEnabled -> 1.

For iOS 11 and below, the previous/next buttons will not work. Please use notification actions with identifiers action_1 and action_2 for this purpose.


Manual carousel

Timer Template

This template features a live countdown timer. You can even choose to show different title, message, and background image after the timer expires.

Timer template

Zero Bezel Template

The Zero Bezel template ensures that the background image covers the entire available surface area of the push notification. All the text is overlayed on the image.

Zero Bezel template

Rating Template

Rating template lets your users give you feedback.

NOTE:

For iOS 12 and above, you need to configure your Notification Content target Info.plist to reflect the category identifier you registered: NSExtension -> NSExtensionAttributes -> UNNotificationExtensionCategory. In addition, set the UNNotificationExtensionInitialContentSizeRatio -> 0.1 , UNNotificationExtensionDefaultContentHidden -> true and UNNotificationExtensionUserInteractionEnabled -> 1. For iOS 11 and below, it will fallback to a basic template.


Rating

Product Catalog Template

Product catalog template lets you show case different images of a product (or a product catalog) before the user can decide to click on the "BUY NOW" option which can take them directly to the product via deep links. This template has two variants.

NOTE:

For iOS 12 and above, you need to configure your Notification Content target Info.plist to reflect the category identifier you registered: NSExtension -> NSExtensionAttributes -> UNNotificationExtensionCategory. In addition, set the UNNotificationExtensionInitialContentSizeRatio -> 0.1 , UNNotificationExtensionDefaultContentHidden -> true and UNNotificationExtensionUserInteractionEnabled -> 1. For iOS 11 and below, it will fallback to a basic template.


Vertical View

Product Display

Linear View

Use the following keys to enable linear view variant of this template.

Template Key Required Value
pt_product_display_linear Optional true

Product Display

WebView Template

WebView template lets you load a remote https URL.

WebView Template

Note: If any image can't be downloaded, the template falls back to basic template with caption and sub caption only.

Template Keys

(Back to top)

Rich Media

Content Slider

Configure your APNS payload:

Then, when sending notifications via APNS:

  • include the mutable-content flag in your payload aps entry (this key must be present in the aps payload or the system will not call your app extension)
  • for the Image Slideshow view, add the ct_ContentSlider key with a json object value, see example below, to the payload, outside of the aps entry.
{

    "aps": {
        "alert": {
            "body": "test message",
            "title": "test title",
        },
        "category": "CTNotification",
        "mutable-content": true,
      },
    "ct_ContentSlider": {
        "orientation": "landscape", // landscape assumes 16:9 images, remove to display default square/portrait images
        "showsPaging": true, // optional to display UIPageControl
        "autoPlay": true, // optional to auto play the slideshow
        "autoDismiss": true, // optional to auto dismiss the notification on item actionUrl launch
        "items":[
            {
                "caption": "caption one",
                "subcaption": "subcaption one",
                "imageUrl": "https://s3.amazonaws.com/ct-demo-images/landscape-1.jpg",
                "actionUrl": "com.clevertap.ctcontent.example://item/one"
            }, 
            {
                "caption": "caption two", 
                "subcaption": "subcaption two", 
                "imageUrl": "https://s3.amazonaws.com/ct-demo-images/landscape-2.jpg",
                "actionUrl": "com.clevertap.ctcontent.example://item/two"
            }
       ]
   }
}

Custom key-value pair

Basic Template

Basic Template Keys Required Description
pt_id Required Value - pt_basic
pt_title Required Title
pt_msg Required Message
pt_msg_summary Required Message line when Notification is expanded
pt_bg Required Background Color in HEX
pt_big_img Optional Image
pt_dl1 Optional One Deep Link
pt_title_clr Optional Title Color in HEX
pt_msg_clr Optional Message Color in HEX
pt_json Optional Above keys in JSON format

Auto Carousel Template

Auto Carousel Template Keys Required Description
pt_id Required Value - pt_carousel
pt_title Required Title
pt_msg Required Message
pt_msg_summary Optional Message line when Notification is expanded
pt_dl1 Required Deep Link
pt_img1 Required Image One
pt_img2 Required Image Two
pt_img3 Required Image Three
pt_bg Required Background Color in HEX
pt_title_clr Optional Title Color in HEX
pt_msg_clr Optional Message Color in HEX
pt_json Optional Above keys in JSON format

Manual Carousel Template

Manual Carousel Template Keys Required Description
pt_id Required Value - pt_manual_carousel
pt_title Required Title
pt_msg Required Message
pt_msg_summary Optional Message line when Notification is expanded
pt_dl1 Required Deep Link One
pt_img1 Required Image One
pt_img2 Required Image Two
pt_img3 Required Image Three
pt_bg Required Background Color in HEX
pt_title_clr Optional Title Color in HEX
pt_msg_clr Optional Message Color in HEX
pt_json Optional Above keys in JSON format

Timer Template

Timer Template Keys Required Description
pt_id Required Value - pt_timer
pt_title Required Title
pt_title_alt Optional Title to show after timer expires
pt_msg Required Message
pt_msg_alt Optional Message to show after timer expires
pt_msg_summary Optional Message line when Notification is expanded
pt_dl1 Required Deep Link
pt_big_img Optional Image
pt_big_img_alt Optional Image to show when timer expires
pt_bg Required Background Color in HEX
pt_chrono_title_clr Optional Color for timer text in HEX
pt_timer_threshold Required Timer duration in seconds. Will be given higher priority.
pt_timer_end Optional Epoch Timestamp to countdown to (for example, $D_1595871380 or 1595871380). Not needed if pt_timer_threshold is specified.
pt_title_clr Optional Title Color in HEX
pt_msg_clr Optional Message Color in HEX
pt_json Optional Above keys in JSON format

Zero Bezel Template

Zero Bezel Template Keys Required Description
pt_id Required Value - pt_zero_bezel
pt_title Required Title
pt_msg Required Message
pt_msg_summary Optional Message line when Notification is expanded
pt_subtitle Optional Subtitle
pt_big_img Required Image
pt_dl1 Required Deep Link
pt_title_clr Optional Title Color in HEX
pt_msg_clr Optional Message Color in HEX
pt_json Optional Above keys in JSON format

Rating Template

Rating Template Keys Required Description
pt_id Required Value - pt_rating
pt_title Required Title
pt_msg Required Message
pt_big_img Optional Image
pt_msg_summary Optional Message line when Notification is expanded
pt_subtitle Optional Subtitle
pt_default_dl Required Default Deep Link for Push Notification
pt_dl1 Required Deep Link for first/all star(s)
pt_dl2 Optional Deep Link for second star
pt_dl3 Optional Deep Link for third star
pt_dl4 Optional Deep Link for fourth star
pt_dl5 Optional Deep Link for fifth star
pt_bg Required Background Color in HEX
pt_ico Optional Large Icon
pt_title_clr Optional Title Color in HEX
pt_msg_clr Optional Message Color in HEX
pt_json Optional Above keys in JSON format

Product Catalog Template

Product Catalog Template Keys Required Description
pt_id Required Value - pt_product_display
pt_title Required Title
pt_msg Required Message
pt_subtitle Optional Subtitle
pt_img1 Required Image One
pt_img2 Required Image Two
pt_img3 Optional Image Three
pt_bt1 Required Big text for first image
pt_bt2 Required Big text for second image
pt_bt3 Required Big text for third image
pt_st1 Required Small text for first image
pt_st2 Required Small text for second image
pt_st3 Required Small text for third image
pt_dl1 Required Deep Link for first image
pt_dl2 Required Deep Link for second image
pt_dl3 Required Deep Link for third image
pt_price1 Required Price for first image
pt_price2 Required Price for second image
pt_price3 Required Price for third image
pt_bg Required Background Color in HEX
pt_product_display_action Required Action Button Label Text
pt_product_display_linear Optional Linear Layout Template ("true"/"false")
pt_product_display_action_clr Required Action Button Background Color in HEX
pt_title_clr Optional Title Color in HEX
pt_msg_clr Optional Message Color in HEX
pt_json Optional Above keys in JSON format

WebView Template

WebView Template Keys Required Description
pt_id Required Value - pt_web_view
pt_dl1 Required Deep Link
pt_url Required URL to load
pt_orientation Optional Value - landscape or portrait
pt_json Optional Above keys in JSON format

Sample App

(Back to top)

Changelog

(Back to top) Refer to the Change Log.

ctnotificationcontent's People

Contributors

aditi3 avatar aishwaryananna avatar akashvercetti avatar judepereira avatar kushct avatar mkumary avatar nishant-clevertap avatar noorulain17 avatar nzagorchev avatar pwilkniss avatar sonal-kachare avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ctnotificationcontent's Issues

iOS Rich Push notifications - Auto Carousel not shown for the very first time tap

Hi @akashvercetti @AishwaryaNanna @nishant-clevertap

We are using the CTNotificationContent for Rich Push Notifications. Added all the required key values for the Auto Carousel template. The issue the Auto carousel is shown up the second time tap not on the first time long press for the same notification.

Configuration details:
Used SPM to install the CTNotificationContent extension and on the latest version.
Please do needful.

Thanks

SDK does not trigger userDidReceive or userDidPerformAction on user tap action in NotificationContent target

Steps to reproduce

  • Open swift example project and run the NotificationContent target
  • Put the app in background
  • Create a carousel (or any other) notification with deeplinks or add custom json properties (including deeplinks)
  • Send it from Clevertap dashboard
  • Long press to expand the notification (can see the images)
  • Tap on the notification (or tap outside to collapse the notification)
  • App opens but neither userDidReceive nor userDidPerformAction get's triggered

Note

userDidPerformAction does get's trigger when carousel's page slides.

Another issue

There are times when we need custom values from notification for mapping on specific action. But since none of the above mentioned function get's triggered, we are unable to get any data.
One good example is deeplink.

Can open user info for current notifciaton?

In method-didReceiveNotification:(UNNotification *)notification of CTNotificationViewController, we can get the user info for this notification, can open this, let we can get this user info?

Template type support not given as per Android has

Hi team in iOS only 4 template types are supported and in Android their is multiple types are supported.
I need to implement Zero bezel template and rating template in my app. So need any suggestion for this or else you guys are in development for that template types.

"View In App" action button tap does not open app.

"View In App" action button tap not invoking callback function
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler

I tried by changing
[UNNotificationAction actionWithIdentifier:@"action_3" title:@"View In App" options:UNNotificationActionOptionNone]

to

[UNNotificationAction actionWithIdentifier:@"action_3" title:@"View In App" options:UNNotificationActionOptionForeground]

Tapping on "View In App" should open invoke the callback for me to handle the deeplink right? Am i missing something here.

Swift Package Manager Support

Please provide support for Swift Package Manager, it is well integrated with Xcode than Cocoapods.
We already use CleverTap SDK as a Swift Package andIt would be great to be able to use it with this as well.

Initial Integration: Carousel Images Not Showing

After following the steps indicated in the docs and in the repos, Single Message is working with the image, but the default carousel has issues. Specifically, the notification shows up, the options for Back, Next, View in App shows up after tap and hold, but the images does not show. And clicking either of the actions only suspends the notification and goes to the url we are using for redirection.

image

Below are the details about the issue we encountered when integrating CleverTap's Rich Push Notifications Feature.

Thank you.

Observations

  1. Aside from the notification being blank, when clicking back, next or view app, it just suspends notification.
  2. We haven't used the custom key-value pairs, but the question is, is it necessary?
  3. What exactly is the needed change on MainInterface.storyboard?
  4. only willPresentNotification & didRegisterForRemoteNotificationsWithDeviceToken is being called during testing.
  5. There's a bit recent issue in this repo that is somewhat similar. But even if we made sure that the test image is jpg and less than 40KB, it still does not show.
  6. We are testing this in a test CT project.

Configuration

Package Version
Test Devices iOS Version 17.2.1 (iPhone 14), 15.8 (iPhone 6s)
Minimum Target Deployment 11.0
XCode 15.2
CleverTap-iOS-SDK 5.2.1
clevertap-react-native 1.2.1
CTNotificationContent 0.2.5
CTNotificationService 0.1.5

Pod File

...
platform :ios, '11.0'

pod "CleverTap-iOS-SDK", '5.2.1'
...
target 'NotificationService' do
  pod 'CTNotificationService', :modular_headers => true  
end

target 'NotificationContent' do
  pod "CTNotificationContent"
end

NotificationService

NofificationService.h

#import <CTNotificationService/CTNotificationService.h>

@interface NotificationService : CTNotificationServiceExtension

@end

NotificationService.m

#import "NotificationService.h"
#import "CleverTap.h"

@interface NotificationService ()

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    
    // Modify the notification content here...
    self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title];
//    
   self.contentHandler(self.bestAttemptContent);
    #if DEBUG
        NSLog(@"AppDelegate: didReceiveRemoteNotificationRequest!");
    #endif

    [[CleverTap sharedInstance] recordNotificationViewedEventWithData:request.content.userInfo];
    [super didReceiveNotificationRequest:request withContentHandler:contentHandler];
}

- (void)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.
    self.contentHandler(self.bestAttemptContent);
}

@end

Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>NSExtension</key>
	<dict>
		<key>NSExtensionPointIdentifier</key>
		<string>com.apple.usernotifications.service</string>
		<key>NSExtensionPrincipalClass</key>
		<string>CTNotificationServiceExtension</string>
	</dict>
	<key>CleverTapAccountID</key>
	<string>$(CT_ACCOUNT_ID)</string>
	<key>CleverTapRegion</key>
	<string>sg1</string>
	<key>CleverTapToken</key>
	<string>$(CT_TOKEN)</string>
</dict>
</plist>

NotificationContent

NotificationViewController.h

#import <UIKit/UIKit.h>
#import <CTNotificationContent/CTNotificationContent.h>

@interface NotificationViewController : CTNotificationViewController

@end

NotificationViewController.m

#import "NotificationViewController.h"
#import <UserNotifications/UserNotifications.h>
#import <UserNotificationsUI/UserNotificationsUI.h>

@interface NotificationViewController () <UNNotificationContentExtension>

@property IBOutlet UILabel *label;

@end

@implementation NotificationViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any required interface initialization here.
}

- (void)didReceiveNotification:(UNNotification *)notification {
    self.label.text = notification.request.content.body;
    #if DEBUG
        NSLog(@"did receive notification: %@", notification.request.content.body);
    #endif
}

// optional: implement to get user event type data
- (void)userDidPerformAction:(NSString *)action withProperties:(NSDictionary *)properties {
    #if DEBUG
        NSLog(@"user did perform action: %@ with props: %@", action , properties);
    #endif
}

// optional: implement to get notification response
- (void)userDidReceiveNotificationResponse:(UNNotificationResponse *)response {
    #if DEBUG
        NSLog(@"user did receive notification response: %@:", response);
    #endif
}

@end

Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Application App Transport Security Settings</key>
	<dict>
		<key>Allow Arbitrary Loads</key>
		<true/>
	</dict>
	<key>NSExtension</key>
	<dict>
		<key>NSExtensionAttributes</key>
		<dict>
			<key>UNNotificationExtensionCategory</key>
			<string>CTNotification</string>
			<key>UNNotificationExtensionUserInteractionEnabled</key>
			<string>1</string>
			<key>UNNotificationExtensionDefaultContentHidden</key>
			<true/>
			<key>UNNotificationExtensionInitialContentSizeRatio</key>
			<real>0.1</real>
			<!-- <key>UNNotificationExtensionInitialContentSizeRatio</key>
			<real>1</real> -->
		</dict>
		<key>NSExtensionMainStoryboard</key>
		<string>MainInterface</string>
		<key>NSExtensionPointIdentifier</key>
		<string>com.apple.usernotifications.content-extension</string>
	</dict>
</dict>
</plist>

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [self initializeClevertap];

  #if DEBUG
    NSLog(@"DEBUG: %d", DEBUG);
    [CleverTap setDebugLevel:CleverTapLogDebug];
    #ifdef FB_SONARKIT_ENABLED
      InitializeFlipper(application);
    #endif
  #endif
  
  if(lOptions == nil) {
    lOptions = launchOptions;
  }
  
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"Booky"
                                            initialProperties:nil];

   if (@available(iOS 13.0, *)) {
      rootView.backgroundColor = [UIColor systemBackgroundColor];
  } else {
      rootView.backgroundColor = [UIColor whiteColor];
  }

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  [RNBootSplash initWithStoryboard:@"BootSplash" rootView:rootView];
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }
  [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];

  return YES;
}
...
- (void) initializeClevertap {
  [CleverTap autoIntegrate]; // integrate CleverTap SDK using the autoIntegrate option
  [self registerPush]; // register for APN
  [[CleverTapReactManager sharedInstance] applicationDidLaunchWithOptions:lOptions];
}
...
- (void)registerPush {    
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

    UNNotificationAction *action1 = [UNNotificationAction actionWithIdentifier:@"action_1" title:@"Back" options:UNNotificationActionOptionNone];
    UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:@"action_2" title:@"Next" options:UNNotificationActionOptionNone];
    UNNotificationAction *action3 = [UNNotificationAction actionWithIdentifier:@"action_3" title:@"View In App" options:UNNotificationActionOptionNone];
    UNNotificationCategory *cat = [UNNotificationCategory categoryWithIdentifier:@"CTNotification" actions:@[action1, action2, action3] intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];
    [center setNotificationCategories:[NSSet setWithObjects:cat, nil]];
    
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error){
        if( !error ){
            dispatch_async(dispatch_get_main_queue(), ^(void) {
                [[UIApplication sharedApplication] registerForRemoteNotifications];
            });
        }
    }];
}
...
/** For iOS 10 and above - Foreground, NOTE: Also works for iOS 8 **/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{    
    /**
      Use this method to perform the tasks associated with your app's custom actions. When the user responds to a notification, the system calls this method with the results. You use this method to perform the task associated with that action, if at all. At the end of your implementation, you must call the completionHandler block to let the system know that you are done processing the notification.
      
      You specify your app's notification types and custom actions using UNNotificationCategory and UNNotificationAction objects.
      You create these objects at initialization time and register them with the user notification center. Even if you register custom actions, the action in the response parameter might indicate that the user dismissed the notification without performing any of your actions.
      
      If you do not implement this method, your app never responds to custom actions.
      
      see https://developer.apple.com/reference/usernotifications/unusernotificationcenterdelegate/1649501-usernotificationcenter?language=objc
      **/

    NSLog(@"%@: will present notification: %@", self.description, notification.request.content.userInfo);

    /** NOTE: As of CT SDK Version 5.2.1, this triggers Push Impressions / Impressions on Campaign Stat page, not Notification Viewed as indicated by name! **/

    [[CleverTap sharedInstance] recordNotificationViewedEventWithData:notification.request.content.userInfo];

    // if you wish CleverTap to record the notification open and fire any deep links contained in the payload, NOTE: This triggers Notification Clicked automatically
    // [[CleverTap sharedInstance]handleNotificationWithData:notification.request.content.userInfo openDeepLinksInForeground: NO];
    completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
...
/** NOTE: This is the only one triggered in testing the happy path, other than willPresentNotification **/
- (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
  #if DEBUG
    NSLog(@"%@: registered for remote notifications: %@", self.description, deviceToken.description);
  #endif
}

Can provide the API to custom actions for different notifications.

- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response
                     completionHandler:(void (^)(UNNotificationContentExtensionResponseOption))completion {
    UNNotificationContentExtensionResponseOption actionResponseOption = [self.contentViewController handleAction:response.actionIdentifier];
    completion(actionResponseOption);
}
- (UNNotificationContentExtensionResponseOption)handleAction:(NSString *)action
{
   // If can open some API, to handle custom action
}

We can custom more actions using code, the category is not "CTNotification".
But, can not handle the action event by ourself.

So, can provide?

pod compilation failure

when we try to build we face this error

Compiling Pods/CTNotificationContent ยป CTNotificationViewController.m

โŒ  (ios/Pods/CTNotificationContent/CTNotificationContent/CTNotificationViewController.m:5:9)

  3 | #import <UserNotifications/UserNotifications.h>
  4 | #import <UserNotificationsUI/UserNotificationsUI.h>
> 5 | #import <CTNotificationContent/CTNotificationContent-Swift.h>
    |         ^ 'CTNotificationContent/CTNotificationContent-Swift.h' file not found
  6 | 
  7 | typedef NS_ENUM(NSInteger, CTNotificationContentType) {
  8 |     CTNotificationContentTypeContentSlider = 0,

not sure what is missing or steps we might have missed

carosel rich notification is not working

i am integrating rich push notification into my react native app, single image rich notification is working but carousel rich notification is not working

Carosel Single Image
carousel.mov
single_image.MP4

i am using same swift example code for NotificationService and NotificationContent in my project https://github.com/CleverTap/CTNotificationContent/tree/master/ExampleSwift/NotificationContent, using same info.plist, appDelegate.mm and MainInterface.storyboard

Screenshot 2023-08-01 at 4 48 46 PM

where can be the issue?

Tempates are not rendering with pt_json Custom key-value pairs

We are using below SDK
clevertap-react-native : 0.9.5
CTNotificationService : 0.1.5
CTNotificationContent : 0.2.4
react-native : 0.64.4

When we use separate Custom key-value pairs from dashboard, templates are rendering correcting.
When we use json with pt_json key, templates are not rendering correctly.

We found one issue in sdk, it is crashing at below line;

[contentController setData:self.jsonString];

It is fixed by doing below change
self.jsonString = [self createJSONData:content[kJSON]];
at

Can you please fix this issue ?

Not able to dismiss Rich push notification on expanded

Created a Rich push notification supported by Clevertap (Timer Template), and it reaches the device then if expand and click on it opens the app but action has not been sent to the UNUserNotificationCenter delegate and the notification remains in the notification center.

SDK Crashing for carousel template

Steps to reproduce

  • Open swift example project and run the NotificationContent target
  • Put the app in background and send the carousel notification from CleverTap Dashboard
  • Long press to expand the notification (can see the images)
  • Tap on the notification (or tap outside to collapse the notification)
  • Crash
CTContentSliderControlle.func moveSlider(direction: Int)
...
// This line
 -> getParentViewController().userDidPerformAction(ConstantKeys.kViewContentItemAction, withProperties: items[currentItemIndex])

Crash Log

{\rtf1\ansi\ansicpg1252\cocoartf2639
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;\f1\fnil\fcharset0 Menlo-Bold;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;}
{\*\expandedcolortbl;;\csgenericrgb\c0\c0\c0;\csgenericrgb\c100000\c100000\c100000;}
\paperw11900\paperh16840\margl1440\margr1440\vieww24760\viewh17340\viewkind0
\deftab1038
\pard\tx1038\pardeftab1038\pardirnatural\partightenfactor0

\f0\fs42 \cf2 \cb3 * thread #1, queue = 'com.apple.main-thread', stop reason = Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
\f1\b \

\f0\b0     frame #0: 0x00000001853a6ebc libswiftCore.dylib`_swift_runtime_on_report
\f1\b \

\f0\b0     frame #1: 0x000000018542da70 libswiftCore.dylib`_swift_stdlib_reportFatalErrorInFile + 204
\f1\b \

\f0\b0     frame #2: 0x00000001850eccb4 libswiftCore.dylib`closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.StaticString, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 356
\f1\b \

\f0\b0     frame #3: 0x00000001850eca1c libswiftCore.dylib`closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in closure #1 (Swift.UnsafeBufferPointer<Swift.UInt8>) -> () in Swift._assertionFailure(_: Swift.StaticString, _: Swift.StaticString, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 192
\f1\b \

\f0\b0     frame #4: 0x00000001850ec3bc libswiftCore.dylib`Swift._assertionFailure(_: Swift.StaticString, _: Swift.StaticString, file: Swift.StaticString, line: Swift.UInt, flags: Swift.UInt32) -> Swift.Never + 228
\f1\b \

\f0\b0   * frame #5: 0x00000001007dbc1c CTNotificationContent`CTContentSliderController.moveSlider(direction=1, self=0x000000012486ba00) at CTContentSliderController.swift:210:9
\f1\b \

\f0\b0     frame #6: 0x00000001007db3b8 CTNotificationContent`CTContentSliderController.showNext(self=0x000000012486ba00) at CTContentSliderController.swift:182:9
\f1\b \

\f0\b0     frame #7: 0x00000001007db3e8 CTNotificationContent`@objc CTContentSliderController.showNext() at <compiler-generated>:0
\f1\b \

\f0\b0     frame #8: 0x0000000182048e58 Foundation`__NSFireTimer + 64
\f1\b \

\f0\b0     frame #9: 0x00000001809afc58 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 28
\f1\b \

\f0\b0     frame #10: 0x00000001809394e8 CoreFoundation`__CFRunLoopDoTimer + 1008
\f1\b \

\f0\b0     frame #11: 0x00000001809340a0 CoreFoundation`__CFRunLoopDoTimers + 316
\f1\b \

\f0\b0     frame #12: 0x0000000180913d94 CoreFoundation`__CFRunLoopRun + 1964
\f1\b \

\f0\b0     frame #13: 0x0000000180926c30 CoreFoundation`CFRunLoopRunSpecific + 572
\f1\b \

\f0\b0     frame #14: 0x00000001a1341988 GraphicsServices`GSEventRunModal + 160
\f1\b \

\f0\b0     frame #15: 0x0000000183121c50 UIKitCore`-[UIApplication _run] + 1080
\f1\b \

\f0\b0     frame #16: 0x0000000182ebb3d0 UIKitCore`UIApplicationMain + 336
\f1\b \

\f0\b0     frame #17: 0x00000001dbac6f14 libxpc.dylib`_xpc_objc_main + 440
\f1\b \

\f0\b0     frame #18: 0x00000001dbac9128 libxpc.dylib`xpc_main + 152
\f1\b \

\f0\b0     frame #19: 0x0000000182075fcc Foundation`-[NSXPCListener resume] + 292
\f1\b \

\f0\b0     frame #20: 0x00000001be1ee818 PlugInKit`___lldb_unnamed_symbol896 + 396
\f1\b \

\f0\b0     frame #21: 0x00000001be1d8f98 PlugInKit`___lldb_unnamed_symbol444 + 572
\f1\b \

\f0\b0     frame #22: 0x00000001be1d7ff4 PlugInKit`___lldb_unnamed_symbol433 + 20
\f1\b \

\f0\b0     frame #23: 0x00000001c9eef3bc ExtensionFoundation`EXExtensionMain + 296
\f1\b \

\f0\b0     frame #24: 0x00000001820d550c Foundation`NSExtensionMain + 216
\f1\b \

\f0\b0     frame #25: 0x00000001008c43d0 dyld`start + 444}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.