Unity本地推送消息(一)
IOS平台
请参考这个文档IOS本地消息通知LocalNotification的使用
以及 Unity官网API文档
Android平台
Unity在Android端的推送,是通过AndroidStudio打jar包的方式来实现的
1.AndroidStudio工程
关于打jar包可以参考我的另一篇文章:Unity调用安卓Native(Android Studio),处理好打jar包前的一系列准备。主要是:导入Unity的class.jar,对应版本的android.jar,在build.gradle里写好打jar包的task
2.写核心代码
新建一个class: AndroidNotificator 继承于BroadcastReceiver 在下面的代码里写的很明确
package cn.gfplay.noti;
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.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import com.unity3d.player.UnityPlayer;
/**
* 用于生成 / 清除本地通知推送的插件
* 仅在安卓平台有效
*/
public class AndroidNotificator extends BroadcastReceiver {
private static int m_nLastID = 0;
/**
* 显示数秒后的通知
*
* @param pAppName 应用名
* @param pTitle 通知标题
* @param pContent 通知内容
* @param pDelaySecond 延迟时间
* @param pIsDailyLoop 是否每日自动推送
* @throws IllegalArgumentException 错误信息
*/
public static void ShowNotification(String pAppName, String pTitle, String pContent, int pDelaySecond, boolean pIsDailyLoop) throws IllegalArgumentException {
if(pDelaySecond < 0)
{
throw new IllegalArgumentException("The param: pDelaySecond < 0");
}
Activity curActivity = UnityPlayer.currentActivity;
Intent intent = new Intent("UNITY_NOTIFICATOR");
intent.putExtra("appname", pAppName);
intent.putExtra("title", pTitle);
intent.putExtra("content", pContent);
PendingIntent pi = PendingIntent.getBroadcast(curActivity, 0, intent, 0);
AlarmManager am = (AlarmManager)curActivity.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, pDelaySecond);
long alarmTime = calendar.getTimeInMillis();
if (pIsDailyLoop){
am.setRepeating(
AlarmManager.RTC_WAKEUP,
alarmTime,
30, // 暂时用30秒测试,一般应该为24小时即86400秒
pi);
} else {
am.set(
AlarmManager.RTC_WAKEUP,
alarmTime,
pi);
}
}
/**
* 清除所有通知,包括日常通知
*/
public static void ClearNotification() {
Activity act = UnityPlayer.currentActivity;
NotificationManager nManager = (NotificationManager)act.getSystemService(Context.NOTIFICATION_SERVICE);
for(int i = m_nLastID; i >= 0; i--) {
nManager.cancel(i);
}
m_nLastID = 0;
}
@SuppressWarnings("deprecation")
public void onReceive(Context pContext, Intent pIntent) {
Class<?> unityActivity = null;
try {
unityActivity = pContext.getClassLoader().loadClass("com.unity3d.player.UnityPlayerProxyActivity");
} catch (Exception ex) {
ex.printStackTrace();
return;
}
ApplicationInfo applicationInfo = null;
PackageManager pm = pContext.getPackageManager();
try {
applicationInfo = pm.getApplicationInfo(pContext.getPackageName(), PackageManager.GET_META_DATA);
} catch (Exception ex) {
ex.printStackTrace();
return;
}
Bundle bundle = pIntent.getExtras();
PendingIntent contentIntent = PendingIntent.getActivity(
pContext,
m_nLastID,
new Intent(pContext, unityActivity),
0);
Notification.Builder builder = new Notification.Builder(pContext)
.setAutoCancel(true)
.setContentTitle((String)bundle.get("title"))
.setContentText((String)bundle.get("content"))
.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.abc)
.setWhen(System.currentTimeMillis())
.setOngoing(true);
Notification notification=builder.getNotification();
NotificationManager nm = (NotificationManager)pContext.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(m_nLastID, notification);
m_nLastID++;
}
}
PS:
1.在src/main/res/drawable/下添加一张图片作为推送的Icon即在setSmallIcon(R.drawable.abc)处设置(目前还没研究明白,按这个代码测试推送的图片就是应用的icon)
对应到Unity中就是 Assets/Plugins/Android/res/drawable/ 否则会出现图片丢失的问题.
2.在AndroidMainifest.xml中需要添加一个receiver具体代码如下
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.gfplay.noti" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal">
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
<application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false" android:isGame="true" android:banner="@drawable/app_banner">
<activity android:label="@string/app_name" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" android:name="cn.gfplay.noti.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
<receiver android:name="cn.gfplay.noti.AndroidNotificator">
<intent-filter>
<action android:name="UNITY_NOTIFICATOR" />
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="23" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
</manifest>
加的是这一部分
<receiver android:name="cn.gfplay.noti.AndroidNotificator">
<intent-filter>
<action android:name="UNITY_NOTIFICATOR" />
</intent-filter>
</receiver>
PS:注意一下包名,很多地方都有 com.xxx.xxx.className
jar包以及xml和相关资源准备好,就进到Unity工程中进行处理了.
再Unity直接调用就可以了,用AndroidJavaObject 这个类,我贴上自己的代码(copy了一下)供参考:
using UnityEngine;
using UnityEngine.UI;
public class JARTest : MonoBehaviour
{
public Text Text_Message;
#if UNITY_ANDROID
private AndroidJavaObject m_ANObj = null;
#endif
public void Button_1_Clicked()
{
#if UNITY_ANDROID
if(InitNotificator())
{
m_ANObj.CallStatic(
"ShowNotification",
Application.productName,
"温馨提示",
"多喝热水",
10,
true);
this.Text_Message.text = "Notification will show in 10sec.";
}
#endif
}
public void Button_2_Clicked()
{
#if UNITY_ANDROID
if(InitNotificator())
{
m_ANObj.CallStatic("ClearNotification");
this.Text_Message.text = "Notification has been cleaned";
}
#endif
}
#if UNITY_ANDROID
private bool InitNotificator()
{
if (m_ANObj == null)
{
try
{
m_ANObj = new AndroidJavaObject("cn.gfplay.noti.AndroidNotificator");
}
catch
{
this.Text_Message.text = "Init AndroidNotificator Fail";
return false;
}
}
if (m_ANObj == null)
{
this.Text_Message.text = "AndroidNotificator Not Found.";
return false;
}
return true;
}
#endif
}
贴上我的Unity截图,简单的用原生UI测试了一下

遇到的一些问题:
1.推送的icon还还不是特清楚
2.出现过闪退的情况,原因是XML中的MainActivity错误
package cn.gfplay.noti;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
在XML的第五行的最后修改一下就好使了
<activity android:label="@string/app_name" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" android:name="cn.gfplay.noti.MainActivity">
3.目前只是推送一个消息,并没有添加点击事件,后续会在更新,调用不同的Notification.Builder的重载应该就是好使的.
后续写在了另一篇文章里Unity通知栏推送消息(二)