零基础教你Unity接入IOS原生本地推送

简介: 从新建项目开始保姆级教程,教你Unity接入IOS原生本地推送。

@TOC

从新建项目开始的保姆级教程,教你Unity接入IOS原生本地推送。

一,新建Unity项目

打开Unity Hub,点击 ”新建“ , 输入项目名称,选择存储位置,点击创建即可。

新建项目

创建后Unity会自动打开,我们先创建几个文件夹

  • IOSLocalNotification: 总目录,存储本次实例使用的所有相关文件
  • Editor: 二级文件夹,存储打包Xcode的自动配置脚本
  • Plugins: 存储对接IOS的桥接文件
  • Scenes: 存储场景,直接把创建项目的带进来就行了
  • Scripts: 存储项目Unity的.cs脚本

工程目录

修改场景名称为 ”LocalNotification“, 然后"场景从外部修改了" 我们点击 ”Reload“ 重新加载下就可以了。

修改场景名称

至此创建Unity项目和准备工作完成。


二,梳理程序流程

graph TD
  点击按钮触发本地推送--> 
    代码调用IOS桥接文件--> 
    IOS桥接文件调用IOS原生--> 
    IOS原生处理本地推送

三,处理代码逻辑

  • IOS端代码逻辑:

IOS端代码的编写,显然超出了本文的范畴(我也不会)。其实我们只要知道Unity代码如何能调用IOS的代码调用就可以了

比如,IOS代码:

// 移除所有通知
- (void)removeAllNotification {
    if (@available(iOS 10.0, *)) {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        [center removeAllPendingNotificationRequests];
    }else {
        [[UIApplication sharedApplication] cancelAllLocalNotifications];
    }
}

在Unity中的调用

#if UNITY_IOS
using System.Runtime.InteropServices;
#endif

public class LocalNotification_IOS : MonoBehaviour
{


#if UNITY_IOS
    // 移除所有推送 -- 调用到IOS
    [DllImport("__Internal")]
    private static extern void _removeAllNotification();   
#endif

    /// <summary>
    /// 移除所有推送
    /// </summary>
    public void RemoveAllNotification()
    {
        _removeAllNotification();
    }
}
    

这样写就实现了,从Unity调用到IOS了。
流程: Unity按钮点击触发RemoveAllNotification()方法 --> 方法体调用 _removeAllNotification() 通过[DllImport("__Internal")]关联到IOS --> 调用到IOS中的 (void)removeAllNotification

由于篇幅问题,IOS端完整代码我就不贴出来了,需要的童鞋点击本段末链接下载即可。


  • Unity代码逻辑:

创建LocalNotification_IOS.cs 放到Scripts文件夹下,此脚本处理对接IOS端代码逻辑:

using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
#if UNITY_IOS
using System.Runtime.InteropServices;
#endif

/// <summary>
/// 本地推送IOS -- 调用桥接文件
/// </summary>
public class LocalNotification_IOS : MonoBehaviour
{
    // 单例
    public static LocalNotification_IOS Instance;

    #region 当首次授权成功后需要重新添加首次的推送消息,以下变量用于首次推送时储存推送内容

    private string titleStr;
    private string subtitleStr;
    private string contentStr;
    private int time;
    private string identifier;

    #endregion
   
    private void Awake()
    {
        Instance = this;
        
        // 切换场景不销毁
        DontDestroyOnLoad(this.gameObject);
        
        // 移除所有推送
        #if !UNITY_EDITOR
        RemoveAllNotification();
        #endif
    }

#if UNITY_IOS
    // 对接IOS端代码逻辑
    [DllImport("__Internal")]
    private static extern void _addLocalNotice(string titleStr,string subtitleStr,string contentStr,int time,string identifier);
    [DllImport("__Internal")]
    private static extern void _registerAPN();
    [DllImport("__Internal")]
    private static extern void _removeOneNotificationWithID(string noticeId);
    [DllImport("__Internal")]
    private static extern void _removeAllNotification();
    [DllImport("__Internal")]
    private static extern bool _haveNoticeNotifocation();
    [DllImport("__Internal")]
    private static extern void _checkPermission();    
    [DllImport("__Internal")]
    private static extern void _showSettingAlert(string title, string content, string leftTxt, string rightTxt);

