使用Unity接SDK有多种方式,方法,接下来我们讲到的是我最近用到的一种方法。
首先配置Eclipse环境(这篇主要叙述流程,这里就不再详细描述环境的配置了)
一、打开Eclipse,建立安卓工程。
这里我们需要注意的是以下三点:
1.packge Name要和Unity项目名称一致!!!
2.Minimun Required SDK 建议选择4.0(网上都这么说,我也不知道为啥,自我理解是时代的分界线吧。)
3.Target SDK 你项目对应的是什么版本就选择什么版本。
然后选择勾选下图的选项,因为我们这种方法只需要Eclipse为我们打包出.jar包文件即可。
然后就是一直下一步,下一步,下一步,之后我们就进入了所创建的安卓工程。工程如下所示:
因为这里我们不需要接入第三方的SDK,这里呢我们只需要在libs文件下导入Unity自带的classes.jar即可。(Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes)
然后我们在src文件下创建类
PS:这里的类名是固定的,在上几步中你选择的默认MainActivity就决定了你的类名必须是这个。
然后就是修改类里的内容了,代码如下:
package com.SDK.ProductName;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends UnityPlayerActivity{
private static MainActivity instance;
@Override
protected void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
//这是一个安卓默认的界面
//setContenView(R.layout.activity_main);
instance = this;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id==R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public int Sum(int x,int y) {
return x+y;
}
public int Max(int x,int y) {
return Math.max(x, y);
}
public void MakeToast(String str) {
Toast.makeText(this, str, Toast.LENGTH_LONG).show();
}
public int AddOne(int x) {
return x+1;
}
public static MainActivity GetInstance() {
return instance;
}
public void CallUnityFunc(String str) {
str = str +"Android Call Unity.";
String ReceiveObject = "MessageHandler";
String receiveMethod = "Receive";
// ReceiveObject 对应Unity内的挂在脚本对象,receiveMethod对应脚本下的方法, str参数
UnityPlayer.UnitySendMessage(ReceiveObject, receiveMethod,str);
}
}
之后选择导出jar包:项目右键,选择导出,选择jar file。因为没有用到第三方的jar包或者lib库,因此只选择勾选src/和res/目录导出为jar包即可。
此时我们就可以对AndroidManifest.xml进行修改了。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.SDK.ProductName" //包名
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14" //最低版本好需要与设定匹配
android:targetSdkVersion="23" />
//四个基本属性。
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
//活动入口,必须拥有的
<activity
android:name="com.SDK.ProductName.MainActivity"
android:label ="@string/app_name">
<intent-filter>
<action android:name ="android.intent.action.MAIN"/>
<category android:name ="android.intent.category.LAUNCHER"/>
intent-filter>
activity>
application>
manifest>
接下来就是Unity端的工程的开发:
建立一个新的Unity工程,然后在Asset/目录下建立如下路径的文件夹:Plugins/Android。从文件夹的名字来看,我们可以知道这是用来存放安卓插件的。然后将我们上面导出的SDK.jar包导入到这个目录下或者是放在Andoird工程目录下的bin/文件夹下,并将Andoird工程目录下的,libs/、res/、AndroidMainFest.xml都复制到该路径下。(如果assets文件下也有资源的话也需要将其复制到Andoird工程目录下)。
需要特别注意的是要将Unity 项目中 libs下的classes.jar文件删除掉,这个就是上面提到的那个起到中介作用的jar包,一定要删掉!一定要删掉!一定要删掉!(重要的事情说三遍,网上不少教程都是针对Unity老版的教程,没有提到要删除这个classes.jar包,结果在Unity 5.x中打包肯定会出错)。
然后我们建立一个场景,简单的在里面放上一些Label和输入框、按钮、供我们验证交互操作。并且编写一个脚本(testSDK),在其中编写用来调用jar包的C#方法,然后将按钮和这些函数进行绑定。
脚本如下:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class testSDK : MonoBehaviour
{
private AndroidJavaClass _jc;
private AndroidJavaObject _jo;
public InputField inputFieldA;
public InputField inputFiledB;
public Text resultLabel;
// Use this for initialization
void Start()
{
//初始化
//"com.unity3d.player.UnityPlayer"和"currentActivity"这两个参数都是固定的
//UnityPlayerActivity里面对其进行了处理
_jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
_jo = _jc.GetStatic("currentActivity");
}
public void AddOne()
{
int a = Convert.ToInt32(inputFieldA.text);
//注意,这里使用的就不是之前默认的com.unity3d.player.UnityPlayer,而是需要传入自己的类(实现了需要调用相应方法的类)
//因为默认的UnityPlayer中是没有我们所需要的方法的,所以需要加载自己的类
AndroidJavaClass jc = new AndroidJavaClass("com.SDK.ProductName.MainActivity");
//调用Java中的静态方法,单例模式,返回当前Activity实例
AndroidJavaObject jo = jc.CallStatic("GetInstance");
resultLabel.text = "AddOne" + jo.Call<int>("AddOne",a);
}
public void Sum()
{
int a = Convert.ToInt32(inputFieldA.text);
int b = Convert.ToInt32(inputFiledB.text);
//调用Java类中的普通方法,返回值为int型
resultLabel.text = "Sum: " + _jo.Call<int>("Sum", a, b);
}
public void Max()
{
int a = Convert.ToInt32(inputFieldA.text);
int b = Convert.ToInt32(inputFiledB.text);
resultLabel.text = "Max: " + _jo.Call<int>("Max", a, b);
}
public void CallUnityFunc()
{
//调用Java中的一个方法,该方法会回调Unity中的指定的一个方法,这里会回调Receive( )
_jo.Call("CallUnityFunc","Unity Call Android.\n");
}
public void Receive(string str)
{
resultLabel.text = str;
}
public void Toast()
{
_jo.Call("MakeToast","Unity 调用Toast");
}
}
通过上面的代码,我们就可以看出来,想在Unity中调用Android的代码,主要涉及到了两个类。AndroidJavaClass 和 AndroidJavaObject 。这两个类在Unity API手册里面有详细的解释。
下面的代码是获取到对应包名的java.lang.Class实例,这里获取到的是com.unity3d.player.UnityPlayer类。
_jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
下面的代码是获取到UnityPlayer类中的静态字段,它的返回值类型是AndroidJavaObject对象。
_jo = _jc.GetStatic("currentActivity");
通过以上两行代码,我们可以获取到这个AndroidJavaObject 对象,然后用 AndroidJavaObject 对象就可以任意地调用Android中的静态和非静态函数了。其中两个函数中的字符串参数 “com.unity3d.player.UnityPlayer” 和 “currentActivity” 都是固定的写法,我们不用去改变。
AndroidJavaObject 类的一些常用方法及功能如下表所示:
函数 | 函数意义 |
---|---|
AndroidJavaObject | 构造函数,根据类名返回AndroidJavaObject对象 |
Call | 调用Android代码中的非静态方法 |
CallStatic | 调用Android代码中的静态方法 |
Dispose | IDisposable 回调 |
Get | 获取Android代码中的非静态字段 |
GetRawClass | 获取一个指向Java class的原始引用 |
GetRawObject | 获取一个指向Java object的原始引用 |
GetStatic | 获取Android代码中的静态字段 |
Set | 设置Android代码中的非静态字段 |
SetStatic | 设置Android代码中的静态字段 |
另外,我们还有第二种方法去访问Java的代码,那就是利用我们之前在Java代码中写的 GetInstance() 静态方法,它会返回一个MainActivity的实例,我们拿到这个实例以后,就能访问里面的方法和字段了。需要注意的是此时的AndroidJavaClass构造函数中传递的字符串就不是 “com.unity3d.player.UnityPlayer” 了。而是要传入自己的包名,比如代码中的 “com.mx.sdkbase.MainActivity” 。代码如下:
int a = Convert.ToInt32(inputFieldA.text);
//注意,这里使用的就不是之前默认的com.unity3d.player.UnityPlayer,而是需要传入自己的类(实现了需要调用相应方法的类)
//因为默认的UnityPlayer中是没有我们所需要的方法的,所以需要加载自己的类
AndroidJavaClass jc = new AndroidJavaClass("com.mx.sdkbase.MainActivity");
//调用Java中的静态方法,单例模式,返回当前Activity实例
AndroidJavaObject jo = jc.CallStatic("GetInstance");
resultLabel.text = "AddOne" + jo.Call("AddOne",a);
不止Unity可以调用Android的代码,Android也可以反过来回调Unity的代码。下面这段代码就是用来回调Unity函数的:
/**供Unity调用的函数,此函数会回调指定的一个Unity中的方法,完成数据的双向交互
* @param str
*/
public void CallUnityFunc(String str){
str=str+"Android Call Unity.";
String ReceiveObject="MessageHandler";
String ReceiverMethod="Receive";
UnityPlayer.UnitySendMessage(ReceiveObject, ReceiverMethod, str);
}
利用UnityPlayer.UnitySendMessage(ReceiveObject, ReceiverMethod, str); 就可以返回过来回调一个Unity中的方法,完成Unity和Android的双向通信。其中第一个参数是接受该回调的gameobject名称,第二个参数是挂载在该gameobject上面的一个脚本中接受该消息的方法,最后一个参数是本条消息发送的字符串信息。比如上面例子中的代码就会调用名称为MessageHandler的gameobject上面挂载的脚本中的Receive方法。
打包发布Android平台的APK
代码写好以后,我们会习惯性地在Unity Editor 里面运行查看一下效果,但是如果要调用 Android 代码的话,是不可以这样做的,一定要在真机上运行(模拟器上也行),在Editor中运行会报错的。所以我们还是打包发布到Android端查看效果吧。
在Unity中按快捷键 ctrl +b ,打开Build Setting界面,然后把平台切换为 Android 平台并将我们的测试场景加到Build Setting队列中。点击PlayerSetting,对工程的信息进行配置。注意要把里面的Company Name和Product Name修改成和包名一致。
然后 ,Bundle Identifier的值也要修改成和包名一样,并且调整下Minimum API Level。
之后,我们就可以打包并查看测试结果了。
如果有小伙伴需要查看模板的话,这是链接:https://download.csdn.net/download/qq_39710961/10449972