接着上篇,本篇对SDK接口进行封装。在开始之前,需要先了解下面知识。

(1)unity与android之间的交互

unity通过下面方式调用android中的函数:

方法一:

AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
AndroidJavaObject _mActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");
_mActivity.Call("函数名");

方法二:

AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");//括号里可以是任意jar包的包名+类名
jc.CallStatic("函数名");

上面代码第一种先获得UnityPlayer类,UnityPlayer类是unity导出Android工程后生成的unity-classes.jar里的类。然后再获取静态变量_mActivity,_mActivity 是Activity类型,由此获得了Android当前的Activity,然后再调用此Activity中的方法。我们可以看一下unity自动生成的classes.jar中的源码:

第二种是通过包名+类名获取该类,直接调用类中的静态方法来实现的。可以是任意自定义的包名和类名。但这种就与Android的生命周期无关了。

我们可以这么理解Android应用中一个界面是一个Activity,两个界面的跳转就是两个Activity之间的跳转(类似的iOS是UIController之间的跳转)。其实我们unity游戏在Android上也是一个Android应用,所以它也是运行在一个Activity上的,这个Activity叫UnityPlayerActivity,它继承自Activity,看源码如下,每个Activity初始化的时候会首先执行onCreate()方法,所以通常把SDK的初始化函数也放在这个函数中。它就会随着Android的生命周期进行初始化,这是第一种做法,也是最常用的SDK初始化方法。还有一种SDK初始化的方法,就是自己新建一个jar包,在jar包中新建类,在类中写一些SDK初始化的静态方法,然后通过方法二在unity中调用这些方法进行初始化。我们这里采用大多数人使用的方法一,即在onCreate()中初始化。

有了上面的了解,我们开始进行unity的通用接口的开发。我们需要一个SDKManager类来管理所有调用SDK接口的方法,代码如下,把脚本挂在一个空物体上。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System; public class SDKManager : MonoBehaviour { private static SDKManager _instance = null;
public static SDKManager Instance
{
get
{
return _instance;
}
} private void Awake()
{
if (_instance != null)
{
GameObject.Destroy(this.gameObject);
}
_instance = this; InitSDKManager(); DontDestroyOnLoad(this);
} private void OnDestroy()
{
if (_instance == this) {
_instance = null;
}
} #if UNITY_ANDROID && !UNITY_EDITOR
private static string UNITY_CLASS = "com.unity3d.player.UnityPlayer";
private AndroidJavaObject _mActivity;
#endif
public void InitSDKManager()
{
#if UNITY_ANDROID && !UNITY_EDITOR
AndroidJavaClass jc = new AndroidJavaClass (UNITY_CLASS);
_mActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");
#endif
} //信鸽SDK接口
public void GetPushToken()
{
#if UNITY_ANDROID && !UNITY_EDITOR
_pushToken = _mActivity.Call<string>("GetXGPushTokenNew");
#endif
} public void SetXGPushTag(string tag)
{
#if UNITY_ANDROID && !UNITY_EDITOR
_mActivity.Call("SetXGPushTag",tag);
#endif
} public void AddLocalPushNotificationAndroid(string content, DateTime date, bool isRepeatEveryday = false)
{
#if UNITY_ANDROID && !UNITY_EDITOR
int isRepeat = ;
if (isRepeatEveryday == true)
{
isRepeat = ;
} _mActivity.Call("AddLocalNotification","SDK集合",content, date.ToString("yyyyMMdd"), date.ToString("HH"), date.ToString("mm"),isRepeat);
#endif
} public void ClearAllLocalNotificationAndroid()
{
#if UNITY_ANDROID && !UNITY_EDITOR
_mActivity.Call("ClearAllLocalNotification");
#endif
} //buglySDK接口
//启动c#异常捕获上报功能
public void buglyCatch()
{
Debug.Log("start Bugly report");
BuglyAgent.EnableExceptionHandler(); } }

