【前言】

  对于手游来说,什么时候需要推送呢?玩过一些带体力限制的游戏就会发现,我的体力在恢复满后,手机会收到一个通知告诉我体力已完全恢复了。这类通知通常是由本地的客户端发起的,没有经过服务端。

  在安卓应用中,本地通知推送是通过调用系统级服务NotificationManager实现的。虽然U3D本身也有NotificationServices类可以进行通知推送,但仅限于iOS平台(这篇博文讲了怎么使用它在iOS平台发起本机推送)。

  而现在我们的游戏是使用U3D开发的,并不能像安卓开发一样直接在代码中调用服务。为了实现本地定时推送效果,需要自己写一个插件来实现了。

  由于推送通常发生在客户端关闭的状态,这个推送应该被放在一个延时服务中,否则玩游戏玩得好好的突然跳出来一条自己的推送,太诡异了。

  于是我们需要完成一个提供三个功能的模块:1、设定X秒后显示一条推送通知;2、设定X秒后显示一条通知,之后每天再显示一次;3、清除本应用的所有推送。


【解决思路】

  因为U3D引擎提供了调用jar包的方法,所以我们可以在jar包中调用安卓的类库,实现消息推送,然后在jar包中留出接口供U3D使用即可,没有必要走JNI层。


【所需工具】

  ● eclipse

  ● 安卓SDK(我使用的4.4)

  ● Unity编辑器(我使用的5.1.3)


【开工】

  1、  创建jar包工程

    创建的时候要引入两个第三方jar包。

    一个是Unity的包,地址: Unity安装目录\Editor\Data\PlaybackEngines\androidplayer\release\bin\classes.jar(貌似4.x的目录和5.x不太一样,但总之就是找到androidplayer里面的classes.jar)

    还有一个是安卓SDK的包,地址: 安卓SDK安装目录\platforms\安卓版本\android.jar

    

  2、  编码

    思路就是使用AlarmManager服务,在一定时间后发起广播,然后通过接收器接受展示。如果你做过安卓开发,对这段代码肯定不会陌生。如果没做过也没关系,当成一个黑盒,在需要的时候调接口就行。

    首先添加一个Java类,注意父类要设为BroadcastReceiver。

    

    

    添加完成后,就可以开始写了:

package com.guyastudio.unityplugins;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;/*** 用于生成 / 清除本地通知推送的插件* 仅在安卓平台有效* * @author Weiren**/
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, 86400, // 24 hourspi); } 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();Notification notification = new Notification(applicationInfo.icon, (String)bundle.get("appname"), System.currentTimeMillis());     PendingIntent contentIntent = PendingIntent.getActivity(pContext, m_nLastID, new Intent(pContext, unityActivity), 0);   notification.setLatestEventInfo(pContext,(String)bundle.get("title"), (String)bundle.get("content"), contentIntent);NotificationManager nm = (NotificationManager)pContext.getSystemService(Context.NOTIFICATION_SERVICE);  nm.notify(m_nLastID, notification);  m_nLastID++;}
}

  

  3、  导出jar包

    在项目上右键——Export,导出为jar格式。

    

  4、添加AndroidManifest.xml

    安卓应用中如果要让应用收到广播,还需要在AndroidManifest.xml中加入receiver标签。我们创建的项目是一个Java项目,不会自动生成AndroidManifest,所以需要手动写一个:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="preferExternal" android:theme="@android:style/Theme.NoTitleBar" android:versionName="1.0" android:versionCode="10"><supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" /><application android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false">  <receiver android:process=":remote" android:name="com.macaronics.notification.AlarmReceiver"></receiver><activity android:name="com.unity3d.player.UnityPlayerProxyActivity" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" ></activity><receiver android:name="com.guyastudio.unityplugins.AndroidNotificator" ><intent-filter><action android:name="UNITY_NOTIFICATOR" /></intent-filter></receiver></application><uses-feature android:glEsVersion="0x00020000" /><uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /></manifest>

  ● 注意“<action android:name="UNITY_NOTIFICATOR" />”这里名字要和前面Java代码中的一致。

  4、  在U3D项目中调用

    创建一个新的U3D项目,在界面上放一个Text和两个Button(为节约时间我用的源生UI):

    

    

    然后将导出的jar文件和AndroidManifest.xml文件移动到 U3D项目目录\Assets\Plugins\Android下:

    

    在几个UI的父节点上加一个脚本,内容如下:

