随笔 - 56, 评论 - 7, 访问 - 191743

导航


  • 访问:191743次
  • 积分:582分
  • 排名:第38名
  • 随笔:56篇
  • 评论:7条

随笔分类

随笔档案

相册

最新评论

阅读排行榜

评论排行榜

unity3d 阅读(671) 评论(0)

运行时API分为两部分:AndroidNotificationCenter和iOSNotificationCenter。这些可用于计划和管理其各自平台的通知。您可以从我们的GitHub页面下载一个NotificationsSamples示例项目,该项目实现了一个高级封装,可用于使用相同的API向Android和iOS发送通知,或查看下面的代码示例。

该软件包支持以下功能:

计划安排本地一次或可重复的通知。
取消已经显示的和即将发生的(计划的)通知。


安卓:
在Android Oreo及更高版本上创建和修改通知渠道(类别)。
设备重新启动时保留通知。
设置自定义通知图标。

 

iOS:
使用Apple Push Notification Service(APN)接收远程通知。
如果设备在您的应用程序运行时收到来自其他应用程序的通知,请修改远程通知内容。
将通知分组为线程(仅在iOS 12+上受支持)。

 

要求:
支持Android 4.4(API 19)和iOS 10或更高版本。
与Unity 2018.3或更高版本兼容。


安卓
建立通知频道

每个本地通知必须属于一个通知通道。通知通道仅在Android 8.0 Oreo及更高版本上受支持。在较旧的Android版本上,此程序包模拟通知通道的行为。Importance为通知频道设置的优先级(重要)之类的设置适用于单个通知,即使在8.0之前的Android版本上也是如此。

 

var c = new AndroidNotificationChannel()
{
Id = "channel_id",
Name = "Default Channel",
Importance = Importance.High,
Description = "Generic notifications",
};
AndroidNotificationCenter.RegisterNotificationChannel(c);

 

发送一个简单的通知

本示例说明如何安排简单的文本通知并将其发送到上一步中创建的通知通道。

 

var notification = new AndroidNotification();
notification.Title = "SomeTitle";
notification.Text = "SomeText";
notification.FireTime = System.DateTime.Now.AddMinutes(5);

AndroidNotificationCenter.SendNotification(notification, "channel_id");


如果您没有为每个通知指定自定义图标,则默认的Unity图标显示在状态栏中。您可以在“项目设置” **窗口(菜单:**“编辑” >“项目设置” >“移动通知设置”)中配置通知图标。每当您在脚本中安排通知时,请使用在“移动通知设置”窗口中定义的图标ID 。

notification.SmallIcon = "my_custom_icon_id";


您可以选择设置一个大图标,该图标也会显示在通知视图中。较小的图标显示为大图标上方的小徽章。

notification.LargeIcon = "my_custom_large_icon_id";


安排通知后,Unity会为每个通知分配一个唯一的标识符。您可以使用标识符来跟踪通知状态或取消通知状态。通知状态跟踪仅适用于Android 6.0棉花糖及更高版本。

var identifier = AndroidNotificationCenter.SendNotification(n, "channel_id");


使用以下代码示例检查您的应用程序是否已将通知传递到设备,并根据结果执行任何操作。

if ( AndroidNotificationCenter.CheckScheduledNotificationStatus(identifier) == NotificationStatus.Scheduled)
{
// Replace the currently scheduled notification with a new notification.
AndroidNotificationCenter.UpdateScheduledNotification(identifier, newNotification, channel);
}
else if ( AndroidNotificationCenter.CheckScheduledNotificationStatus(identifier) == NotificationStatus.Delivered)
{
//Remove the notification from the status bar
AndroidNotificationCenter.CancelNotification(identifier);
}
else if ( AndroidNotificationCenter.CheckScheduledNotificationStatus(identifier) == NotificationStatus.Unknown)
{
AndroidNotificationCenter.SendNotification(newNotification, "channel_id");
}

 

设备重启后保留预定的通知

默认情况下,应用在设备重新启动时会删除计划的通知。要在用户重新打开设备电源时自动重新计划所有通知,请在“项目设置”窗口(菜单:“编辑” >“项目设置” >“移动通知设置”)中启用“重新启动设备时重新计划通知”设置。这会将权限添加到您的应用清单中。RECEIVE_BOOT_COMPLETED

在应用程序运行时处理收到的通知

您可以订阅AndroidNotificationCenter.OnNotificationReceived事件以在应用程序运行时每当设备收到远程通知时接收回调。

 

AndroidNotificationCenter.NotificationReceivedCallback receivedNotificationHandler =
delegate(AndroidNotificationIntentData data)
{
var msg = "Notification received : " + data.Id + "\n";
msg += "\n Notification received: ";
msg += "\n .Title: " + data.Notification.Title;
msg += "\n .Body: " + data.Notification.Text;
msg += "\n .Channel: " + data.Channel;
Debug.Log(msg);
};

