這篇文章是對(duì)Unity通知欄推送的完善......
在上一篇文章Unity通知欄推送消息(一)里簡(jiǎn)單介紹了Unity在IOS平臺(tái)的推送參考,以及安卓平臺(tái)僅推送消息的簡(jiǎn)單實(shí)現(xiàn),這篇文章參考Git上的一個(gè)項(xiàng)目,進(jìn)行了一些完善,在原有的基礎(chǔ)上實(shí)現(xiàn)了通知消息的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<NotificationAction> {
@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 這個(gè)類(lèi)的方法會(huì)在Unity中被調(diào)用到
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<String> 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<NotificationAction> 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<NotificationAction> 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<NotificationAction> 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可自行修改,一般為應(yīng)用圖標(biāo),保證和Unity里的一樣即可
然后生成jar包
Unity里的處理
1.把jar包,AndroidManifest.xml,res文件夾,以及相關(guān)的arr包放到對(duì)應(yīng)的目錄下
2.修改.xml文件,其他改動(dòng)參考Unity通知欄推送消息(一),最后加上receiver如圖
3.C#代碼的處理
截取了C#部分核心代碼,以及java的代碼進(jìn)行參照分析
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<NotificationAction> 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));
}
對(duì)應(yīng)的參數(shù)很清晰,修改對(duì)應(yīng)的值來(lái)實(shí)現(xiàn)不同的效果
按這個(gè)過(guò)程進(jìn)行下來(lái),應(yīng)該是沒(méi)有問(wèn)題,如果出錯(cuò)了:
1.檢查所有用到包名的地方 com.xx.xx 是否一致.
2.AndroidManifest.xml是否配置正確,如果不正確可以通過(guò)導(dǎo)出GoogleProject的方式獲得,覆蓋項(xiàng)目里的然后重新打包.
3.最后附上參考的Git上的項(xiàng)目可直接參考其中的代碼,res,以及AndroidStudio項(xiàng)目里的文件
https://github.com/Agasper/unity-android-notifications
其他的博客參考:
在Unity3D中實(shí)現(xiàn)安卓平臺(tái)的本地通知推送
Unity之a(chǎn)ndroid推送
unity3d 之本地推送