    /// <summary>
    /// 注册APN推送通道
    /// </summary>
    private void RegisterAPN()
    {
#if !UNITY_EDITOR
        _registerAPN();
#endif
    }

    /// <summary>
    /// 判断当前是否开始了授权权限
    /// </summary>
    /// <returns></returns>
    public bool HaveNoticeNotifocation()
    {
#if !UNITY_EDITOR
        Debug.Log("判断当前是否开始了授权权限"+_haveNoticeNotifocation());
        return _haveNoticeNotifocation();
#endif
        return true;
    }

    /// <summary>
    /// 通知授权回调
    /// </summary>
    /// <param name="ret">结果</param>
    public void GetpermissionCallBack(string ret)
    {
        //授权成功后重新添加首次的本地通知
        AddLocalNotice(titleStr,subtitleStr,contentStr,time,identifier);
    }
    
    /// <summary>
    /// 判断是否注册了通知权限回调
    /// </summary>
    /// <param name="ret"></param>
    public void CheckPermissionCallBack(string ret)
    {
        Debug.Log("判断是否注册了通知权限回调..." + ret);
    }
    
    /// <summary>
    /// 添加一条推送
    /// </summary>
    /// <param name="titleStr">标题</param>
    /// <param name="subtitleStr">副标题</param>
    /// <param name="contentStr">内容</param>
    /// <param name="time">时间(多少秒之后)</param>
    /// <param name="identifier">标识符,用于移除单条推送</param>
    public void AddLocalNotice(string titleStr, string subtitleStr, string contentStr, int time, string identifier)
    {
        if (HaveNoticeNotifocation())
        {
#if !UNITY_EDITOR
            if (time>0)
            {
                _addLocalNotice(titleStr, subtitleStr, contentStr, time, identifier);
            }
#endif
        }
        else
        {
            this.titleStr = titleStr;
            this.subtitleStr = subtitleStr;
            this.contentStr = contentStr;
            this.time = time;
            this.identifier = identifier;
            _checkPermission();            
        }

    }
    /// <summary>
    /// 移除单个推送
    /// </summary>
    /// <param name="noticeId">标识符</param>
    public void RemoveOneNotificationWithID(string noticeId)
    {
#if !UNITY_EDITOR
        _removeOneNotificationWithID(noticeId);
#endif
    }
    /// <summary>
    /// 移除所有推送
    /// </summary>
    public void RemoveAllNotification()
    {
#if !UNITY_EDITOR
        _removeAllNotification();
#endif
    }

    /// <summary>
    /// 显示提示信息
    /// </summary>
    /// <param name="title">标题</param>
    /// <param name="content">显示文本</param>
    /// <param name="cancelTxt">取消</param>
    /// <param name="okTxt">点击OK按钮内容</param>
    public void ShowSettingAlert(string title,string content,string cancelTxt,string okTxt)
    {
        _showSettingAlert(title, content, cancelTxt, okTxt);
    }
#endif
}

创建LocalNotificationTest.cs 放到Scripts文件夹下,此脚本是处理Unity通过按钮点击调用的本地推送和移除推送逻辑:

using UnityEngine;
using UnityEngine.UI;

public class LocalNotificationTest : MonoBehaviour
{
    /// <summary>
    /// 推送标签 -- 可根据这个标签关闭未推送消息
    /// </summary>
    private readonly string pushLabelString = "本地推送标签";
    /// <summary>
    /// 推送时间 -- 60表示60秒后推送消息
    /// </summary>
    private int pushTime = 60;
    