AndroidNotificationCenter.OnNotificationReceived += receivedNotificationHandler;


保存自定义数据并在用户从通知中打开应用程序时进行检索

要在通知对象中存储任意字符串数据,请设置IntentData属性。

 

var notification = new AndroidNotification();
notification.IntentData = "{\"title\": \"Notification 1\", \"data\": \"200\"}";
AndroidNotificationCenter.SendNotification(notification, "channel_id");
如果用户从通知中打开该应用程序,则可以按以下方式检索该应用程序中的任何内容以及它分配给它的任何数据:

var notificationIntentData = AndroidNotificationCenter.GetLastNotificationIntent();

if (notificationIntentData != null)
{
var id = notificationIntentData.Id;
var channel = notificationIntentData.Channel;
var notification = notificationIntentData.Notification;
}


如果以其他任何方式打开应用程序,则GetLastNotificationIntent返回null。

 

iOS

请求授权

您需要从系统请求权限才能发布本地通知并接收远程通知。如果您打算在用户确认授权请求后向其发送远程通知,则需要检索DeviceToken。为此,必须创建请求并将其registerForRemoteNotifications设置为true。有关如何向设备发送推送通知以及如何向应用程序添加推送通知支持的更多信息,请参阅Apple Developer网站文档。

(可选)您可以请求用户许可以仅发送某些通知类型。以下示例显示了如何请求权限以显示“ UI警报”对话框并在应用程序图标上添加徽章。但是,用户可以随时在设置应用中更改每种通知类型的授权状态,因此要检查实际的授权状态,请致电iOSNotificationCenter.GetNotificationSettings。

或者,您可以在“项目设置”窗口(菜单:“编辑” >“项目设置” >“移动通知设置”)中启用“应用程序启动时的请求授权”设置,这将使应用程序在以下情况下自动显示权限请求对话框:用户启动该应用程序。之后,您可以再次调用此方法以确定当前的授权状态。如果用户已经授予或拒绝了授权,则权限请求对话框将不会再次显示。

IEnumerator RequestAuthorization()
{
using (var req = new AuthorizationRequest(AuthorizationOption.Alert | AuthorizationOption.Badge, true))
{
while (!req.IsFinished)
{
yield return null;
};

string res = "\n RequestAuthorization: \n";
res += "\n finished: " + req.IsFinished;
res += "\n granted : " + req.Granted;
res += "\n error: " + req.Error;
res += "\n deviceToken: " + req.DeviceToken;
Debug.Log(res);
}

 

发送一个简单的通知

var timeTrigger = new iOSNotificationTimeIntervalTrigger()
{
TimeInterval = new TimeSpan(0, minutes, seconds),
Repeats = false
};

var notification = new iOSNotification()
{
// You can optionally specify a custom identifier which can later be
// used to cancel the notification, if you don't set one, a unique
// string will be generated automatically.
Identifier = "_notification_01",
Title = "Title",
Body = "Scheduled at: " + DateTime.Now.ToShortDateString() + " triggered in 5 seconds",
Subtitle = "This is a subtitle, something, something important...",
ShowInForeground = true,
ForegroundPresentationOption = (PresentationOption.Alert | PresentationOption.Sound),
CategoryIdentifier = "category_a",
ThreadIdentifier = "thread1",
Trigger = timeTrigger,
};

iOSNotificationCenter.ScheduleNotification(notification);


以下代码示例在未触发的情况下取消通知:

iOSNotificationCenter.RemoveScheduledNotification(notification.Identifier);


以下代码示例如果通知已经显示给用户,则将其从通知中心中删除:

iOSNotificationCenter.RemoveDeliveredNotification(notification.Identifier);


其他触发因素

除了时间间隔触发器外,您还可以使用日历和位置触发器。中的所有字段iOSNotificationCalendarTrigger都是可选的,但是您需要至少设置一个字段才能使触发器起作用。例如,如果仅设置小时和分钟字段,则系统会在下一个指定的小时和分钟上自动触发通知。

var calendarTrigger = new iOSNotificationCalendarTrigger()
{
// Year = 2018,
// Month = 8,
//Day = 30,
Hour = 12,
Minute = 0,
// Second = 0
Repeats = false
};

如果要安排在设备进入或离开特定地理区域时发送通知的时间,还可以创建位置触发器。在使用此触发器安排任何通知之前,您的应用必须具有使用“核心位置”的权限,并且必须具有“使用时”权限。使用Unity LocationService API请求此授权。有关更多信息,请参阅Apple Developer网站上的Core Location文档。

在此示例中,中心坐标是使用WGS 84系统定义的。当用户进入巴黎埃菲尔铁塔周围250米半径范围内的区域时,该应用会触发通知。

var locationTrigger = new iOSNotificationLocationTrigger()
{
Center = new Vector2(2.294498f, 48.858263f),
Radius = 250f,
NotifyOnEntry = true,
NotifyOnExit = false,
}


在应用运行时处理收到的通知

如果您的应用在运行时触发了通知,则您可以执行自定义操作,而不是显示通知警报。默认情况下,如果您的应用在前台运行时触发了本地通知,则设备不会为该通知显示警报。如果希望通知的行为就像设备未在运行应用程序一样,请ShowInForeground在安排通知时设置属性:

notification.ShowInForeground = true;

// In this case you need to specify its 'ForegroundPresentationOption'
notification.ForegroundPresentationOption = (PresentationOption.Sound | PresentationOption.Alert);
另外,您可以在应用触发通知时执行其他操作。例如,您可以使用应用程序的UI显示通知内容。为此,请订阅OnNotificationReceived活动。每当收到本地或远程通知时,无论它是否显示在前台,您的应用都会调用此事件。

要修改或隐藏您的应用在运行时收到的远程通知的内容,请订阅该OnRemoteNotificationReceived事件。如果执行此操作,则在您的应用程序运行时不会显示远程通知。如果您仍然想要显示警报,请使用远程通知的内容安排本地通知,如下所示:

iOSNotificationCenter.OnRemoteNotificationReceived += notification =>
{
// When a remote notification is received, modify its contents and show it
// after 1 second.
var timeTrigger = new iOSNotificationTimeIntervalTrigger()
{
TimeInterval = new TimeSpan(0, 0, 1),
Repeats = false
};

iOSNotification n = new iOSNotification()
{
Title = "Remote : " + notification.Title,
Body = "Remote : " + notification.Body,
Subtitle = "Remote: " + notification.Subtitle,
ShowInForeground = true,
ForegroundPresentationOption = PresentationOption.Sound | PresentationOption.Alert | PresentationOption.Badge,
CategoryIdentifier = notification.CategoryIdentifier,
ThreadIdentifier = notification.ThreadIdentifier,
Trigger = timeTrigger,
};
iOSNotificationCenter.ScheduleNotification(n);

Debug.Log("Rescheduled remote notifications with id: " + notification.Identifier);
};


保存自定义数据并在用户从通知中打开应用程序时进行检索

要将任意字符串数据存储在通知对象中,请设置Data属性:

var notification = new iOSNotification();
notification.Data = "{\"title\": \"Notification 1\", \"data\": \"200\"}";
//.f.assign other fields..
iOSNotificationCenter.ScheduleNotification(notification);


以下代码示例显示了如何检索应用程序收到的最新通知:

var n = iOSNotificationCenter.GetLastRespondedNotification();
if (n != null)
{
var msg = "Last Received Notification : " + n.Identifier + "\n";
msg += "\n - Notification received: ";
msg += "\n - .Title: " + n.Title;
msg += "\n - .Badge: " + n.Badge;
msg += "\n - .Body: " + n.Body;
msg += "\n - .CategoryIdentifier: " + n.CategoryIdentifier;
msg += "\n - .Subtitle: " + n.Subtitle;
msg += "\n - .Data: " + n.Data;
Debug.Log(msg);
}
else
{
Debug.Log("No notifications received.");
}
如果用户从通知中打开应用程序,则GetLastRespondedNotification还返回该通知。否则,它返回null。

 

常见问题
为什么小Android图标在编辑器通知设置预览中为白色?

小通知图标必须是单色的,Android会忽略图标图像中的所有非alpha通道,因此Unity会自动剥离所有RGB通道。您也可以通过将图标放在\Assets\Plugins\Android\res\drawable-{scaleFactor}文件夹中来提供图标,在这种情况下,它们不会被自动处理,但是包含非Alpha通道的图标将无法在Android 5.0及更高版本上正确显示。

可以通过设置AndroidNotification.Color属性来修改通知颜色。

 

为什么当我的应用程序关闭且未在后台运行时,某些华为和小米手机上没有发送通知?

似乎华为(包括荣耀)和小米采用了激进的节电技术 ,除非用户在设备设置中将该应用列入了白名单,否则它们会限制应用程序的后台活动。这意味着,如果应用已关闭或不在bacgkround中运行,则不会发送任何计划的通知。除了鼓励用户将您的应用列入白名单之外,我们没有任何其他方法可以解决此问题。

 

如果带有位置触发器的通知不起作用,该怎么办?

确保将CoreLocation框架添加到您的项目中。您可以在Unity编辑器的“移动通知设置”菜单中执行此操作(菜单:“编辑” >“项目设置” >“移动通知设置”)。或者,将其手动添加到Xcode项目中,或使用Unity Xcode API。您还需要使用位置服务API来请求您的应用访问位置数据的权限。


发表评论
切换编辑模式