然后新建一个Test脚本挂在摄像机上,调用这些接口:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System; public class Test : MonoBehaviour
{ void OnGUI()
{
if (GUILayout.Button("信鸽推送", GUILayout.Width(100.0f), GUILayout.Height(50.0f)))
{
DateTime noticeTime = new DateTime(, , , , , );
SDKManager.Instance.AddLocalPushNotificationAndroid("信鸽给你的推送", noticeTime);
}
if (GUILayout.Button("清除本地推送", GUILayout.Width(100.0f), GUILayout.Height(50.0f)))
{ SDKManager.Instance.ClearAllLocalNotificationAndroid();
}
if (GUILayout.Button("开启Bugly异常上报", GUILayout.Width(100.0f), GUILayout.Height(50.0f)))
{
SDKManager.Instance.buglyCatch();
}
}
}

上面代码,我们新建一个SDKManaget单例类,把每个SDK的接口封装成一个函数。像信鸽这种原生的jar包中的方法,我们就用_mActivity.Call()去调用,像bugly这种提供了接口的,我们直接调用提供的接口。通用接口类就介绍到这里,下面我们来实现_mActivity.Call()中调用的Android工程里的方法。使用Android Studio(2.3.3)新建一个工程。我们的目的是做一个jar包,这个jar包作用有两点:(1)用来对接unity调用jar包里的方法。(2)对接unity导出的Android工程的生命周期。这是我们为什么选择上面第一种接入方法的原因。上面说过unity运行的Activity是UnityPlayerActivity,我们新建一个类MainActivity,继承com.unity3d.player.UnityPlayerNativeActivity,而UnityPlayerNativeActivity继承UnityPlayerActivity。然后在AndroidManifest.xml里设置MainActivity为启动的Activity,所以MainActivity就是当前unity运行的Activity。我们通过_mActivity = jc.GetStatic<AndroidJavaObject>("currentActivity")获取到的就是MainActivity,然后我们在MainActivity中实现被unity调用的函数。代码:

public class MainActivity extends com.unity3d.player.UnityPlayerNativeActivity {

   private static boolean _isXGRegisterSuccess = false;
private static String _pushToken = ""; @Override
protected void onCreate(Bundle savedInstanceState)
{
if (savedInstanceState == null)
{
savedInstanceState = new Bundle();
}
super.onCreate(savedInstanceState);
Log.d("myGame", "MainActivity onCreate Called"); InitBugly();
InitXG();
} void InitBugly()
{
CrashReport.initCrashReport(getApplicationContext(),"aaaaaaaa",false);
} void InitXG(){
XGPushConfig.enableDebug(this,false);
MsgReceiver testReceiver = new MsgReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.abc.def.receiveintent");
registerReceiver(testReceiver,intentFilter);
XGPushManager.registerPush(this, new XGIOperateCallback() {
@Override
public void onSuccess(Object o, int i) {
Log.w("XGPush","XGsuccess:"+o);
_isXGRegisterSuccess = true;
_pushToken = o.toString();
} @Override
public void onFail(Object o, int i, String s) {
_isXGRegisterSuccess = false;
Log.w("XGPush","failed:"+i+", msg:"+s);
}
});
} public void AddLocalNotification(String title, String content, String date, String hour, String min, int isRepeatEveryday)
{
if (_isXGRegisterSuccess)
{
XGLocalMessage msg = new XGLocalMessage();
msg.setTitle(title);
msg.setContent(content);
msg.setDate(date);
msg.setHour(hour);
msg.setMin(min); int notifyIconId = getResources().getIdentifier("notify_icon", "drawable", getPackageName());
Log.e("notify icon id",notifyIconId+"");
msg.setSmall_icon(Integer.toString(notifyIconId)); int _hour = Integer.parseInt(hour);
int _min = Integer.parseInt(min);
msg.setRing(1); XGPushManager.addLocalNotification(MainActivity.this,msg);
}
}
public void ClearAllLocalNotification()
{
Log.w("ClearAllLocalNotice","success");
if (_isXGRegisterSuccess)
{
XGPushManager.clearLocalNotifications(MainActivity.this);
}
}
}