    // 开启推送按钮
    public Button StartPushBtn;
    // 关闭推送按钮
    public Button StopPushBtn;

    void Start()
    {
        StartPushBtn.onClick.AddListener(() => { PushSwitch(true); });
        StopPushBtn.onClick.AddListener(() => { PushSwitch(false); });
    }

    void PushSwitch(bool isOn)
    {
#if UNITY_EDITOR
        Debug.Log("PushSwitch 满体力值推送..." + isOn);
#elif UNITY_IOS
        if (isOn)
        {
            if(!LocalNotification_IOS.Instance.HaveNoticeNotifocation())
            {
                string title = "提示";
                string content = "功能不可用,请在设置->通知->游戏->设置允许通知";
                string cancelTxt = "取消";
                string okTxt = "去设置";
                LocalNotification_IOS.Instance.ShowSettingAlert(title, content, cancelTxt, okTxt);
            }
            else
            {
                SetPushContext();
            }
        }
        else
        {
            LocalNotification_IOS.Instance.RemoveOneNotificationWithID(pushLabelString);
        }
#endif
    }
    
    // 设置推送内容
    void SetPushContext()
    {
#if UNITY_EDITOR
        Debug.Log("推送内容设置,发起定时推送");
#elif UNITY_IOS
        // 推送前关闭同标签未推送消息
        // LocalNotification_IOS.Instance.RemoveOneNotificationWithID(pushLabelString);
        // 设置推送
        LocalNotification_IOS.Instance.AddLocalNotice("应用名称", "本地推送标题!","本地推送内容...", pushTime, pushLabelString);
#endif
    }

}

所有代码在工程下的目录:

代码目录

这是所有代码网盘链接, 密码: b7jm

源码分享在文末哦~ 别着急,先按照步骤看完吧。


四,测试场景搭建

场景搭建赋值步骤如下:

  1. 创建两个按钮,修改文本内容和显示位置调整
  2. 创建一个空物体并挂载脚本LocalNotification_IOS和LocalNotificationTest脚本
  3. 将两个按钮拖拽赋值给LocalNotificationTest

整体程序结构如下图:

工程目录


五,处理自动配置

创建脚本IOSAggregateEditor.cs 放到Editor文件夹下, 此脚本为编辑器脚本,只处理IOS打包自动配置:

using System.IO;
using UnityEditor;
using UnityEngine;
#if UNITY_IOS
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
#endif

/// <summary>
/// IOS打包自动配置文件
/// </summary>
public class IOSAggregateEditor
{
#if UNITY_IOS
    [PostProcessBuildAttribute(100)]
    public static void onPostProcessBuild(BuildTarget target, string targetPath)
    {
        if (target != BuildTarget.iOS)
        {
            return;
        }

        string projPath = PBXProject.GetPBXProjectPath(targetPath);
        PBXProject proj = new PBXProject();
        proj.ReadFromString(File.ReadAllText(projPath));
        string unityTarget = proj.GetUnityFrameworkTargetGuid();

        //*******************************添加framework*******************************//
        proj.AddFrameworkToProject(unityTarget, "UserNotifications.framework", false);
 
        string content = proj.WriteToString();
        File.WriteAllText(projPath, content);
    }
#endif
}

六,双端打包测试

  • Unity打包设置:

设置公司名称,项目名称(随便起,只要IOS开发者账号允许打包即可)

项目配置

通过 “File” --> “Build Setting...” 打开Build Setting弹窗,如下图:

打开BudildSetting

选择 “IOS” 后,点击右下角 “Switch Platform” 按钮,切换到IOS平台,如下图:

切换平台

等待进度条完成即可。
切换进度

切换平台后点击 “Add Open Scenes” 添加当前场景到Scenes In Build,最后点击右下角 “Build” 按钮导出Xcode工程,如下图:

Build设置

然后命名为 “IOSLocalPushXcode” 指定到当前工程目录,选择 “Save” 导出Xcode工程:

