这篇文章是对Unity通知栏推送的完善......
在上一篇文章Unity通知栏推送消息(一)里简单介绍了Unity在IOS平台的推送参考,以及安卓平台仅推送消息的简单实现,这篇文章参考Git上的一个项目,进行了一些完善,在原有的基础上实现了通知消息的Action,以及通知的各种属性的处理.
AndroidStudio里的处理
1.直接贴上代码供参考:
NotificationAction
package xx.xx.xx;
import android.os.Parcel;
import android.os.Parcelable;
public class NotificationAction implements Parcelable {
public static final Creator CREATOR = new Creator();
private String identifier;
private String title;
private String icon;
private boolean foreground;
private String gameObject;
private String handlerMethod;
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public boolean isForeground() { return foreground; }
public void setForeground(boolean foreground) { this.foreground = foreground; }
public String getGameObject() {
return gameObject;
}
public void setGameObject(String gameObject) {
this.gameObject = gameObject;
}
public String getHandlerMethod() {
return handlerMethod;
}
public void setHandlerMethod(String handlerMethod) {
this.handlerMethod = handlerMethod;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getIdentifier());
dest.writeString(getTitle());
dest.writeString(getIcon());
dest.writeInt(isForeground() ? 1 : 0);
dest.writeString(getGameObject());
dest.writeString(getHandlerMethod());
}
private static class Creator implements Parcelable.Creator {
@Override
public NotificationAction createFromParcel(Parcel source) {
NotificationAction action = new NotificationAction();
action.setIdentifier(source.readString());
action.setTitle(source.readString());
action.setIcon(source.readString());
action.setForeground(source.readInt() == 1);
action.setGameObject(source.readString());
action.setHandlerMethod(source.readString());
return action;
}
@Override
public NotificationAction[] newArray(int size) {
return new NotificationAction[size];
}
}
}
UnityNotificationActionHandler
package xx.xx.xx;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class UnityNotificationActionHandler extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int id = intent.getIntExtra("id", 0);
String gameObject = intent.getStringExtra("gameObject");
String handlerMethod = intent.getStringExtra("handlerMethod");
String actionId = intent.getStringExtra("actionId");
boolean foreground = intent.getBooleanExtra("foreground", true);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(id);
if (foreground) {
Intent launchIntent = new Intent(context, UnityPlayerActivity.class);
launchIntent.setPackage(null);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(launchIntent);
}
UnityPlayer.UnitySendMessage(gameObject, handlerMethod, actionId);
}
}
UnityNotificationManager 这个类的方法会在Unity中被调用到
package xx.xx.xx;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.media.AudioAttributes;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import com.unity3d.player.UnityPlayer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class UnityNotificationManager extends BroadcastReceiver
{
private static Set channels = new HashSet<>();
public static void CreateChannel(String identifier, String name, String description, int importance, String soundName, int enableLights, int lightColor, int enableVibration, long[] vibrationPattern, String bundle) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return;
channels.add(identifier);
NotificationManager nm = (NotificationManager) UnityPlayer.currentActivity.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(identifier, name, importance);
channel.setDescription(description);
if (soundName != null) {
Resources res = UnityPlayer.currentActivity.getResources();
int id = res.getIdentifier("raw/" + soundName, null, UnityPlayer.currentActivity.getPackageName());
AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();
channel.setSound(Uri.parse("android.resource://" + bundle + "/" + id), audioAttributes);
}
channel.enableLights(enableLights == 1);
channel.setLightColor(lightColor);
channel.enableVibration(enableVibration == 1);
if (vibrationPattern == null)
vibrationPattern = new long[] { 1000L, 1000L };
channel.setVibrationPattern(vibrationPattern);
nm.createNotificationChannel(channel);
}
private static void createChannelIfNeeded(String identifier, String name, String soundName, boolean enableLights, boolean enableVibration, String bundle) {
if (channels.contains(identifier))
return;
channels.add(identifier);
CreateChannel(identifier, name, identifier + " notifications", NotificationManager.IMPORTANCE_DEFAULT, soundName, enableLights ? 1 : 0, Color.GREEN, enableVibration ? 1 : 0, null, bundle);
}
public static void SetNotification(int id, long delayMs, String title, String message, String ticker, int sound, String soundName, int vibrate,
int lights, String largeIconResource, String smallIconResource, int bgColor, String bundle, String channel,
ArrayList actions)
{
Activity currentActivity = UnityPlayer.currentActivity;
AlarmManager am = (AlarmManager)currentActivity.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(currentActivity, UnityNotificationManager.class);
intent.putExtra("ticker", ticker);
intent.putExtra("title", title);
intent.putExtra("message", message);
intent.putExtra("id", id);
intent.putExtra("color", bgColor);
intent.putExtra("sound", sound == 1);
intent.putExtra("soundName", soundName);
intent.putExtra("vibrate", vibrate == 1);
intent.putExtra("lights", lights == 1);
intent.putExtra("l_icon", largeIconResource);
intent.putExtra("s_icon", smallIconResource);
intent.putExtra("bundle", bundle);
intent.putExtra("channel", channel);
Bundle b = new Bundle();
b.putParcelableArrayList("actions", actions);
intent.putExtra("actionsBundle", b);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayMs, PendingIntent.getBroadcast(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT));
else
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayMs, PendingIntent.getBroadcast(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
public static void SetRepeatingNotification(int id, long delayMs, String title, String message, String ticker, long rep, int sound, String soundName, int vibrate, int lights,
String largeIconResource, String smallIconResource, int bgColor, String bundle, String channel, ArrayList actions)
{
Activity currentActivity = UnityPlayer.currentActivity;
AlarmManager am = (AlarmManager)currentActivity.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(currentActivity, UnityNotificationManager.class);
intent.putExtra("ticker", ticker);
intent.putExtra("title", title);
intent.putExtra("message", message);
intent.putExtra("id", id);
intent.putExtra("color", bgColor);
intent.putExtra("sound", sound == 1);
intent.putExtra("soundName", soundName);
intent.putExtra("vibrate", vibrate == 1);
intent.putExtra("lights", lights == 1);
intent.putExtra("l_icon", largeIconResource);
intent.putExtra("s_icon", smallIconResource);
intent.putExtra("bundle", bundle);
intent.putExtra("channel", channel);
Bundle b = new Bundle();
b.putParcelableArrayList("actions", actions);
intent.putExtra("actionsBundle", b);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayMs, rep, PendingIntent.getBroadcast(currentActivity, id, intent, 0));
}
public void onReceive(Context context, Intent intent)
{
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
String ticker = intent.getStringExtra("ticker");
String title = intent.getStringExtra("title");
String message = intent.getStringExtra("message");
String s_icon = intent.getStringExtra("s_icon");
String l_icon = intent.getStringExtra("l_icon");
int color = intent.getIntExtra("color", 0);
String bundle = intent.getStringExtra("bundle");
Boolean sound = intent.getBooleanExtra("sound", false);
String soundName = intent.getStringExtra("soundName");
Boolean vibrate = intent.getBooleanExtra("vibrate", false);
Boolean lights = intent.getBooleanExtra("lights", false);
int id = intent.getIntExtra("id", 0);
String channel = intent.getStringExtra("channel");
Bundle b = intent.getBundleExtra("actionsBundle");
ArrayList actions = b.getParcelableArrayList("actions");
Resources res = context.getResources();
Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage(bundle);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntent(notificationIntent);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (channel == null)
channel = "default";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannelIfNeeded(channel, title, soundName, lights, vibrate, bundle);
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setContentTitle(title)
.setContentText(message);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
builder.setColor(color);
if (ticker != null && ticker.length() > 0)
builder.setTicker(ticker);
if (s_icon != null && s_icon.length() > 0)
builder.setSmallIcon(res.getIdentifier(s_icon, "drawable", context.getPackageName()));
if (l_icon != null && l_icon.length() > 0)
builder.setLargeIcon(BitmapFactory.decodeResource(res, res.getIdentifier(l_icon, "drawable", context.getPackageName())));
if (sound) {
if (soundName != null) {
int identifier = res.getIdentifier("raw/" + soundName, null, context.getPackageName());
builder.setSound(Uri.parse("android.resource://" + bundle + "/" + identifier));
} else
builder.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
}
if (vibrate)
builder.setVibrate(new long[] {
1000L, 1000L
});
if (lights)
builder.setLights(Color.GREEN, 3000, 3000);
if (actions != null) {
for (int i = 0; i < actions.size(); i++) {
NotificationAction action = actions.get(i);
int icon = 0;
if (action.getIcon() != null && action.getIcon().length() > 0)
icon = res.getIdentifier(action.getIcon(), "drawable", context.getPackageName());
builder.addAction(icon, action.getTitle(), buildActionIntent(action, i));
}
}
Notification notification = builder.build();
notificationManager.notify(id, notification);
}
private static PendingIntent buildActionIntent(NotificationAction action, int id) {
Activity currentActivity = UnityPlayer.currentActivity;
Intent intent = new Intent(currentActivity, UnityNotificationActionHandler.class);
intent.putExtra("id", id);
intent.putExtra("gameObject", action.getGameObject());
intent.putExtra("handlerMethod", action.getHandlerMethod());
intent.putExtra("actionId", action.getIdentifier());
intent.putExtra("foreground", action.isForeground());
return PendingIntent.getBroadcast(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public static void CancelPendingNotification(int id)
{
Activity currentActivity = UnityPlayer.currentActivity;
AlarmManager am = (AlarmManager)currentActivity.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(currentActivity, UnityNotificationManager.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pendingIntent);
}
public static void ClearShowingNotifications()
{
Activity currentActivity = UnityPlayer.currentActivity;
NotificationManager nm = (NotificationManager)currentActivity.getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancelAll();
}
}
2.res文件夹的处理
注意drawable下的.png可自行修改,一般为应用图标,保证和Unity里的一样即可
然后生成jar包
Unity里的处理
1.把jar包,AndroidManifest.xml,res文件夹,以及相关的arr包放到对应的目录下
2.修改.xml文件,其他改动参考Unity通知栏推送消息(一),最后加上receiver如图
3.C#代码的处理
截取了C#部分核心代码,以及java的代码进行参照分析
NotificationTest.cs里的方法
public void OneTimeWithActions()
{
Debug.Log("OneTimeWithActions");
LocalNotification.Action action1 = new LocalNotification.Action("background", "In Background", this);
action1.Foreground = true;
LocalNotification.Action action2 = new LocalNotification.Action("foreground", "In Foreground", this);
LocalNotification.SendNotification(1, 5000, "温馨提示", "多喝热水", new Color32(0xff, 0x44, 0x44, 255), false, true, true, null, "boing", "default", action1, action2);
}
LocalNotification.cs里的方法
public static int SendNotification(int id, long delayMs, string title, string message, Color32 bgColor, bool sound = true, bool vibrate = true, bool lights = true, string bigIcon = "", String soundName = null, string channel = "default", params Action[] actions)
{
AndroidJavaClass pluginClass = new AndroidJavaClass(fullClassName);
if (pluginClass != null)
{
pluginClass.CallStatic("SetNotification", id, delayMs, title, message, message,
sound ? 1 : 0, soundName, vibrate ? 1 : 0, lights ? 1 : 0, bigIcon, "notify_icon_small",
ToInt(bgColor), bundleIdentifier, channel, PopulateActions(actions));
}
return id;
}
public static void SetNotification(int id, long delayMs, String title, String message, String ticker, int sound, String soundName, int vibrate,
int lights, String largeIconResource, String smallIconResource, int bgColor, String bundle, String channel,
ArrayList actions)
{
Activity currentActivity = UnityPlayer.currentActivity;
AlarmManager am = (AlarmManager)currentActivity.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(currentActivity, UnityNotificationManager.class);
intent.putExtra("ticker", ticker);
intent.putExtra("title", title);
intent.putExtra("message", message);
intent.putExtra("id", id);
intent.putExtra("color", bgColor);
intent.putExtra("sound", sound == 1);
intent.putExtra("soundName", soundName);
intent.putExtra("vibrate", vibrate == 1);
intent.putExtra("lights", lights == 1);
intent.putExtra("l_icon", largeIconResource);
intent.putExtra("s_icon", smallIconResource);
intent.putExtra("bundle", bundle);
intent.putExtra("channel", channel);
Bundle b = new Bundle();
b.putParcelableArrayList("actions", actions);
intent.putExtra("actionsBundle", b);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayMs, PendingIntent.getBroadcast(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT));
else
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delayMs, PendingIntent.getBroadcast(currentActivity, id, intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
对应的参数很清晰,修改对应的值来实现不同的效果
按这个过程进行下来,应该是没有问题,如果出错了:
1.检查所有用到包名的地方 com.xx.xx 是否一致.
2.AndroidManifest.xml是否配置正确,如果不正确可以通过导出GoogleProject的方式获得,覆盖项目里的然后重新打包.
3.最后附上参考的Git上的项目可直接参考其中的代码,res,以及AndroidStudio项目里的文件
https://github.com/Agasper/unity-android-notifications
其他的博客参考:
在Unity3D中实现安卓平台的本地通知推送
Unity之android推送
unity3d 之本地推送