【Unity与Android】01-Unity与Android交互通信的简易实现
前言
使用Unity也有不短的时间了,安卓包也打过不少,但是对Unity与Android的交互却知之甚少。
因工作需求,需要在Android平台接一些sdk(扩展功能)。我就借此机会了解了下Unity与Android交互的一些知识,并做了一个简易实现。
现将实现步骤记录下来以供日后查阅。
一、开发准备
Unity、Android Stuido以及JDK安装,这些都是基本操作了,网上也有很多教程,这里不细述。
本次开发所使用的软件版本如下:
Android Studio 3.5
Unity 2018.3.10f1
Java 1.8.0191
二、要实现的功能
要在unity项目中进行安卓功能扩展,有两种方式:
1、Unity项目导出为Android工程,然后在Android Studio(以后简称为AS)中进行二次开发,添加扩展功能。这样的方式开发起来很灵活,改动起来也很方便,但是就是很麻烦,因为每次改动都要打一回安卓工程。
2、将扩展功能制作成Android库文件(jar包),然后将jar包导入到Unity中,直接使用。这样的方式,使用者无法修改这个库文件的功能,但也更便于使用 。
因为我将要做的功能可能会在团队内传播使用,也不需要每个人都去做改动。因此选择第二种方式。
所以本文的目的就是:
制作一个Android库文件(jar包),然后在Unity中使用它。
三、如何制作Android库文件
1、新建Android工程
打开AS,新建一个Android工程,选择Empty Activity,配置工程名称、包名、位置以及语言,如下图
语言最好选Java,因为Java和C#的语法极为相似,学习成本很低。
工程创建之后,默认显示的是Android视图下app的工程结构,如下图。能看到在包名下有一个MainActivity.java的文件,这是安卓app的入口,不过这里并不打算使用它,忽略即可。
2、创建一个Android Library 模块
选中app,然后右键,选Module,在Create New Module窗口中选择 Android Library
填入Library name、Module name 、Package name以及Language后,点完成。
这里的Package name好像是可以改的,不必和之前创建工程时完全一样(未验证)。不过为了少点事,还是先保持一致吧。
现在可以看到,在工程中同时存在着app和mysdk模块,它俩是平级存在的,并且都有自己的源码目录(com.letui.mysdk),以及清单目录(manifests)。
app部分可以不用管了,后续只对mysdk模块进行操作。
3、引入Unity对接Android的库文件
1)在unity的安装目录下件,找到一个名为classes.jar的文件
我的目录为 D:\Unity2018\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Development\Classes
2)然后将classes.jar粘贴到mysdk模块的libs目录下(需要将工程切换到project视图)
额外说明:
在il2cpp目录下也有一个名称一样的classes.jar文件,其目录为
D:\Unity2018\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Development\Classes
这两个文件的选择,与unity的Player Setting中脚本后端设置有关。如下图
脚本后端用哪个就,就选哪个目录下的classes.jar
3)选中刚粘贴的classes.jar文件,右键,选择 Add as Library,出现一个弹窗口,默认选中mysdk模块,直接点确定
然后,这个classes.jar文件就被引入到工程中了,展开三角,可以看到如下三个模块,其中就有com.unity3d.player。如下
4、创建本模块的Activity文件
1)展开mysdk模块下的src目录,选中com.leitui.mysdk,然后右键,新建一个Activity,选择Empty Activity,输入Activity Name以及Package Name和Language,勾掉Generate Layout File, 完成。
新建的SDKMainAcivity.java脚本,默认继承自AppCompatActivity,并带有一个onCreate方法,如下:
现将SDKMainActivity脚本内容修改为继续自UnityPlayerActivity ,并添加两个方法 UnityCallAndroid 和 AndroidCallUnity,
UnityCallAndroid 用来接受Unity的调用,AndroidCallUnity用于向unity发起调用。具体代码如下:
package com.letui.mysdk; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle;
import android.widget.Toast; import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity; public class SDKMainActivity extends UnityPlayerActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
} //unity调用Android
public void UnityCallAndroid () { Toast.makeText(this,"unity调用android成功", Toast.LENGTH_LONG).show(); AndroidCallUnity();
} //android调用unity
public void AndroidCallUnity () { //第1个参数为Unity场景中用于接收android消息的对象名称
//第2个参数为对象上的脚本的一个成员方法名称(脚本名称不限制)
//第3个参数为unity方法的参数
UnityPlayer.UnitySendMessage("receiveObj", "UnityMethod", "This is args.");
}
}5、将模块打包
打包方法有两种。
一是手动进行构建,然后在Build/intermediates/packaged-classes/release目录下找到相应的jar包(这个jar包默认名称为classes.jar,为了区分,需要自己改名称);
二是用gradle命令。
打开本模块的build.gradle文件,在文件尾添加如下的一组命令。
//----------------这是一组将module导出为jar的gradle命令-------------------
// mysdk为自定义的jar包名称
//task to delete the old jar
task deleteOldJar(type: Delete) {
delete 'release/mysdk.jar'
} //task to export contents as jar
task exportJar(type: Copy) {
from('build/intermediates/packaged-classes/release/')
into('release/')
include('classes.jar')
///Rename the jar
rename('classes.jar', 'mysdk.jar')
} exportJar.dependsOn(deleteOldJar, build)
//---------------------------命令结束------------------------------
这组命令的功能就是打包方法1的自动化版。
build.gradle文件修改后,会提示要求同步,直接同步即可。同步结束,在IDE右上点开Gradle窗口,在other下找到exportJar命令。
双击exportJar命令,等一会就会自动生成本模块的jar文件了。
生成的文件位于mysdk/release/目录下,如下图
6、修改AndroidManifest.xml文件
1)打开本模块的AndroidManifest.xml文件,文件位于mysdk/src/main目录下,如下图:
这个文件的内容,目前只有一对application标签和activity标签
删掉这三行,将其内容修改为如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.letui.mysdk"> <!-- 这个android:label设置后,unity中ProductName就不生效了,记得改这个-->
<application android:label="MySDK"> <!-- 这个android:name的值必须为包名+类名-->
<activity android:name="com.letui.mysdk.SDKMainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter> <!-- 这一行不能少,否则会闪退-->
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application> </manifest>这其中有三个要注意的点,注释中都有说明。修改完成后保存。
至此,在AS中的操作就结束了。
四、在unity中使用jar文件
1、新建一个Unity工程。
a.新建一个Unity工程,在Assets目录下新建Plugins/Android/bin目录。
b.将第三步修改的AndroidManifest.xml文件拷贝到Assets/Plugins/Android目录下
c.将第三步生成的mysdk.jar文件拷贝到Assets/Plugins/Android/bin目录下
完成之后文件结构图如下:
libs目录用于存放其它android插件的jar文件,没有也可以不用创建。
2、制作一个UI界面
a.在SampleScene场景中创建一个Canvas,并创建一个名为"receiveObj"的对象,在receiveObj之下再放一个按钮和一个Text。
按钮用于触发调用Android方法。
Text用于显示Android调用Unity方法传递来的参数。如下图:
这里要注意,receiveObj的名称必须与SDKMainActivity类的AndroidCallUnity方法中的UnityPlayer.UnitySendMessage方法的第一个参数保持一致。
b.创建一个SDKTest.cs文件,将脚本挂在receiveObj对象上。如下:
SDKTest脚本的内容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; public class SDKTest : MonoBehaviour
{
private AndroidJavaClass jc;
private AndroidJavaObject jo; private Button btn;
private Text text; private void Awake()
{
btn = transform.Find("Button").GetComponent<Button>();
text = transform.Find("Text").GetComponent<Text>(); //这两行是固定写法
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); btn.onClick.AddListener(OnBtnClickHandler);
} private void OnBtnClickHandler ()
{
//调用Android中的方法UnityCallAndroid
jo.Call("UnityCallAndroid");
} /// <summary>
/// 被Android中AndroidCallUnity调用
/// </summary>
/// <param name="str"></param>
public void UnityMethod(string str)
{
Debug.Log("UnityMethod被调用,参数:" + str);
text.text = str;
}
}其中必须要有UnityMethod方法,因为它在AndroidCallUnity方法中的UnityPlayer.UnitySendMessage的第二个参数已经指定了。如果不存在的话,调用就会出错。
jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); 这两句,一个是获取到UnityPlayer类,一个是获取到类的实例。
到于为什么这样能取到我创建的模块的SDKMainActivity的实例,还有待探究。反正目前这么写了就行了。3、打包并测试。
在unity中设置Bundle Identifier和Company等信息之后,打一个apk包。
安装后运行,能正常显示UI。
点击按钮后,显示了一个Toast,提示“Unity调用Android成功”,说明jar包中的UnityCallAndroid方法被调用。
Unity->Android通信成功。
同时屏幕上方的NewText被变更为“This is args”,"This is args"是 AndroidCallUnity方法中传递给UnityMethod方法的参数。
这表示Android->Unity通信成功。
演示见下图:
调用 前:
,调用后:
五、一点说明
1、模块的包名和Unity的Bundle Identifier可以不一致(至少在Module模式下,是可以不一致的)。
说明:写这条是因为其它相关文章全都要求两边保持一致,而如果模块的包名要跟着Unity工程走,也太蛋疼了,所以验证了下。
2、将AndroidManifest.xml引入到Unity之后,在unity中设置的Product Name就无效了。
需要在AndroidManifest.xml的application标签中,添加android:label属性来指定。
初次接触Android开发,以上内容如有错误,还请不吝指出。
本文件所使用的Android工程和Unity工程源码在此:安卓工程 Unity工程
【Unity与Android】01-Unity与Android交互通信的简易实现的更多相关文章
- Android与Unity交互研究
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/46733221 Android与Unity交互研究 unity与android交互的由来 ...
- Android/Unity大乱斗-完整双方集成交互指南
这是一个很长很长的story!-芝麻粒儿创作 开篇 源码地址:GitHub 本文目的,将Unity集成到Android端,学完本文后你可以做到 Android任意布局加载Unity 3D场景 任意操作 ...
- 最新Unity 与Android 交互通信(基于Unity 2019.4 和 Android Studio 4.1.1)
原文章链接:https://blog.csdn.net/woshihaizeiwang/article/details/115395519 CLSays:网上找了一圈,真的是很多都不能用,要么太老,要 ...
- unity编译android包时提示android sdk路径有问题
如果你有洁癖喜欢把各种软件各种IDE都更新到最新,那么就恭喜你也会遇到我的问题: 重装了公司的imac,下载了最新的android sdk,uinty各种编译失败,真是耽误时间,其实不是android ...
- 教你高速高效接入SDK——Unity统一接入渠道SDK(Android篇)
U8SDK的设计之初,就是为了可以支持各种游戏引擎开发的游戏,而不不过Android的原生平台.眼下一大半的手游,都是採用Unity3D和Cocos2dx开发,那么这里,我们就先来一步步给大家演示,用 ...
- Android向unity发送消息
有些时候需要Android向unity发送消息,有两种方法实现,一.通过unity再带的消息机制,二.通过注册回调的方式. 一.通过UnityPlayer.UnitySendMessage():方法 ...
- Unity 5.3 安装完没有Android(安卓)或IOS Module(模块)?
Unity5.3 模块独立 Unity5.3把各个模块分开来了,主程序安装包更轻巧,在官网下载的话,能下载到 Unity安装程序,Unity编辑器等一些资源package,其它的模块可以通过Unity ...
- Android原生代码与html5交互
一.首先是网页端,这个就是一些简单的标签语言和JS函数: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN&q ...
- Android客户端和服务器端数据交互
网上有很多例子来演示Android客户端和服务器端数据如何实现交互不过这些例子大多比较繁杂,对于初学者来说这是不利的,现在介绍几种代码简单.逻辑清晰的交互例子,本篇博客介绍第四种: 一.服务器端: 代 ...
随机推荐
- python报错 TypeError: a() got multiple values for argument 'name'
[问题现象] 在一次调用修饰函数中出现了问题,折腾了一下午,一直报错 TypeError: got multiple values for argument 只是很简单的调用 from tsu2Ru ...
- 开源题材征集 + MVC&EF Core 完整教程小结
到目前为止,我们的MVC+EF Core 完整教程的理论部分就全部结束了,共20篇,覆盖了核心的主要知识点. 下一阶段是实战部分,我们将会把这些知识点串联起来,用10篇(天)来完成一个开源项目. 现向 ...
- 为什么不建议在hbase中使用过多的列簇
我们知道,hbase表可以设置一个至多个列簇(column families),但是为什么说越少的列簇越好呢? 官网原文: HBase currently does not do well with ...
- pycharm使用教程
https://www.cnblogs.com/tsingke/p/7392800.html
- Java性能测试从入门到放弃-概述篇
Java性能测试从入门到放弃-概念篇 辅助工具 Jmeter: Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试.JMeter 可以用于对服务器.网络 ...
- 体验RxJava
RxJava是 ReactiveX在 Java上的开源的实现,简单概括,它就是一个实现异步操作的库,使用时最直观的感受就是在使用一个观察者模式的框架来完成我们的业务需求: 其实java已经有了现成的观 ...
- HTTP网页异常错误代码详解
在调试TomCat,等web服务器的时候我们有时候各种错误代码铺面而来,让人头疼不已,那么这些代码究竟都代表什么呢?知道这些代码会会对我们的调试帮助很大 让我们来看一下这些代码究竟什么意思 400 无 ...
- canvas 的基本使用
一.canvas的介绍 canvas是html5出现的新标签,像所有的DOM对象一样它有自己本身 的属性.方法和事件,其中就有绘图的方法,js能够调用它来进行绘图.canvas只有两个属性,而且是可选 ...
- 重温Android和Fragment生命周期
重温下Android和Fragment生命周期,理解生命周期方法的作用,什么时候调用,可以做一些什么操作. 1.Android生命周期 1.1 生命周期图 1.2 生命周期函数说明 onCreate: ...
- CentOS搭建php + nginx环境
更新Centos的yum源 yum update 安装EPEL源和REMI源 yum install epel-release yum install http://rpms.remirepo.net ...