Unity本地推送消息(二)(完善)

這篇文章是對(duì)Unity通知欄推送的完善......

在上一篇文章Unity通知欄推送消息(一)里簡單介紹了Unity在IOS平臺(tái)的推送參考,以及安卓平臺(tái)僅推送消息的簡單實(shí)現(xiàn),這篇文章參考Git上的一個(gè)項(xiàng)目,進(jìn)行了一些完善,在原有的基礎(chǔ)上實(shí)現(xiàn)了通知消息的Action,以及通知的各種屬性的處理.

AndroidStudio里的處理

javaclass截圖
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è)類的方法會(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文件夾的處理
res截圖

注意drawable下的.png可自行修改,一般為應(yīng)用圖標(biāo),保證和Unity里的一樣即可

然后生成jar包

Unity里的處理

1.把jar包,AndroidManifest.xml,res文件夾,以及相關(guān)的arr包放到對(duì)應(yīng)的目錄下
Unity目錄截圖
2.修改.xml文件,其他改動(dòng)參考Unity通知欄推送消息(一),最后加上receiver如圖
.xml的修改
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)的值來實(shí)現(xiàn)不同的效果

按這個(gè)過程進(jìn)行下來,應(yīng)該是沒有問題,如果出錯(cuò)了:

1.檢查所有用到包名的地方 com.xx.xx 是否一致.
2.AndroidManifest.xml是否配置正確,如果不正確可以通過導(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 之本地推送

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容