unity3d 之本地推送

时间:2023-03-09 22:28:18
unity3d 之本地推送

参考:http://blog.csdn.net/azhou_hui/article/details/50790870

1. 本地推送主要包括在android和ios上,下面所有的代码都是本人写的,经过测试是没有问题的,已经运用到项目中了。首先是接口INotification:

using System;

public interface INotification : IDisposable
{
/// <summary>
/// 注册一个推送
/// </summary>
/// <param name="id">消息唯一标识</param>
/// <param name="name">消息弹出一时在手机屏幕最上方显示的文字,对苹果无效</param>
/// <param name="title">通知栏中消息的标题</param>
/// <param name="content">通知栏中消息的正文</param>
/// <param name="triggerTime">触发的时间</param>
/// <param name="repeat">是否要每日重复触发</param>
void Register(int id, string name, string title, string content, DateTime triggerTime, bool repeat); /// <summary>
/// 取消一个推送
/// </summary>
/// <param name="id">消息唯一标识</param>
void Unregister(int id); /// <summary>
/// 取消所有推送
/// </summary>
void ClearAll();
}

INotification

2. android的实现:

#if UNITY_ANDROID

using 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[]
{
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 = ; i < types.Length * ; 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

AndroidNotification

其中 "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(time<now)
time+=RepeatInterval; return time;
}
} @Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction(); Log.d("Unity", "Bleach: onReceive......................" + action);
if (action!=null && action.equals("android.intent.action.BOOT_COMPLETED"))
{
for (BleachNotification bn : LoadAllNotification())
Register(bn, false);
}
else
{
if (!intent.getBooleanExtra("repeat", true))
{
int id = intent.getIntExtra("id", -1);
if (id != -1)
DisableNotification(context, id);
} NotificationManager nm=(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); ApplicationInfo applicationInfo=null;
try
{
final PackageManager pm=context.getPackageManager();
applicationInfo = pm.getApplicationInfo(context.getPackageName(),PackageManager.GET_META_DATA);
}
catch (NameNotFoundException e)
{
Log.d("Unity","Bleach: onReceive failed, reason: get applicationInfo failed.");
} Notification notification=new Notification(applicationInfo.icon,intent.getStringExtra("name"),System.currentTimeMillis()); Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(context, 0, notificationIntent, 0); notification.setLatestEventInfo(context, intent.getStringExtra("title"), intent.getStringExtra("content"), pi); // Notify
nm.notify(intent.getIntExtra("id",0),notification); Log.d("Unity","Bleach: notify succeed!");
}
} public static void Register(int id, String name, String title, String content, int secondsFromNow, boolean repeat)
{
Calendar calendar=Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, secondsFromNow);
long time=calendar.getTimeInMillis(); Register(new BleachNotification(id,name,title,content,time,repeat),true);
} private static void Register(BleachNotification bn,boolean isSave)
{
Activity activity =UnityPlayer.currentActivity; Intent intent =new Intent(activity, AlarmReceiver.class);
intent.putExtra("name", bn.Name);
intent.putExtra("title", bn.Title);
intent.putExtra("content", bn.Content);
intent.putExtra("id", bn.Id);
intent.putExtra("repeat",bn.Repeat); PendingIntent pi=PendingIntent.getBroadcast(activity, bn.Id, intent, PendingIntent.FLAG_CANCEL_CURRENT); // Schedule the alarm!
AlarmManager am = (AlarmManager)activity.getSystemService(Context.ALARM_SERVICE);
if(bn.Repeat)
am.setRepeating(AlarmManager.RTC_WAKEUP, bn.TriggerMillis, RepeatInterval, pi);
else
am.set(AlarmManager.RTC_WAKEUP,bn.TriggerMillis, pi); if(isSave)
SaveNotification(bn); Log.d("Unity", "Bleach: Start Alarm...,id: "+bn.Id+
" name: "+bn.Name+
" title: "+bn.Title+
" content: "+bn.Content+
" triggerMillis: "+bn.TriggerMillis+
" currentTime:"+System.currentTimeMillis()+
" repeat: "+bn.Repeat);
} public static void Unregister(int id)
{
Activity activity = UnityPlayer.currentActivity;
Intent intent = new Intent(activity, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(activity, id, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)activity.getSystemService(Context.ALARM_SERVICE);
am.cancel(pi); NotificationManager mNM = (NotificationManager)activity.getSystemService(Context.NOTIFICATION_SERVICE);
mNM.cancel(id); DisableNotification(activity, id); Log.d("Unity","Bleach: Cancel, id: "+id);
} private static void DisableNotification(Context context,int id)
{
SharedPreferences sp = context.getSharedPreferences("Notification", Context.MODE_APPEND); Editor edit = sp.edit();
String sid = String.valueOf(id);
edit.putInt(sid, -1);
edit.commit();
} private static void SaveNotification(BleachNotification notification)
{
SharedPreferences sp = UnityPlayer.currentActivity.getSharedPreferences("Notification", Context.MODE_APPEND); Editor edit = sp.edit();
String sid = String.valueOf(notification.Id);
edit.putInt(sid, 1);
edit.putString(sid + "name", notification.Name);
edit.putString(sid + "title", notification.Title);
edit.putString(sid + "content", notification.Content);
edit.putLong(sid + "triggerTime", notification.TriggerMillis);
edit.putBoolean(sid + "repeat", notification.Repeat);
edit.commit();
} private static ArrayList<BleachNotification> LoadAllNotification()
{
ArrayList<BleachNotification> l = new ArrayList<BleachNotification>();
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;
}
}

