参考:
1. 本地推送主要包括在android和ios上,下面所有的代码都是本人写的,经过测试是没有问题的,已经运用到项目中了。首先是接口INotification:
using System;public interface INotification : IDisposable{ ////// 注册一个推送 /// /// 消息唯一标识 /// 消息弹出一时在手机屏幕最上方显示的文字,对苹果无效 /// 通知栏中消息的标题 /// 通知栏中消息的正文 /// 触发的时间 /// 是否要每日重复触发 void Register(int id, string name, string title, string content, DateTime triggerTime, bool repeat); ////// 取消一个推送 /// /// 消息唯一标识 void Unregister(int id); ////// 取消所有推送 /// void ClearAll();}
2. android的实现:
#if UNITY_ANDROIDusing System;using UnityEngine;public class AndroidNotification : INotification{ AndroidJavaObject m_javaObj = new AndroidJavaObject("com.example.localpush.AlarmReceiver"); public void Register(int id, string name, string title, string content, DateTime triggerTime, bool repeat) { int secondsFromNow = (int)(triggerTime - DateTime.Now).TotalSeconds; m_javaObj.CallStatic("Register", new object[6] { id, name, title, content, secondsFromNow, repeat }); } public void Unregister(int id) { m_javaObj.CallStatic("Unregister", id); } public void ClearAll() { var types = Enum.GetValues(typeof(NotificationType)); for (int i = 0; i < types.Length * 100; i++) Unregister(i); } #region IDisposable public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { m_javaObj.Dispose(); m_javaObj = null; } } ~AndroidNotification() { Dispose(false); } #endregion}#endif
其中 "com.example.localpush.AlarmReceiver" 中的java代码如下:
package com.example.localpush;import java.util.ArrayList;import java.util.Calendar;import android.app.Activity;import android.app.AlarmManager;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.content.SharedPreferences.Editor;import android.content.pm.ApplicationInfo;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;import android.util.Log;import com.unity3d.player.UnityPlayer;public class AlarmReceiver extends BroadcastReceiver { static final int NotificationCount = 10; static final int RepeatInterval = 24 * 60 * 60 * 1000;// 86400000 // Inner class static class BleachNotification { public int Id; public String Name; public String Title; public String Content; public long TriggerMillis; public boolean Repeat; public BleachNotification(int id, String name, String title, String content, long triggerMillis, boolean repeat) { Id = id; Name=name; Title = title; Content = content; TriggerMillis = repeat?GetNextRepeatTime(triggerMillis):triggerMillis; Repeat = repeat; } private long GetNextRepeatTime(long time) { long now = System.currentTimeMillis(); while(timeLoadAllNotification() { ArrayList l = new ArrayList (); SharedPreferences sp = UnityPlayer.currentActivity.getSharedPreferences("Notification", Context.MODE_APPEND); int index = 0; while (index < NotificationCount) { String id = String.valueOf(index); if (sp.getInt(id, -1) != -1) { BleachNotification bn=new BleachNotification( index, sp.getString(id + "name", ""), sp.getString(id + "title", ""), sp.getString(id + "content",""), sp.getLong(id + "triggerTime", 0), sp.getBoolean(id + "repeat", false) ); l.add(bn); } index++; } return l; }}
manifest配置为:
3. ios 直接调用 unity3d 的 api,实现如下:
#if UNITY_IPHONEusing System;using UnityEngine;public class IOSNotification : INotification{ static IOSNotification() { Clear(); NotificationServices.RegisterForLocalNotificationTypes(LocalNotificationType.Alert); } public void Register(int id, string name, string title, string content, DateTime triggerTime, bool repeat) { var iosNotification = new LocalNotification() { alertBody = content, hasAction = false, applicationIconBadgeNumber = 1, fireDate = triggerTime, soundName = LocalNotification.defaultSoundName, }; if (repeat) { iosNotification.repeatCalendar = CalendarIdentifier.ChineseCalendar; iosNotification.repeatInterval = CalendarUnit.Day; } NotificationServices.ScheduleLocalNotification(iosNotification); } public void Unregister(int id) { } public void ClearAll() { Clear(); } static void Clear() { var ln = new LocalNotification() { applicationIconBadgeNumber = -1 }; NotificationServices.PresentLocalNotificationNow(ln); NotificationServices.CancelAllLocalNotifications(); NotificationServices.ClearLocalNotifications(); } #region INotification public void Dispose() { } #endregion}#endif
4. 最后是一个与上层交互的接口:
using System;using UnityEngine;// 本地推送的类型,注意:id不能重复public enum NotificationType{ SevenDaysNoLogin = 1, // 7日登陆 SpecialTrain = 100, // 紧急特训 SpaTime = 200, // 温泉 LoginNextDay = 300, // 次日登陆 PuYuanShopRefresh = 400, // 浦原商店刷新 WorldBossOpen = 500, // 世界boss开启}public class NotificationManager : IDisposable{ INotification m_notification; #region Singleton static NotificationManager s_instance; public static NotificationManager Instance { get { if (s_instance == null) s_instance = new NotificationManager(); return s_instance; } } #endregion #region DefaultNotification class DefaultNotification : INotification { public void Register(int id, string name, string title, string content, DateTime triggerTime, bool repeat) { } public void Unregister(int id) { } public void ClearAll() { } public void Dispose() { } } #endregion private NotificationManager() { m_notification = CreateObj(); } INotification CreateObj() { INotification obj;#if UNITY_EDITOR obj = new DefaultNotification();#elif UNITY_ANDROID obj = new AndroidNotification();#elif UNITY_IPHONE obj = new IOSNotification();#else obj = new DefaultNotification(); Debugger.LogWarning("Local push not support this platform");#endif return obj; } public void Register(int id, string content, DateTime triggerTime, bool repeat) { if (string.IsNullOrEmpty(content)) throw new ArgumentException("content"); string title = MLocalization.Get("194260041"); // 游戏名 if (string.IsNullOrEmpty(title)) throw new ArgumentException("title"); m_notification.Register(id, content, title, content, triggerTime, repeat); Debug.Log(string.Format("local push, id: {0}, title: {1}, content: {2}, Time: {3} repeat: {4}", id, title, content, triggerTime, repeat)); } public void Register(NotificationType type, string content, DateTime triggerTime, bool repeat) { Register((int)type, content, triggerTime, repeat); } public void Unregister(int id) { m_notification.Unregister(id); } public void Unregister(NotificationType type) { Unregister((int)type); } public void ClearAll() { m_notification.ClearAll(); } ////// 登陆完成后更新本地推送 /// public void UpdateWhenLoginComplete() { UpdateSevenDaysNoLogin(); //UpdateLoginNextDay(); UpdatePuYuanShopRefresh(); UpdateWorldBossOpen(); } #region Special notification // 七天未登陆 void UpdateSevenDaysNoLogin() { string content = MLocalization.Get("194260031"); var time = PlayerInfo.Instance().GetServerNow().AddDays(7); Unregister(NotificationType.SevenDaysNoLogin); Register(NotificationType.SevenDaysNoLogin, content, time, false); } // 紧急特训 public void RegisterSpecialTrain(TrainingSpecially tr) { string content = MLocalization.Get("194260021"); Register(NotificationType.SpecialTrain, content, tr.begin_time, true); } // 温泉 public void UpdateSpaTime() { string content = null; // spaTime just notify once //for (int i = 0; i < ActivityInfoValue.Instance().spaStartTimeList.Count; i++) //{ int notiId = (int)NotificationType.SpaTime + 0; Unregister(notiId); if (SystemSettingModel.Instance.NotifyHotSpring) // 系统设置 { ulong spaStartTime = ActivityInfoValue.Instance().spaStartTimeList[0]; DateTime dateTimeStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); DateTime dateTimeTrigger = dateTimeStart.AddSeconds(spaStartTime).ToLocalTime(); if (content == null) content = MLocalization.Get("194260011"); Register(notiId, content, dateTimeTrigger, true); } //} } public void ClearSpaTime() { if (ActivityInfoValue.Instance().spaStartTimeList == null) return; for (int i = 0; i < ActivityInfoValue.Instance().spaStartTimeList.Count; i++) { int notiId = (int)NotificationType.SpaTime + i; Unregister(notiId); } } /* * 当玩家首次打开客户端进入游戏时,设置一条推送,在第二天的20点进行推送 * 当玩家第二天20点之前,登录过游戏,则取消此条推送。 * 推送文字为“你今天还没有登录死神哦,登录即可入手斩月。“(本文字为语言包文字) */ void UpdateLoginNextDay() { string prefKey = string.Format("LocalPush.{0}.{1}", PlayerInfo.Instance().roleID, NotificationType.LoginNextDay); int prefValue = PlayerPrefs.GetInt(prefKey); Unregister(NotificationType.LoginNextDay); if (prefValue <= 0) { DateTime serverNow = PlayerInfo.Instance().GetServerNow(); string timeString = GameOption.Instance().NotifyBladeTime; DateTime time = DateTime.Parse(timeString); DateTime triggerTime = new DateTime(serverNow.Year, serverNow.Month, serverNow.Day, time.Hour, time.Minute, 0).AddDays(1); string content = MLocalization.Get("194260051"); Register(NotificationType.LoginNextDay, content, triggerTime, false); PlayerPrefs.SetInt(prefKey, 1); } } // 浦原商店刷新 public void UpdatePuYuanShopRefresh() { Unregister(NotificationType.PuYuanShopRefresh); if (SystemSettingModel.Instance.NotifyShopRefresh) { DateTime time = DateTime.Parse(GameOption.Instance().refreshShopResetTime[0]); // 只需要每天9点推送 DateTime serverNow = PlayerInfo.Instance().GetServerNow(); DateTime triggerTime = new DateTime(serverNow.Year, serverNow.Month, serverNow.Day, time.Hour, time.Minute, 0); string content = MLocalization.Get("194260071"); Register(NotificationType.PuYuanShopRefresh, content, triggerTime, true); } } // 世界 boss 开启 public void UpdateWorldBossOpen() { Unregister(NotificationType.WorldBossOpen); bool isOpen = PlayerInfo.Instance().openedSystemID.Contains((uint)SystemEnum.WorldBoss); if (isOpen && SystemSettingModel.Instance.NotifyWorldBossOpen) { string content = MLocalization.Get("194260061"); DateTime serverNow = PlayerInfo.Instance().GetServerNow(); string timeString = GameOption.Instance().bossYammyNotifyTime; DateTime time = DateTime.Parse(timeString); DateTime triggerTime = new DateTime(serverNow.Year, serverNow.Month, serverNow.Day, time.Hour, time.Minute, 0); Register(NotificationType.WorldBossOpen, content, triggerTime, true); } } #endregion public void Dispose() { m_notification.Dispose(); }}
转载请注明出处: