fix:1、更换sdk

This commit is contained in:
2026-07-14 09:49:24 +08:00
parent 4187297e82
commit 8435b6e676
667 changed files with 36728 additions and 23022 deletions
@@ -0,0 +1,22 @@
//
// UnityAppController+Notifications.h
// iOS.notifications
//
#if TARGET_OS_IOS
#import "UnityAppController.h"
#include "Classes/PluginBase/LifeCycleListener.h"
#include "Classes/PluginBase/AppDelegateListener.h"
@interface UnityAppController (Notifications)
@end
@interface UnityNotificationLifeCycleManager : NSObject
+ (instancetype)sharedInstance;
@end
#endif
@@ -0,0 +1,44 @@
fileFormatVersion: 2
guid: 16485d365daaf42668d353cf0a47af00
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude iOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,93 @@
//
// UnityAppController+Notifications.m
// iOS.notifications
//
#if TARGET_OS_IOS
#import <objc/runtime.h>
#import "UnityNotificationManager.h"
#import "UnityAppController+Notifications.h"
@implementation UnityNotificationLifeCycleManager
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[UnityNotificationLifeCycleManager sharedInstance];
});
}
+ (instancetype)sharedInstance;
{
static UnityNotificationLifeCycleManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[UnityNotificationLifeCycleManager alloc] init];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserverForName: UIApplicationDidBecomeActiveNotification
object: nil
queue: [NSOperationQueue mainQueue]
usingBlock:^(NSNotification *notification) {
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
[manager updateScheduledNotificationList];
[manager updateDeliveredNotificationList];
[manager updateNotificationSettings];
}];
[nc addObserverForName: UIApplicationDidEnterBackgroundNotification
object: nil
queue: [NSOperationQueue mainQueue]
usingBlock:^(NSNotification *notification) {
[UnityNotificationManager sharedInstance].lastReceivedNotification = NULL;
}];
[nc addObserverForName: kUnityWillFinishLaunchingWithOptions
object: nil
queue: [NSOperationQueue mainQueue]
usingBlock:^(NSNotification *notification) {
[UNUserNotificationCenter currentNotificationCenter].delegate = [UnityNotificationManager sharedInstance];
BOOL authorizeOnLaunch = [[[NSBundle mainBundle] objectForInfoDictionaryKey: @"UnityNotificationRequestAuthorizationOnAppLaunch"] boolValue];
BOOL supportsPushNotification = [[[NSBundle mainBundle] objectForInfoDictionaryKey: @"UnityAddRemoteNotificationCapability"] boolValue];
BOOL registerRemoteOnLaunch = supportsPushNotification == YES ?
[[[NSBundle mainBundle] objectForInfoDictionaryKey: @"UnityNotificationRequestAuthorizationForRemoteNotificationsOnAppLaunch"] boolValue] : NO;
NSInteger defaultAuthorizationOptions = [[[NSBundle mainBundle] objectForInfoDictionaryKey: @"UnityNotificationDefaultAuthorizationOptions"] integerValue];
if (defaultAuthorizationOptions <= 0)
defaultAuthorizationOptions = (UNAuthorizationOptionSound + UNAuthorizationOptionAlert + UNAuthorizationOptionBadge);
if (authorizeOnLaunch)
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
[manager requestAuthorization: defaultAuthorizationOptions withRegisterRemote: registerRemoteOnLaunch forRequest: NULL];
}
}];
[nc addObserverForName: kUnityDidRegisterForRemoteNotificationsWithDeviceToken
object: nil
queue: [NSOperationQueue mainQueue]
usingBlock:^(NSNotification *notification) {
NSLog(@"didRegisterForRemoteNotificationsWithDeviceToken");
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
[manager finishRemoteNotificationRegistration: UNAuthorizationStatusAuthorized notification: notification];
}];
[nc addObserverForName: kUnityDidFailToRegisterForRemoteNotificationsWithError
object: nil
queue: [NSOperationQueue mainQueue]
usingBlock:^(NSNotification *notification) {
NSLog(@"didFailToRegisterForRemoteNotificationsWithError");
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
[manager finishRemoteNotificationRegistration: UNAuthorizationStatusDenied notification: notification];
}];
});
return sharedInstance;
}
@end
#endif
@@ -0,0 +1,34 @@
fileFormatVersion: 2
guid: a1fc929ae85b245fcadbb125623bc498
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,116 @@
//
// UnityNotificationData.h
// iOS.notifications
//
#if TARGET_OS_IOS
#ifndef UnityNotificationData_h
#define UnityNotificationData_h
enum triggerType
{
TIME_TRIGGER = 0,
CALENDAR_TRIGGER = 10,
LOCATION_TRIGGER = 20,
PUSH_TRIGGER = 3,
UNKNOWN_TRIGGER = -1,
};
enum UnitySoundType
{
kSoundTypeDefault = 0,
kSoundTypeCritical = 1,
kSoundTypeRingtone = 2,
kSoundTypeNone = 4,
};
enum UnityNotificationInterruptionLevel
{
kInterruptionLevelActive = 0,
kInterruptionLevelCritical = 1,
kInterruptionLevelPassive = 2,
kInterruptionLevelTimeSensitive = 3,
};
typedef struct iOSNotificationData
{
char* identifier;
char* title;
char* body;
int badge;
char* subtitle;
char* categoryIdentifier;
char* threadIdentifier;
int soundType;
float soundVolume;
char* soundName;
int interruptionLevel;
double relevanceScore;
void* userInfo;
void* attachments;
// Trigger
int triggerType; //0 - time, 1 - calendar, 2 - location, 3 - push.
union
{
struct
{
int interval;
unsigned char repeats;
} timeInterval;
struct
{
int year;
int month;
int day;
int hour;
int minute;
int second;
unsigned char repeats;
} calendar;
struct
{
double latitude;
double longitude;
float radius;
unsigned char notifyOnEntry;
unsigned char notifyOnExit;
unsigned char repeats;
} location;
} trigger;
} iOSNotificationData;
typedef struct iOSNotificationAuthorizationData
{
int granted;
const char* error;
const char* deviceToken;
} iOSNotificationAuthorizationData;
typedef struct NotificationSettingsData
{
int authorizationStatus;
int notificationCenterSetting;
int lockScreenSetting;
int carPlaySetting;
int alertSetting;
int badgeSetting;
int soundSetting;
int alertStyle;
int showPreviewsSetting;
} NotificationSettingsData;
typedef void (*NotificationDataReceivedResponse)(iOSNotificationData data);
typedef void (*AuthorizationRequestResponse) (void* request, struct iOSNotificationAuthorizationData data);
NotificationSettingsData UNNotificationSettingsToNotificationSettingsData(UNNotificationSettings* settings);
iOSNotificationData UNNotificationRequestToiOSNotificationData(UNNotificationRequest* request);
void freeiOSNotificationData(iOSNotificationData* notificationData);
#endif /* UnityNotificationData_h */
#endif
@@ -0,0 +1,44 @@
fileFormatVersion: 2
guid: 7609257501e8b48f98214be5de026339
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude iOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,315 @@
//
// UnityNotificationData.m
// iOS.notifications
//
#if TARGET_OS_IOS
#import <Foundation/Foundation.h>
#import <UserNotifications/UserNotifications.h>
#if UNITY_USES_LOCATION
#import <CoreLocation/CoreLocation.h>
#endif
#import "UnityNotificationData.h"
static NSString* ParseNotificationDataObject(id obj)
{
if ([obj isKindOfClass: [NSString class]])
return obj;
else if ([obj isKindOfClass: [NSNumber class]])
{
NSNumber* numberVal = obj;
if (CFBooleanGetTypeID() == CFGetTypeID((__bridge CFTypeRef)(obj)))
return numberVal.boolValue ? @"true" : @"false";
return numberVal.stringValue;
}
else if ([NSJSONSerialization isValidJSONObject: obj])
{
NSError* error;
NSData* data = [NSJSONSerialization dataWithJSONObject: obj options: NSJSONWritingPrettyPrinted error: &error];
if (data)
{
NSString* v = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
return v;
}
else
{
NSLog(@"Failed parsing notification userInfo value: %@", error);
}
}
else
NSLog(@"Failed parsing notification userInfo value");
NSObject* o = obj;
return o.description;
}
NotificationSettingsData UNNotificationSettingsToNotificationSettingsData(UNNotificationSettings* settings)
{
NotificationSettingsData settingsData;
settingsData.alertSetting = (int)settings.alertSetting;
settingsData.authorizationStatus = (int)settings.authorizationStatus;
settingsData.badgeSetting = (int)settings.badgeSetting;
settingsData.carPlaySetting = (int)settings.carPlaySetting;
settingsData.lockScreenSetting = (int)settings.lockScreenSetting;
settingsData.notificationCenterSetting = (int)settings.notificationCenterSetting;
settingsData.soundSetting = (int)settings.soundSetting;
settingsData.alertStyle = (int)settings.alertStyle;
settingsData.showPreviewsSetting = (int)settings.showPreviewsSetting;
return settingsData;
}
void initiOSNotificationData(iOSNotificationData* notificationData)
{
notificationData->title = NULL;
notificationData->body = NULL;
notificationData->badge = 0;
notificationData->subtitle = NULL;
notificationData->categoryIdentifier = NULL;
notificationData->threadIdentifier = NULL;
notificationData->soundType = kSoundTypeDefault;
notificationData->soundVolume = -1.0f;
notificationData->soundName = NULL;
notificationData->interruptionLevel = kInterruptionLevelActive;
notificationData->relevanceScore = 0;
notificationData->triggerType = PUSH_TRIGGER;
notificationData->userInfo = NULL;
}
static enum UnityNotificationInterruptionLevel InterruptionLevelToUnity(UNNotificationInterruptionLevel level)
API_AVAILABLE(ios(15.0))
{
switch (level)
{
case UNNotificationInterruptionLevelActive:
default:
return kInterruptionLevelActive;
case UNNotificationInterruptionLevelCritical:
return kInterruptionLevelCritical;
case UNNotificationInterruptionLevelPassive:
return kInterruptionLevelPassive;
case UNNotificationInterruptionLevelTimeSensitive:
return kInterruptionLevelTimeSensitive;
}
}
static void parseCustomizedData(iOSNotificationData* notificationData, UNNotificationRequest* request)
{
NSDictionary* userInfo = request.content.userInfo;
NSObject* customizedData = [userInfo objectForKey: @"data"];
// For local notifications, the customzied data is always a string.
if (notificationData->triggerType == TIME_TRIGGER || notificationData->triggerType == CALENDAR_TRIGGER || customizedData == nil)
{
notificationData->userInfo = (__bridge_retained void*)userInfo;
return;
}
// For push notifications, we have to handle more cases.
NSString* strData = ParseNotificationDataObject(customizedData);
if (strData == nil)
NSLog(@"Failed parsing notification userInfo[\"data\"]");
NSMutableDictionary* parsedUserInfo = [NSMutableDictionary dictionaryWithDictionary: userInfo];
[parsedUserInfo setValue: strData forKey: @"data"];
notificationData->userInfo = (__bridge_retained void*)parsedUserInfo;
}
iOSNotificationData UNNotificationRequestToiOSNotificationData(UNNotificationRequest* request)
{
iOSNotificationData notificationData;
initiOSNotificationData(&notificationData);
UNNotificationContent* content = request.content;
notificationData.identifier = strdup([request.identifier UTF8String]);
if (content.title != nil && content.title.length > 0)
notificationData.title = strdup([content.title UTF8String]);
if (content.body != nil && content.body.length > 0)
notificationData.body = strdup([content.body UTF8String]);
notificationData.badge = [content.badge intValue];
if (content.subtitle != nil && content.subtitle.length > 0)
notificationData.subtitle = strdup([content.subtitle UTF8String]);
if (content.categoryIdentifier != nil && content.categoryIdentifier.length > 0)
notificationData.categoryIdentifier = strdup([content.categoryIdentifier UTF8String]);
if (content.threadIdentifier != nil && content.threadIdentifier.length > 0)
notificationData.threadIdentifier = strdup([content.threadIdentifier UTF8String]);
if (@available(iOS 15.0, *))
{
notificationData.interruptionLevel = InterruptionLevelToUnity(content.interruptionLevel);
notificationData.relevanceScore = content.relevanceScore;
}
else
{
notificationData.interruptionLevel = kInterruptionLevelActive;
notificationData.relevanceScore = 0;
}
if ([request.trigger isKindOfClass: [UNTimeIntervalNotificationTrigger class]])
{
notificationData.triggerType = TIME_TRIGGER;
UNTimeIntervalNotificationTrigger* timeTrigger = (UNTimeIntervalNotificationTrigger*)request.trigger;
notificationData.trigger.timeInterval.interval = timeTrigger.timeInterval;
notificationData.trigger.timeInterval.repeats = timeTrigger.repeats;
}
else if ([request.trigger isKindOfClass: [UNCalendarNotificationTrigger class]])
{
notificationData.triggerType = CALENDAR_TRIGGER;
UNCalendarNotificationTrigger* calendarTrigger = (UNCalendarNotificationTrigger*)request.trigger;
NSDateComponents* date = calendarTrigger.dateComponents;
notificationData.trigger.calendar.year = (int)date.year;
notificationData.trigger.calendar.month = (int)date.month;
notificationData.trigger.calendar.day = (int)date.day;
notificationData.trigger.calendar.hour = (int)date.hour;
notificationData.trigger.calendar.minute = (int)date.minute;
notificationData.trigger.calendar.second = (int)date.second;
notificationData.trigger.calendar.repeats = (int)calendarTrigger.repeats;
}
else if ([request.trigger isKindOfClass: [UNLocationNotificationTrigger class]])
{
#if UNITY_USES_LOCATION
notificationData.triggerType = LOCATION_TRIGGER;
UNLocationNotificationTrigger* locationTrigger = (UNLocationNotificationTrigger*)request.trigger;
CLCircularRegion *region = (CLCircularRegion*)locationTrigger.region;
notificationData.trigger.location.latitude = region.center.latitude;
notificationData.trigger.location.longitude = region.center.longitude;
notificationData.trigger.location.radius = region.radius;
notificationData.trigger.location.notifyOnExit = region.notifyOnEntry;
notificationData.trigger.location.notifyOnEntry = region.notifyOnExit;
notificationData.trigger.location.repeats = locationTrigger.repeats;
#endif
}
else if ([request.trigger isKindOfClass: [UNPushNotificationTrigger class]])
{
notificationData.triggerType = PUSH_TRIGGER;
}
else
notificationData.triggerType = UNKNOWN_TRIGGER;
parseCustomizedData(&notificationData, request);
notificationData.attachments = (__bridge_retained void*)request.content.attachments;
return notificationData;
}
void freeiOSNotificationData(iOSNotificationData* notificationData)
{
if (notificationData->identifier != NULL)
free(notificationData->identifier);
if (notificationData->title != NULL)
free(notificationData->title);
if (notificationData->body != NULL)
free(notificationData->body);
if (notificationData->subtitle != NULL)
free(notificationData->subtitle);
if (notificationData->categoryIdentifier != NULL)
free(notificationData->categoryIdentifier);
if (notificationData->threadIdentifier != NULL)
free(notificationData->threadIdentifier);
if (notificationData->soundName != NULL)
free(notificationData->soundName);
if (notificationData->userInfo != NULL)
{
NSDictionary* userInfo = (__bridge_transfer NSDictionary*)notificationData->userInfo;
userInfo = nil;
}
if (notificationData->attachments != NULL)
{
NSArray* attachments = (__bridge_transfer NSArray*)notificationData->attachments;
attachments = nil;
}
}
void* _AddItemToNSDictionary(void* dict, const char* key, const char* value)
{
NSDictionary* dictionary;
if (dict != NULL)
dictionary = (__bridge NSDictionary*)dict;
else
{
dictionary = [[NSMutableDictionary alloc] init];
dict = (__bridge_retained void*)dictionary;
}
NSString* k = [NSString stringWithUTF8String: key];
NSString* v = value ? [NSString stringWithUTF8String: value] : @"";
[dictionary setValue: v forKey: k];
return dict;
}
void* _AddAttachmentToNSArray(void* arr, const char* attId, const char* url, void** outError)
{
*outError = NULL;
NSString* attachmentId = nil;
if (attId != NULL)
attachmentId = [NSString stringWithUTF8String: attId];
NSURL* uri = [NSURL URLWithString: [NSString stringWithUTF8String: url]];
NSError* error = nil;
UNNotificationAttachment* attachment = [UNNotificationAttachment attachmentWithIdentifier: attachmentId URL: uri options: nil error: &error];
if (attachment != nil)
{
NSMutableArray* array;
if (arr != NULL)
array = (__bridge NSMutableArray*)arr;
else
{
array = [[NSMutableArray alloc] init];
arr = (__bridge_retained void*)array;
}
[array addObject: attachment];
return arr;
}
if (error != nil)
*outError = (__bridge_retained void*)error;
return NULL;
}
void _ReadNSDictionary(void* csDict, void* nsDict, void (*callback)(void* csDcit, const char*, const char*))
{
NSDictionary* dict = (__bridge NSDictionary*)nsDict;
[dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSString* k = key;
NSString* v = ParseNotificationDataObject(obj);
if (v != nil)
callback(csDict, k.UTF8String, v.UTF8String);
else
NSLog(@"Failed to parse value for key '%@'", key);
}];
}
void _ReadAttachmentsNSArray(void* csList, void* nsArray, void (*callback)(void*, const char*, const char*))
{
NSArray<UNNotificationAttachment*>* attachments = (__bridge NSArray<UNNotificationAttachment*>*)nsArray;
[attachments enumerateObjectsUsingBlock:^(UNNotificationAttachment * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSString* idr = obj.identifier;
NSString* url = obj.URL.absoluteString;
callback(csList, idr.UTF8String, url.UTF8String);
}];
}
#endif
@@ -0,0 +1,37 @@
fileFormatVersion: 2
guid: a44b320ceb3374077b14c5d3a8f0037f
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,42 @@
//
// UnityNotificationManager.h
// iOS.notifications
//
#if TARGET_OS_IOS
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>
#import "UnityNotificationData.h"
@interface UnityNotificationManager : NSObject<UNUserNotificationCenterDelegate>
@property UNNotificationSettings* cachedNotificationSettings;
@property NotificationDataReceivedResponse onNotificationReceivedCallback;
@property NotificationDataReceivedResponse onRemoteNotificationReceivedCallback;
@property AuthorizationRequestResponse onAuthorizationCompletionCallback;
@property NSArray<UNNotificationRequest *> * cachedPendingNotificationRequests;
@property NSArray<UNNotification *> * cachedDeliveredNotifications;
@property (nonatomic) UNNotification* lastReceivedNotification;
@property NSString* lastRespondedNotificationAction;
@property NSString* lastRespondedNotificationUserText;
+ (instancetype)sharedInstance;
- (id)init;
- (void)finishAuthorization:(struct iOSNotificationAuthorizationData*)authData forRequest:(void*)request;
- (void)finishRemoteNotificationRegistration:(UNAuthorizationStatus)status notification:(NSNotification*)notification;
- (void)updateScheduledNotificationList;
- (void)updateDeliveredNotificationList;
- (void)updateNotificationSettings;
- (void)requestAuthorization:(NSInteger)authorizationOptions withRegisterRemote:(BOOL)registerRemote forRequest:(void*)request;
- (void)unregisterForRemoteNotifications;
- (void)scheduleLocalNotification:(iOSNotificationData*)data;
@end
#endif
@@ -0,0 +1,44 @@
fileFormatVersion: 2
guid: cef86cd5b8e5d4dc6acd332b2199c6c8
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude iOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,420 @@
//
// UnityNotificationManager.m
// iOS.notifications
//
#if TARGET_OS_IOS
#import "UnityNotificationManager.h"
#if UNITY_USES_LOCATION
#import <CoreLocation/CoreLocation.h>
#endif
@implementation UnityNotificationManager
{
NSLock* _lock;
UNAuthorizationStatus _remoteNotificationsRegistered;
NSInteger _remoteNotificationForegroundPresentationOptions;
NSString* _deviceToken;
NSPointerArray* _pendingRemoteAuthRequests;
}
+ (instancetype)sharedInstance
{
static UnityNotificationManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[UnityNotificationManager alloc] init];
});
[sharedInstance updateNotificationSettings];
[sharedInstance updateScheduledNotificationList];
return sharedInstance;
}
- (id)init
{
_lock = [[NSLock alloc] init];
_remoteNotificationsRegistered = UNAuthorizationStatusNotDetermined;
_deviceToken = nil;
_pendingRemoteAuthRequests = nil;
_remoteNotificationForegroundPresentationOptions = [[[NSBundle mainBundle] objectForInfoDictionaryKey: @"UnityRemoteNotificationForegroundPresentationOptions"] integerValue];
return self;
}
- (void)finishAuthorization:(struct iOSNotificationAuthorizationData*)authData forRequest:(void*)request
{
if (self.onAuthorizationCompletionCallback != NULL && request)
self.onAuthorizationCompletionCallback(request, *authData);
}
- (void)finishRemoteNotificationRegistration:(UNAuthorizationStatus)status notification:(NSNotification*)notification
{
struct iOSNotificationAuthorizationData authData;
authData.granted = status == UNAuthorizationStatusAuthorized;
authData.error = NULL;
authData.deviceToken = NULL;
NSString* deviceToken = nil;
if (authData.granted)
{
deviceToken = [UnityNotificationManager deviceTokenFromNotification: notification];
authData.deviceToken = [deviceToken UTF8String];
}
[_lock lock];
_remoteNotificationsRegistered = status;
_deviceToken = deviceToken;
NSPointerArray* pointers = _pendingRemoteAuthRequests;
_pendingRemoteAuthRequests = nil;
[_lock unlock];
while (pointers.count > 0)
{
unsigned long idx = pointers.count - 1;
void* request = [pointers pointerAtIndex: idx];
[pointers removePointerAtIndex: idx];
[self finishAuthorization: &authData forRequest: request];
}
}
- (void)requestAuthorization:(NSInteger)authorizationOptions withRegisterRemote:(BOOL)registerRemote forRequest:(void*)request
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
BOOL supportsPushNotification = [[[NSBundle mainBundle] objectForInfoDictionaryKey: @"UnityAddRemoteNotificationCapability"] boolValue];
registerRemote = registerRemote && supportsPushNotification;
[center requestAuthorizationWithOptions: authorizationOptions completionHandler:^(BOOL granted, NSError * _Nullable error)
{
BOOL authorizationRequestFinished = YES;
struct iOSNotificationAuthorizationData authData;
authData.granted = granted;
authData.error = [[error localizedDescription]cStringUsingEncoding: NSUTF8StringEncoding];
authData.deviceToken = "";
if (granted)
{
[_lock lock];
if (registerRemote && _remoteNotificationsRegistered == UNAuthorizationStatusNotDetermined)
{
authorizationRequestFinished = NO;
if (request)
{
if (_pendingRemoteAuthRequests == nil)
_pendingRemoteAuthRequests = [NSPointerArray pointerArrayWithOptions: NSPointerFunctionsOpaqueMemory];
[_pendingRemoteAuthRequests addPointer: request];
}
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] registerForRemoteNotifications];
});
}
else
authData.deviceToken = [_deviceToken UTF8String];
[_lock unlock];
}
else
NSLog(@"Requesting notification authorization failed with: %@", error);
if (authorizationRequestFinished)
[self finishAuthorization: &authData forRequest: request];
[self updateNotificationSettings];
}];
}
- (void)unregisterForRemoteNotifications
{
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
_remoteNotificationsRegistered = UNAuthorizationStatusNotDetermined;
}
+ (NSString*)deviceTokenFromNotification:(NSNotification*)notification
{
NSData* deviceTokenData;
if ([notification.userInfo isKindOfClass: [NSData class]])
deviceTokenData = (NSData*)notification.userInfo;
else
return nil;
NSUInteger len = deviceTokenData.length;
if (len == 0)
return nil;
const unsigned char *buffer = deviceTokenData.bytes;
NSMutableString *str = [NSMutableString stringWithCapacity: (len * 2)];
for (int i = 0; i < len; ++i)
[str appendFormat: @"%02x", buffer[i]];
return str;
}
// Called when a notification is delivered to a foreground app.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
iOSNotificationData notificationData;
BOOL haveNotificationData = NO;
if (self.onNotificationReceivedCallback != NULL)
{
notificationData = UNNotificationRequestToiOSNotificationData(notification.request);
haveNotificationData = YES;
self.onNotificationReceivedCallback(notificationData);
}
BOOL showInForeground;
NSInteger presentationOptions;
showInForeground = [[notification.request.content.userInfo objectForKey: @"showInForeground"] boolValue];
if ([notification.request.trigger isKindOfClass: [UNPushNotificationTrigger class]])
{
presentationOptions = _remoteNotificationForegroundPresentationOptions;
if (self.onRemoteNotificationReceivedCallback != NULL)
{
if (!haveNotificationData)
{
notificationData = UNNotificationRequestToiOSNotificationData(notification.request);
haveNotificationData = YES;
}
self.onRemoteNotificationReceivedCallback(notificationData);
}
else
{
showInForeground = YES;
}
}
else
{
presentationOptions = [[notification.request.content.userInfo objectForKey: @"showInForegroundPresentationOptions"] intValue];
}
if (haveNotificationData)
freeiOSNotificationData(&notificationData);
if (showInForeground)
completionHandler(presentationOptions);
else
completionHandler(UNNotificationPresentationOptionNone);
[[UnityNotificationManager sharedInstance] updateDeliveredNotificationList];
}
// Called to let your app know which action was selected by the user for a given notification.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(nonnull void(^)(void))completionHandler
{
self.lastReceivedNotification = response.notification;
self.lastRespondedNotificationAction = response.actionIdentifier;
if ([response isKindOfClass: UNTextInputNotificationResponse.class])
{
UNTextInputNotificationResponse* resp = (UNTextInputNotificationResponse*)response;
self.lastRespondedNotificationUserText = resp.userText;
}
else
self.lastRespondedNotificationUserText = nil;
completionHandler();
[[UnityNotificationManager sharedInstance] updateDeliveredNotificationList];
}
- (void)updateScheduledNotificationList
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> * _Nonnull requests) {
self.cachedPendingNotificationRequests = requests;
}];
}
- (void)updateDeliveredNotificationList
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
self.cachedDeliveredNotifications = notifications;
}];
}
- (void)updateNotificationSettings
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
self.cachedNotificationSettings = settings;
}];
}
bool validateAuthorizationStatus(UnityNotificationManager* manager)
{
UNAuthorizationStatus authorizationStatus = manager.cachedNotificationSettings.authorizationStatus;
if (authorizationStatus == UNAuthorizationStatusAuthorized)
return true;
if (authorizationStatus == UNAuthorizationStatusProvisional)
return true;
NSLog(@"Attempting to schedule a local notification without authorization, please call RequestAuthorization first.");
return false;
}
- (void)scheduleLocalNotification:(iOSNotificationData*)data
{
if (!validateAuthorizationStatus(self))
return;
assert(self.onNotificationReceivedCallback != NULL);
NSDictionary* userInfo = (__bridge_transfer NSDictionary*)data->userInfo;
data->userInfo = NULL;
// Convert from iOSNotificationData to UNMutableNotificationContent.
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
NSString* dataTitle = data->title ? [NSString stringWithUTF8String: data->title] : [NSString string];
NSString* dataBody = data->body ? [NSString stringWithUTF8String: data->body] : [NSString string];
content.title = [NSString localizedUserNotificationStringForKey: dataTitle arguments: nil];
content.body = [NSString localizedUserNotificationStringForKey: dataBody arguments: nil];
content.userInfo = userInfo;
if (data->badge >= 0)
content.badge = [NSNumber numberWithInt: data->badge];
if (data->subtitle != NULL)
content.subtitle = [NSString localizedUserNotificationStringForKey: [NSString stringWithUTF8String: data->subtitle] arguments: nil];
if (data->categoryIdentifier != NULL)
content.categoryIdentifier = [NSString stringWithUTF8String: data->categoryIdentifier];
if (data->threadIdentifier != NULL)
content.threadIdentifier = [NSString stringWithUTF8String: data->threadIdentifier];
UNNotificationSound* sound = [self soundForNotification: data];
if (sound != nil)
content.sound = sound;
if (@available(iOS 15.0, *))
{
content.interruptionLevel = [self unityInterruptionLevelToIos: data->interruptionLevel];
content.relevanceScore = data->relevanceScore;
}
content.attachments = (__bridge_transfer NSArray<UNNotificationAttachment*>*)data->attachments;
data->attachments = NULL;
NSString* identifier = [NSString stringWithUTF8String: data->identifier];
// Generate UNNotificationTrigger from iOSNotificationData.
UNNotificationTrigger* trigger;
if (data->triggerType == TIME_TRIGGER)
{
trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval: data->trigger.timeInterval.interval repeats: data->trigger.timeInterval.repeats];
}
else if (data->triggerType == CALENDAR_TRIGGER)
{
NSDateComponents* date = [[NSDateComponents alloc] init];
if (data->trigger.calendar.year >= 0)
date.year = data->trigger.calendar.year;
if (data->trigger.calendar.month >= 0)
date.month = data->trigger.calendar.month;
if (data->trigger.calendar.day >= 0)
date.day = data->trigger.calendar.day;
if (data->trigger.calendar.hour >= 0)
date.hour = data->trigger.calendar.hour;
if (data->trigger.calendar.minute >= 0)
date.minute = data->trigger.calendar.minute;
if (data->trigger.calendar.second >= 0)
date.second = data->trigger.calendar.second;
date.calendar = [NSCalendar calendarWithIdentifier: NSCalendarIdentifierGregorian];
if ([@"1" isEqualToString: [userInfo objectForKey: @"OriginalUtc"]])
date.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"UTC"];
trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents: date repeats: data->trigger.calendar.repeats];
NSLog(@"Notification will show after %f s.", ((UNCalendarNotificationTrigger*)trigger).nextTriggerDate.timeIntervalSinceNow);
}
else if (data->triggerType == LOCATION_TRIGGER)
{
#if UNITY_USES_LOCATION
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(data->trigger.location.latitude, data->trigger.location.longitude);
CLCircularRegion* region = [[CLCircularRegion alloc] initWithCenter: center
radius: data->trigger.location.radius identifier: identifier];
region.notifyOnEntry = data->trigger.location.notifyOnEntry;
region.notifyOnExit = data->trigger.location.notifyOnExit;
trigger = [UNLocationNotificationTrigger triggerWithRegion: region repeats: data->trigger.location.repeats];
#else
return;
#endif
}
else
{
return;
}
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier: identifier content: content trigger: trigger];
// Schedule the notification.
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest: request withCompletionHandler:^(NSError * _Nullable error) {
if (error != NULL)
NSLog(@"%@", [error localizedDescription]);
[self updateScheduledNotificationList];
}];
}
- (UNNotificationSound*)soundForNotification:(const iOSNotificationData*)data
{
NSString* soundName = nil;
if (data->soundName != NULL)
soundName = [NSString stringWithUTF8String: data->soundName];
switch (data->soundType)
{
case kSoundTypeNone:
return nil;
case kSoundTypeCritical:
if (soundName != nil)
{
if (data->soundVolume < 0)
return [UNNotificationSound criticalSoundNamed: soundName];
return [UNNotificationSound criticalSoundNamed: soundName withAudioVolume: data->soundVolume];
}
if (data->soundVolume >= 0)
return [UNNotificationSound defaultCriticalSoundWithAudioVolume: data->soundVolume];
return UNNotificationSound.defaultCriticalSound;
case kSoundTypeRingtone:
if (@available(iOS 15.2, *))
{
if (soundName != nil)
return [UNNotificationSound ringtoneSoundNamed: soundName];
return UNNotificationSound.defaultRingtoneSound;
}
// continue to default
case kSoundTypeDefault:
default:
if (soundName != nil)
return [UNNotificationSound soundNamed: soundName];
return UNNotificationSound.defaultSound;
}
}
- (UNNotificationInterruptionLevel)unityInterruptionLevelToIos:(int)level
API_AVAILABLE(ios(15.0))
{
switch (level)
{
case kInterruptionLevelActive:
return UNNotificationInterruptionLevelActive;
case kInterruptionLevelCritical:
return UNNotificationInterruptionLevelCritical;
case kInterruptionLevelPassive:
return UNNotificationInterruptionLevelPassive;
case kInterruptionLevelTimeSensitive:
return UNNotificationInterruptionLevelTimeSensitive;
default:
return UNNotificationInterruptionLevelActive;
}
}
@end
#endif
@@ -0,0 +1,34 @@
fileFormatVersion: 2
guid: d15de7aefd6e94456967d000884a11ea
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,362 @@
//
// UnityNotificationWrapper.m
// iOS.notifications
//
#if TARGET_OS_IOS
#import <Foundation/Foundation.h>
#import "UnityNotificationManager.h"
int _NativeSizeof_iOSNotificationAuthorizationData()
{
return sizeof(iOSNotificationAuthorizationData);
}
int _NativeSizeof_iOSNotificationData()
{
return sizeof(iOSNotificationData);
}
int _NativeSizeof_NotificationSettingsData()
{
return sizeof(NotificationSettingsData);
}
void _FreeUnmanagediOSNotificationDataArray(iOSNotificationData* ptr, int count)
{
for (int i = 0; i < count; ++i)
freeiOSNotificationData(&ptr[i]);
free(ptr);
}
void _SetAuthorizationRequestReceivedDelegate(AuthorizationRequestResponse callback)
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
manager.onAuthorizationCompletionCallback = callback;
}
void _SetNotificationReceivedDelegate(NotificationDataReceivedResponse callback)
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
manager.onNotificationReceivedCallback = callback;
}
void _SetRemoteNotificationReceivedDelegate(NotificationDataReceivedResponse callback)
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
manager.onRemoteNotificationReceivedCallback = callback;
}
void _RequestAuthorization(void* request, int options, BOOL registerRemote)
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
[manager requestAuthorization: options withRegisterRemote: registerRemote forRequest: request];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = manager;
}
int _RegisteredForRemoteNotifications()
{
return [UIApplication sharedApplication].registeredForRemoteNotifications;
}
void _UnregisterForRemoteNotifications()
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
[manager unregisterForRemoteNotifications];
}
void _ScheduleLocalNotification(iOSNotificationData data)
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
[manager scheduleLocalNotification: &data];
}
NotificationSettingsData _GetNotificationSettings()
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
return UNNotificationSettingsToNotificationSettingsData(manager.cachedNotificationSettings);
}
iOSNotificationData* _GetScheduledNotificationDataArray(int* count)
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
NSArray<UNNotificationRequest*>* pendingNotificationRequests = manager.cachedPendingNotificationRequests;
if (pendingNotificationRequests == nil)
{
*count = 0;
return NULL;
}
*count = (int)pendingNotificationRequests.count;
if (*count == 0)
return NULL;
iOSNotificationData* ret = (iOSNotificationData*)malloc(*count * sizeof(iOSNotificationData));
for (int i = 0; i < *count; ++i)
{
UNNotificationRequest *request = pendingNotificationRequests[i];
ret[i] = UNNotificationRequestToiOSNotificationData(request);
}
return ret;
}
iOSNotificationData* _GetDeliveredNotificationDataArray(int* count)
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
NSArray<UNNotification*>* deliveredNotifications = manager.cachedDeliveredNotifications;
if (deliveredNotifications == nil)
{
*count = 0;
return NULL;
}
*count = (int)deliveredNotifications.count;
if (*count == 0)
return NULL;
iOSNotificationData* ret = (iOSNotificationData*)malloc(*count * sizeof(iOSNotificationData));
for (int i = 0; i < *count; ++i)
{
UNNotification* notification = deliveredNotifications[i];
ret[i] = UNNotificationRequestToiOSNotificationData(notification.request);
}
return ret;
}
void _RemoveScheduledNotification(const char* identifier)
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center removePendingNotificationRequestsWithIdentifiers: @[[NSString stringWithUTF8String: identifier]]];
[[UnityNotificationManager sharedInstance] updateScheduledNotificationList];
}
void _RemoveAllScheduledNotifications()
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center removeAllPendingNotificationRequests];
[[UnityNotificationManager sharedInstance] updateScheduledNotificationList];
}
void _RemoveDeliveredNotification(const char* identifier)
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center removeDeliveredNotificationsWithIdentifiers: @[[NSString stringWithUTF8String: identifier]]];
[[UnityNotificationManager sharedInstance] updateDeliveredNotificationList];
}
void _RemoveAllDeliveredNotifications()
{
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center removeAllDeliveredNotifications];
[[UnityNotificationManager sharedInstance] updateDeliveredNotificationList];
}
void _SetApplicationBadge(long badge)
{
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: badge];
}
long _GetApplicationBadge()
{
return [UIApplication sharedApplication].applicationIconBadgeNumber;
}
bool _GetAppOpenedUsingNotification()
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
return manager.lastReceivedNotification != NULL;
}
iOSNotificationData* _GetLastNotificationData()
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
UNNotification* notification = manager.lastReceivedNotification;
if (notification == nil)
return NULL;
UNNotificationRequest* request = notification.request;
if (request == nil)
return NULL;
iOSNotificationData* ret = (iOSNotificationData*)malloc(sizeof(iOSNotificationData));
*ret = UNNotificationRequestToiOSNotificationData(request);
return ret;
}
const char* _GetLastRespondedNotificationAction()
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
NSString* action = manager.lastRespondedNotificationAction;
if (action == nil)
return NULL;
return strdup(action.UTF8String);
}
const char* _GetLastRespondedNotificationUserText()
{
UnityNotificationManager* manager = [UnityNotificationManager sharedInstance];
NSString* userText = manager.lastRespondedNotificationUserText;
if (userText == nil)
return NULL;
return strdup(userText.UTF8String);
}
static NSObject* CreateNotificationActionIcon(int iconType, const char* icon)
{
enum IconType
{
kIconTypeNone = 0,
kIconTypeSystemImageName = 1,
kIconTypeTemplateImageName = 2,
};
NSObject* actionIcon = nil;
if (@available(iOS 15.0, *))
{
if (icon != NULL && iconType != kIconTypeNone)
{
NSString* iconName = [NSString stringWithUTF8String: icon];
switch (iconType)
{
case kIconTypeSystemImageName:
actionIcon = [UNNotificationActionIcon iconWithSystemImageName: iconName];
break;
case kIconTypeTemplateImageName:
actionIcon = [UNNotificationActionIcon iconWithTemplateImageName: iconName];
break;
}
}
}
return actionIcon;
}
void* _CreateUNNotificationAction(const char* identifier, const char* title, int options, int iconType, const char* icon)
{
UNNotificationActionOptions opts = (UNNotificationActionOptions)options;
NSString* idr = [NSString stringWithUTF8String: identifier];
NSString* titl = [NSString stringWithUTF8String: title];
UNNotificationAction* action;
if (@available(iOS 15.0, *))
{
UNNotificationActionIcon* actionIcon = (UNNotificationActionIcon*)CreateNotificationActionIcon(iconType, icon);
action = [UNNotificationAction actionWithIdentifier: idr title: titl options: opts icon: actionIcon];
}
else
action = [UNNotificationAction actionWithIdentifier: idr title: titl options: opts];
return (__bridge_retained void*)action;
}
void* _CreateUNTextInputNotificationAction(const char* identifier, const char* title, int options, int iconType, const char* icon, const char* buttonTitle, const char* placeholder)
{
UNNotificationActionOptions opts = (UNNotificationActionOptions)options;
NSString* idr = [NSString stringWithUTF8String: identifier];
NSString* titl = [NSString stringWithUTF8String: title];
NSString* btnTitle = [NSString stringWithUTF8String: buttonTitle];
NSString* placeHolder = placeholder ? [NSString stringWithUTF8String: placeholder] : NULL;
UNTextInputNotificationAction* action;
if (@available(iOS 15.0, *))
{
UNNotificationActionIcon* actionIcon = (UNNotificationActionIcon*)CreateNotificationActionIcon(iconType, icon);
action = [UNTextInputNotificationAction actionWithIdentifier: idr title: titl options: opts icon: actionIcon textInputButtonTitle: btnTitle textInputPlaceholder: placeHolder];
}
else
action = [UNTextInputNotificationAction actionWithIdentifier: idr title: titl options: opts textInputButtonTitle: btnTitle textInputPlaceholder: placeHolder];
return (__bridge_retained void*)action;
}
void _ReleaseNSObject(void* obj)
{
NSObject* a = (__bridge_transfer NSObject*)obj;
a = nil;
}
const char* _NSErrorToMessage(void* error)
{
NSError* e = (__bridge_transfer NSError*)error;
NSString* msg = e.localizedDescription;
return strdup(msg.UTF8String);
}
void* _AddActionToNSArray(void* actions, void* action, int capacity)
{
NSMutableArray<UNNotificationAction*>* array;
void* ret = actions;
if (actions == NULL)
{
array = [NSMutableArray arrayWithCapacity: capacity];
ret = (__bridge_retained void*)array;
}
else
array = (__bridge NSMutableArray<UNNotificationAction*>*)actions;
UNNotificationAction* a = (__bridge UNNotificationAction*)action;
[array addObject: a];
return ret;
}
void* _AddStringToNSArray(void* array, const char* str, int capacity)
{
NSMutableArray<NSString*>* arr;
void* ret = array;
if (array == NULL)
{
arr = [NSMutableArray arrayWithCapacity: capacity];
ret = (__bridge_retained void*)arr;
}
else
arr = (__bridge NSMutableArray<NSString*>*)array;
NSString* s = [NSString stringWithUTF8String: str];
[arr addObject: s];
return ret;
}
void* _CreateUNNotificationCategory(const char* identifier, const char* hiddenPreviewsBodyPlaceholder, const char* summaryFormat,
int options, void* actions, void* intentIdentifiers)
{
NSString* idr = [NSString stringWithUTF8String: identifier];
NSString* placeholder = hiddenPreviewsBodyPlaceholder ? [NSString stringWithUTF8String: hiddenPreviewsBodyPlaceholder] : nil;
NSString* summary = summaryFormat ? [NSString stringWithUTF8String: summaryFormat] : nil;
NSArray<UNNotificationAction*>* acts = (__bridge_transfer NSArray<UNNotificationAction*>*)actions;
NSArray<NSString*>* intents = (__bridge_transfer NSArray<NSString*>*)intentIdentifiers;
UNNotificationCategoryOptions opts = (UNNotificationCategoryOptions)options;
UNNotificationCategory* category = [UNNotificationCategory categoryWithIdentifier: idr actions: acts intentIdentifiers: intents hiddenPreviewsBodyPlaceholder: placeholder categorySummaryFormat: summary options: opts];
return (__bridge_retained void*)category;
}
void* _AddCategoryToCategorySet(void* categorySet, void* category)
{
UNNotificationCategory* cat = (__bridge_transfer UNNotificationCategory*)category;
NSMutableSet<UNNotificationCategory*>* categories;
if (categorySet == NULL)
{
categories = [NSMutableSet setWithObject: cat];
return (__bridge_retained void*)categories;
}
categories = (__bridge NSMutableSet<UNNotificationCategory*>*)categorySet;
[categories addObject: cat];
return categorySet;
}
void _SetNotificationCategories(void* categorySet)
{
NSMutableSet<UNNotificationCategory*>* categories = (__bridge_transfer NSMutableSet<UNNotificationCategory*>*)categorySet;
[UNUserNotificationCenter.currentNotificationCenter setNotificationCategories: categories];
}
void _OpenNotificationSettings()
{
NSURL* url = [NSURL URLWithString: UIApplicationOpenSettingsURLString];
UIApplication* app = [UIApplication sharedApplication];
if ([app canOpenURL: url])
[app openURL: url options: @{} completionHandler: nil];
}
#endif
@@ -0,0 +1,34 @@
fileFormatVersion: 2
guid: ce0614a77cbc545b99eca271d5c36809
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant: