Unity_接安卓SDK流程详解

使用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<AndroidJavaObject>("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<AndroidJavaObject>("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<AndroidJavaObject>("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<AndroidJavaObject>("GetInstance");
        resultLabel.text = "AddOne" + jo.Call<int>("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

猜你喜欢

转载自blog.csdn.net/qq_39710961/article/details/80512412