using UnityEngine;
using UnityEngine.UI;public class JARTest : MonoBehaviour {public Text Text_Message;#if UNITY_ANDROIDprivate AndroidJavaObject m_ANObj = null;
#endif// Use this for initializationvoid Start () { }// Update is called once per framevoid Update () { }public void Button_1_Clicked(){
#if UNITY_ANDROIDif(InitNotificator()){m_ANObj.CallStatic("ShowNotification",Application.productName,"温馨提示","你该食屎了",10,false);this.Text_Message.text = "Notification will show in 10 sec.";}
#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_ANDROIDprivate bool InitNotificator(){if (m_ANObj == null){try{m_ANObj = new AndroidJavaObject("com.guyastudio.unityplugins.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
}

    ● 注意实例化AndroidJavaObject的参数名字要和Java工程的包名类名一致。

    然后绑定控件和事件方法。绑定好后先编译一下,如果通过了,就可以导出一个apk包了。将这个包安装到安卓设备上。我手头没有安卓设备,就用模拟器来测试:

    

    

    点击“Show”按钮,10秒后会收到通知(点击后可将应用至后台,或杀掉):

    

    

    而点击“Clean”按钮,通知都会被清除。

    至此,这个通知插件就完成了。


【后记】

  最近两个月经历了辞职,以休息的名义玩(主要是肝夏活,你懂的),苦逼地找工作,意外地入职这一系列过程,心情比较复杂,博客这一块也一直没上。直到今天在项目中搞了个这个模块,才意识到可以稍微更新一下。

  我知道你们想要谱面编辑器教程(

  好吧,完整的制作过程我看来是没时间写出来了,这周末讲一下核心部分的逻辑,核心搞懂了其他都很简单了。不发直播拆大和,我是认真的!

 

转载于:https://www.cnblogs.com/GuyaWeiren/p/4830854.html

在Unity3D中实现安卓平台的本地通知推送相关推荐

  1. 游戏陪玩平台源码开发,关于本地通知推送实现的详细解析

    游戏陪玩平台源码开发也是需要实现推送功能的,这样用户就能在第一时间了解平台消息以及好友发送的消息.这虽然只是一个小的方面,但却有着不容忽视的作用.今天我们主要了解一下利用系统的原生推送类结合工程实践如 ...

  2. android 本地提醒功能,android中的本地定时推送到通知栏

    一.使用系统定义的Notification 以下是使用示例代码: import android.app.Notification; import android.app.NotificationMan ...

  3. Java后端实现安卓/IOS移动端消息推送(百度云推送)

    本文主要介绍Java服务器端如何借助第三方推送平台(百度云推送)推送给移动端消息. 使用案例介绍: 根据客户的需求,需要做一个类似淘宝消息推送的功能,客户下订单.订单付款.订单商品已发货,以及客户完成 ...

  4. Git使用及创建本地文件推送到github仓库

    Git使用 一.安装Git 一般我们工作的电脑都是Windows系统,要使用git首先要进行安装.从软件管家或者其他平台找到git的安装包,下载后默认安装即可. 安装成功之后,可以在开始菜单里面找到g ...

  5. docker学习(三):docker镜像分层原理及本地镜像推送到阿里云或私服

    文章目录 前言 docker镜像分层加载原理 docker镜像commit操作产生新镜像 本地镜像发布到阿里云 将本地镜像推送到私有库 前言 大家好,这是我学习docker系列的笔记文章,目标是掌握d ...

  6. Windows平台RTMP/RTSP直播推送模块设计和使用说明

    开发背景 好多开发者一直反馈,Windows平台,做个推屏或者推摄像头,推RTMP或者RTSP出去,不知道哪些功能是必须的,哪些设计是可有可无的,还有就是,不知道如何选技术方案,以下是基于我们设计的W ...

  7. 【Git】IntelliJ IDEA 提交代码到 GitCode 远程仓库 ( GitCode 创建远程仓库 | 将本地工程推送到 GitCode 远程仓库 | 验证权限 | 生成个人访问令牌 )

    文章目录 前言 一.GitCode 创建远程仓库 二.将本地工程推送到 GitCode 远程仓库 三.验证权限 前言 GitHub 又挂了 , 国内不太好用 , 现在开始使用 gitcode , 地址 ...

  8. idea怎么把代码放到git_在IDEA中如何初始化Git,把项目推送到Git上

    在IDEA中如何初始化Git,把项目推送到Git上 登录Gitee(码云)账号,新建仓库 先按如下步骤简单新建一个仓库: 创建成功后,会出现下图中所示的原始文件: 在IDEA上的Terminal中进行 ...

  9. IDEA使用Git将本地工程推送到远程仓库

    本篇文章介绍一下,IDEA开发工具如何使用Git将本地工程推送到远程仓库,具体步骤如下所示. 目录 (1)创建gitee远程仓库 (2)创建本地工程 (3)初始化本地仓库 (4)提交代码到本地仓库 ( ...

最新文章

  1. R语言使用edit函数在Rsudio中生成数据编辑器(在windows中生成编辑器)、在编辑器中输出需要的数据生成最终的dataframe
  2. ylinux系统找到软件_电脑用了段时间发现多处一些软件该怎么办?
  3. DVWA系列之21 存储型XSS分析与利用
  4. python global 变量_python 全局变量和局部变量 (例子)
  5. Arbitrage(判断正环 spfa写法)
  6. Cesium官方教程6--相机
  7. AI学习笔记(十八)NLP常见场景之情感分析
  8. 四通滑阀非对称液压缸matlab,基于MATLAB-simulink的液压系统动态仿真PPT课件
  9. 软考中级软件设计师-加密技术(自用)
  10. oracle数据库中汉字转化成拼音
  11. 特朗普Twitter账号解封!马斯克:人民的声音,上帝的声音
  12. TextRank算法原理简析、代码实现
  13. 十万个Web3为什么:什么是Optimism?它靠何法宝帮助以太坊扩容?
  14. linux卸载exe文件怎么恢复,linux中误删除程序包恢复实例
  15. 嘉兴 机器人仓库 菜鸟_菜鸟智能机器人仓库启用 助力包裹分得又快又好
  16. C# CSharp计算标准偏差 重复精度 和Excel中的STDEV函数相同
  17. 无法启动此程序,因为计算机丢失api-ms-win-crt-process-l1-1-0.dll
  18. 营销系列(1)数字营销通识——广告人应掌握的营销、广告概念
  19. 网站域名在微信端被封禁了怎么办?这样几步就能解封!
  20. epl2编程指南_epl幻想gw2回顾和gw3算法精选

热门文章

  1. iOS 获取屏幕的属性和宽度
  2. Oracle、DB2、SQLSERVER、Mysql、Access分页SQL语句梳理
  3. 为什么要用Web Service
  4. C++---继承总结
  5. 零基础带你学习MySQL—Delete语句以及注意事项(九)
  6. 【PHP学习】—数组的定义和遍历(三)
  7. 如何看出男朋友有没有潜力?
  8. htaccess有什么用
  9. 大多数人贫穷到极致时,就是富人灾难的开始,你认同这句话吗?
  10. 农村俗语“一代亲、二代淡,三代不管饭”啥意思?