如果需要在启动unity的Activity(即MainActivity)前做一些处理,你可以新建一个类SplashActivity继承Activity,设置SplashActivity为启动Activity,然后跳转到MainActivity。就可以在SplashActivity中做一些启动游戏前的处理。我们把上述工作做完后,就可以将这些类打包成一个jar包(AS如何打jar包,再说),导入unity导出的Android工程中就可以了。到这里通用接口的开发就完了。还剩下一项工作就是我们之前从unity中提取出来的SDK资源,我们需要添加到Android工程中,下面就介绍如何进行资源管理,把资源添加到unity导出的Android工程中。

注:

AS打jar包,在build.gradle最后加这些代码:

task makeJar(type: Jar, dependsOn:['build']){
archiveName = 'QuicksdkDemo.jar' //包名
from('build/intermediates/classes/debug/')
destinationDir = file('build/libs') //导出路径
exclude('com/taiyouxi/a3k/BuildConfig.class') //不打进包的文件
exclude('com/taiyouxi/a3k/BuildConfig\$*.class') //不打进包的文件
exclude('**/R.class') //不打进包的文件
exclude('**/R\$*.class') //不打进包的文件
include('com/taiyouxi/a3k/*.class') //需要打进包的文件
include('com/quicksdk/unity/*.class') //需要打进包的文件
include('com/weibo/*.class') //需要打进包的文件
include('com/wxapi/*.class') //需要打进包的文件
}
makeJar.dependsOn(build)

然后打开Terminal窗口,输入gradlew makeJar然后回车:

gradlew makeJar

打出的包在build>libs文件夹下如图:

Unity接入多个SDK的通用接口开发与资源管理(二)的更多相关文章

  1. Unity接入多个SDK的通用接口开发与资源管理(三)

    接着上篇,介绍SDK资源的导入.首先介绍一下Android Studio工程. AS工程可以由多个Module组成,我们可以把某个Module作为我们打包的Module,其他的Module当做资源导入 ...

  2. Unity接入多个SDK的通用接口开发与资源管理(一)

    每一款游戏都有接入多个SDK的需求.当接入多个SDK时会面临两个问题: (1)代码层面:每个SDK都有调用各自功能的方法,我们需要统一管理每个SDK提供的方法,这样会使每个SDK调用方便,使代码整洁易 ...

  3. Senparc.Weixin.MP SDK 微信公众平台开发教程(二):成为开发者

    Senparc.Weixin.MP SDK 微信公众平台开发教程(二):成为开发者 这一篇主要讲作为一名使用公众平台接口的开发者,你需要知道的一些东西.其中也涉及到一些微信官方的规定或比较掩蔽的注意点 ...

  4. Senparc.Weixin.MP SDK 微信公众平台开发教程(二十):使用菜单消息功能

    在<Senparc.Weixin.MP SDK 微信公众平台开发教程(十一):高级接口说明>教程中,我们介绍了如何使用“客服接口”,即在服务器后台,在任意时间向微信发送文本.图文.图片等不 ...

  5. Senparc.Weixin.MP SDK 微信公众平台开发教程(二十一):在小程序中使用 WebSocket (.NET Core)

    本文将介绍如何在 .NET Core 环境下,借助 SignalR 在小程序内使用 WebSocket.关于 WebSocket 和 SignalR 的基础理论知识不在这里展开,已经有足够的参考资料, ...

  6. Senparc.Weixin.MP SDK 微信公众平台开发教程(二十二):如何安装 Nuget(dll) 后使用项目源代码调试

    最近碰到开发者问:我使用 nuget 安装了 Senparc.Weixin SDK,但是有一些已经封装好的过程想要调试,我又不想直接附加源代码项目,这样就没有办法同步更新了,我应该怎么办? 这其实是一 ...

  7. Unity接入微信支付SDK 2022年版安卓篇

    最近1年转了UE开发,博客更新的比较少,技术栈宽了不少,以后有空尽量多更新,也方便总结记忆 Unity接入微信支付整个过程坑比较多,网上之前的教程要么比较老,要么比较零碎,只能东拼西凑摸索,跑通后还是 ...

  8. Senparc.Weixin.MP SDK 微信公众平台开发教程(二十二):在 .NET Core 2.0/3.0 中使用 MessageHandler 中间件

    概述 在 <Senparc.Weixin.MP SDK 微信公众平台开发教程(六):了解MessageHandler> 中我们已经了解了 MessageHandler 的运行原理和使用方法 ...

  9. Senparc.Weixin.MP SDK 微信公众平台开发教程(八):通用接口说明

    一.基础说明 这里说的“通用接口(CommonAPIs)”是使用微信公众账号一系列高级功能的必备验证功能(应用于开发模式). 我们通过微信后台唯一的凭证,向通用接口发出请求,得到访问令牌(Access ...

随机推荐

  1. JavaScript 中 Blob对象的初步认识

    Blob Binary Large Object的缩写,二进制大对象 虽然在前端中开发并不常见,但是实际上MySql数据库中,可以通过设置一个Blob类型的数据来存储一个Blob对象的内容 语法 le ...

  2. Android Studio Gradle build 报错:Received status code 400 from server: Bad Request

    错误提示如下 Could not GET 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.1.2/ ...

  3. vue cli 中关于vue.config.js中chainWebpack的配置

    Vue CLI  的官方文档上写:调整webpack配置最简单的方式就是在vue.config.js中的configureWebpack选项提供一个对象. Vue CLI 内部的 webpack 配置 ...

  4. 遗传算法框架-基于java jenetics库实现

    本篇并非介绍如何从0开始开发遗传算法框架,反而推荐各位使用已有的GA库jenetics来做遗传算法. GA算法的逻辑还是贴下: 好了,下面介绍的是基于jenetics开发的更贴近业务侧的框架,以及使用 ...

  5. 浏览器自动化的一些体会6 增强的webBrowser控件

    这里谈两点 1.支持代理服务器切换 一种方法是修改注册表,不是太好的做法,而且,只能改全局设置,不能改局部(比如只让当前的webBrowser控件使用代理,而其他应用不用代理) 另外一个较好的方法,示 ...

  6. js使用html2canvas 生成图片然后下载

    1:html2canvas官网 首先去官网把这个JS下载下来 <!DOCTYPE html> <html lang="en"> <head> & ...

  7. linux root用户下没有.ssh目录

    .ssh 是记录密码信息的文件夹,如果没有登录过root的话,就没有 .ssh 文件夹,因此登录 localhost ,并输入密码就会生成了 ssh localhost

  8. FIRST集合、FOLLOW集合及LL(1)文法求法

    FIRST集合 定义 可从α推导得到的串的首符号的集合,其中α是任意的文法符号串. 规则 计算文法符号 X 的 FIRST(X),不断运用以下规则直到没有新终结符号或 ε可以被加入为止 : (1)如果 ...

  9. openstack vnc 报1006的错误

    1.问题现象 创建完虚拟机以后,通过nova get-vnc-console命令,获取虚机的vnc连接地址,在浏览器中打开该连接,报1006错误 2.vnc的原理图 3.定位分析 1)分别在控制节点和 ...

  10. 【转】Linux环境搭建FTP服务器与Python实现FTP客户端的交互介绍

    Linux环境搭建FTP服务器与Python实现FTP客户端的交互介绍 FTP 是File Transfer Protocol(文件传输协议)的英文简称,它基于传输层协议TCP建立,用于Interne ...