fix:1、sdk更换。2、修复bug
This commit is contained in:
+22
@@ -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
|
||||
+44
@@ -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:
|
||||
+93
@@ -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
|
||||
+34
@@ -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:
|
||||
+116
@@ -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
|
||||
+44
@@ -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:
|
||||
+315
@@ -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(¬ificationData);
|
||||
|
||||
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(¬ificationData, 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
|
||||
+37
@@ -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:
|
||||
+42
@@ -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
|
||||
+44
@@ -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:
|
||||
+420
@@ -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(¬ificationData);
|
||||
|
||||
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
|
||||
+34
@@ -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:
|
||||
+362
@@ -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
|
||||
+34
@@ -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:
|
||||
Reference in New Issue
Block a user