AlarmReceiver

manifest配置为:

<!-- Add by tj[-->
<receiver android:name="com.example.localpush.AlarmReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver> <activity
android:name="com.unity3d.player.UnityPlayerProxyActivity"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >
</activity> <activity
android:name="com.unity3d.player.UnityPlayerActivity"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >
</activity> <activity
android:name="com.unity3d.player.UnityPlayerNativeActivity"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" >
<meta-data android:name="android.app.lib_name" android:value="unity" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />
</activity>
<!-- ] -->

Manifest

3. ios 直接调用 unity3d 的 api,实现如下:

#if  UNITY_IPHONE

using 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 = ,
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 = -
}; NotificationServices.PresentLocalNotificationNow(ln);
NotificationServices.CancelAllLocalNotifications();
NotificationServices.ClearLocalNotifications();
} #region INotification public void Dispose()
{ } #endregion
} #endif

IOSNotification

4. 最后是一个与上层交互的接口:

using System;
using UnityEngine; // 本地推送的类型,注意:id不能重复
public enum NotificationType
{
SevenDaysNoLogin = , // 7日登陆
SpecialTrain = , // 紧急特训
SpaTime = , // 温泉
LoginNextDay = , // 次日登陆
PuYuanShopRefresh = , // 浦原商店刷新
WorldBossOpen = , // 世界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(""); // 游戏名
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();
} /// <summary>
/// 登陆完成后更新本地推送
/// </summary>
public void UpdateWhenLoginComplete()
{
UpdateSevenDaysNoLogin(); //UpdateLoginNextDay(); UpdatePuYuanShopRefresh(); UpdateWorldBossOpen();
} #region Special notification // 七天未登陆
void UpdateSevenDaysNoLogin()
{
string content = MLocalization.Get("");
var time = PlayerInfo.Instance().GetServerNow().AddDays(); Unregister(NotificationType.SevenDaysNoLogin);
Register(NotificationType.SevenDaysNoLogin, content, time, false);
} // 紧急特训
public void RegisterSpecialTrain(TrainingSpecially tr)
{
string content = MLocalization.Get(""); 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 + ;
Unregister(notiId); if (SystemSettingModel.Instance.NotifyHotSpring) // 系统设置
{
ulong spaStartTime = ActivityInfoValue.Instance().spaStartTimeList[];
DateTime dateTimeStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(, , ));
DateTime dateTimeTrigger = dateTimeStart.AddSeconds(spaStartTime).ToLocalTime(); if (content == null)
content = MLocalization.Get(""); Register(notiId, content, dateTimeTrigger, true);
}
//}
} public void ClearSpaTime()
{
if (ActivityInfoValue.Instance().spaStartTimeList == null)
return;
for (int i = ; 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 <= )
{
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, ).AddDays();
string content = MLocalization.Get(""); Register(NotificationType.LoginNextDay, content, triggerTime, false); PlayerPrefs.SetInt(prefKey, );
}
} // 浦原商店刷新
public void UpdatePuYuanShopRefresh()
{
Unregister(NotificationType.PuYuanShopRefresh); if (SystemSettingModel.Instance.NotifyShopRefresh)
{
DateTime time = DateTime.Parse(GameOption.Instance().refreshShopResetTime[]); // 只需要每天9点推送
DateTime serverNow = PlayerInfo.Instance().GetServerNow();
DateTime triggerTime = new DateTime(serverNow.Year, serverNow.Month, serverNow.Day, time.Hour, time.Minute, );
string content = MLocalization.Get(""); 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("");
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, ); Register(NotificationType.WorldBossOpen, content, triggerTime, true);
}
} #endregion public void Dispose()
{
m_notification.Dispose();
}
}

NotificationManager

转载请注明出处:http://www.cnblogs.com/jietian331/p/5025561.html