导出Xcode


  • Xcode打包设置:

Xcode工程目录如下,然后双击 ”Unity-iPhone.xcodeproj“ 打开Xcode工程:

Xcode目录

打开Xcode后,左侧选择 “Unity-iPhone”, 上面选择 ”Signing & Capabilities“,然后选择Team。

Xcode设置

最后连线选择设备,点击运行,等待进度条完成,自动安装成功即可:

安装运行


七,查看测试结果

打开程序点击 “开启本地推送按钮” ,

首次点击开启推送按钮会出现提示 —> 选择 “去设置” —> 然后选择 “允许” 消息推送
设置允许后,后续点击开启推送按钮则不会进行此提示,会默认开始设置推送。

开启推送

允许后,将退出程序(关闭进程),等待设置的推送时间后,在IOS上会显示如下推送消息:
【注意点击推送后一定要关闭程序,程序在线是不会进行推送的】

推送成功

上图可以看到,我们在代码中设置的标题,内容等属性都可以在通知中显示出来,大功告成。

相关文章
|
7月前
|
iOS开发
Flutter与iOS原生通信方式
Flutter与iOS原生通信方式
313 2
|
JSON JavaScript 前端开发
iOS小技能: 开发 uni-app 原生插件(支持iOS Extension)
术语:uni原生插件指的是将`原生开发的功能按照规范封装成插件包`,然后即可在 uni-app 前端项目中通过js调用原生能力。
795 0
iOS小技能: 开发 uni-app 原生插件(支持iOS Extension)
|
4月前
|
存储 移动开发 JavaScript
【原生】sd.js帮助您简化繁重的获取数据、存储数据(CRUD)骚操作(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)
【原生】sd.js帮助您简化繁重的获取数据、存储数据(CRUD)骚操作(吐槽~在安卓9.0以下或者IOS10.X以下手机端H5页面不支持,在这两种情况下的系统只能使用ajax或者原生js请求后台数据)
|
7月前
|
Dart 开发工具 Android开发
Flutter与iOS原生混合开发
Flutter与iOS原生混合开发
347 2
|
自然语言处理 开发工具 Swift
移动用户反馈-iOS接入指南 | 学习笔记
快速学习移动用户反馈-iOS接入指南
222 0
移动用户反馈-iOS接入指南 | 学习笔记
|
iOS开发 芯片 MacOS
macOS Big Sur 正式发布并已开放下载,支持原生运行 iOS 和 iPadOS App
macOS Big Sur 正式发布并已开放下载,支持原生运行 iOS 和 iPadOS App
149 0
|
数据管理 测试技术 C#
一个近乎完美的Unity全平台原生c#热更方案
HybridCLR是一个特性完整、零成本、高性能、低内存的近乎完美的Unity全平台原生c#热更方案。
514 0
一个近乎完美的Unity全平台原生c#热更方案
|
存储 负载均衡 安全
【Unity干货教程】如何实现Unity和Android原生互相调用?
Unity是一个跨平台开发工具,发布到移动平台也是大部分Unity开发者的必备技能。而由于Unity跨平台的特性,总会遇到在移动平台的技术细节支持不够,或者需要在调用其他原生插件的情况。这里我们说一下如何在Android Studio中创建一个可供Unity调用的aar插件,以实现Unity和Android原生互相调用的目的。
|
移动开发 JavaScript weex
week-iOS的扩展之内置模块,将原生模块做成标签在weex中使用
week-iOS的扩展之内置模块,将原生模块做成标签在weex中使用
94 0
week-iOS的扩展之内置模块,将原生模块做成标签在weex中使用
|
移动开发 JavaScript weex
weex-自定义module,实现weex在iOS的本地化,js之间互相跳转,交互,传值(iOS接入weex的最佳方式)
weex-自定义module,实现weex在iOS的本地化,js之间互相跳转,交互,传值(iOS接入weex的最佳方式)
219 0