原理概述:Unity在生成apk的时候,会把相对路径为Plugins/Android下的aar文件打入到apk里面,通过Unity自己的api,AndroidJavaClass就可以调用aar里面的代码,实现一些Android原生层的一些功能
本文内容:主要写了用aar沟通Unity的基础流程,不涉及具体的sdk等的接入,本人不是Android原生开发,所以Android的部分很多还不是很理解,所以只能提供一些基本方法,其他的只能靠大家自己去研究了
生成aar
要生成aar,大体步骤如下
- AndroiStudio 编辑器里面,新建一个空工程(只是用来当出aar包的载体,后面可以看到里面很多东西是不需要的)
- 添加新模块 Android Library
- 导入Unity提供的classes.jar包(主要是为了编译通过,如果你没用用到Unity的代码,只是Unity调用java,其实可以不用)
- 写自己需要的功能代码,同时根据功能,调整AndroiManifest.xml以及build.gradle(主要配置一些引用等内容,不一定需要调整)
- 执行Gradle的assemble task(可以选择出Debug或者Release版本,但没做调整实际都一样,所以简单接入的时候不需要关心)
下面将详细介绍每一步的操作
1. 新建空工程
第一次打开AndroidStudio的话就会让你创建工程,它会提供我们一些工程的模板,如果想看到最干净的Android工程,就选择No Activity,想要做一些最简单的展示啥的,就用BasicActivity,两者差距并不是很大,这里我创建No Activity
这个界面是设置的是工程的名字等信息,Name和Package name没什么关联,随便取都行,后面也一般不会涉及到这些参数。
AndroidStudio的左边这个位置,会有选项让你看到当前项目的结构,选择Project,就是真实的这个项目在硬盘上的目录结构,而选择Android则是精简过的,Android开发时只需要注意的文件,这个影响不大 一个空的Android工程其实文件数量就不少,但是实际我看来就两部分,app就是我们自己的代码、图标等内容,是开发阶段我们需要注意的,其他的Gradle都是在生成apk时,发布阶段需要注意的,app文件夹里面也是一样,凡事Gradle相关的,在开发阶段我们都不用太关心(除非你要添加些依赖啥的)
2. 添加新模块
左上角选择File>ProjectStucture,打开如下面板
文章最开始也提到过,我们创建这个Android App工程只是为了生成aar的一个载体,这个位置我们可以先加一个module(点击+号)
module name 和 PackageName 也一样,可以随意,只是这里的Package name后面Unity调用的时候就会用到了,因为Unity就是通过这个包名+类名才能定位到java函数的位置
选中app模块并移除,因为我们实际上不需要这个东西,不删除也无所谓,只是放在这儿比较碍眼,不方便我们工作
移除完后,实际上app还是会在磁盘上,只是现在可以右键删除了,这里我们删除一下即可,同时可以看到刚刚创建的Library已经有了,里面的结构也和app大差不差的,没什么特别要关心的
里面的这两个文件夹可以删除掉,都是测试用的,我们用不上,改了这儿还可以去这个路径下的build.gradle里面把几个test工具的引用也移除掉(这几个工具具体的作用我并不清楚,只能说删除后不影响我们后续的流程),每次修改Gradle后,Android Studio都会提示你Sync同步一下,这里你可能会遇到Java连不上网的情况,这个时候可能是你之前配置过vpn,百度一下,删除掉就行
3. 导入Unity提供的classes.jar包
这个jar包的路径在unity安装目录下面,相对路径是这个,我是2019.4.19f1版本的,2019.4.19f1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\Classes 这个版本的jar包里面是没有UnityPlayerActivity这个java类的,这个类在2019.4.19f1\Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player下面,需要自己导入,我们这里用不上,也就不导入了
直接拖到libs下面就行,这个时候还只是在磁盘上放了这个文件,工程还没有引用这个jar包,所以需要右键classes.jar,在列表的最下面选择Add As Libraray即可,正常情况下你就能看到这个jar包里面的代码等内容了
4. 写代码
这步骤就因人而异了,也就是说前面的流程已经把基本环境弄好了,剩下的就是自己定制了,这里我只提供一个最简单的测试用的代码
package com.jodebug.myapplication;
import android.app.Fragment;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.unity3d.player.UnityPlayer;
public class TutorialTest extends Fragment {
private static final String TAG = "TestLibrary";
private String gameObjectName;
private static TutorialTest Instance = null;
public static TutorialTest GetInstance(String gameObject) {
if (Instance == null) {
Instance = new TutorialTest();
Instance.gameObjectName = gameObject;
UnityPlayer.currentActivity.getFragmentManager().beginTransaction().add(Instance, TAG).commit();
}
return Instance;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
private int callCount = 0;
public void UnityCall() {
callCount += 1;
UnityPlayer.UnitySendMessage(gameObjectName, "JavaPluginCallback", String.valueOf(callCount));
}
}
我这里不需要改AndroidManifest,所以到此,代码写完,就可以开始出包aar了,这里我贴出我的AndroidManifest的内容(其实就是默认的)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jodebug.myapplication">
</manifest>
5. 执行assemble task
位置在右边,这个Gradle的位置,里面的myapplication下的带齿轮标签的Task就是我们要执行的目标,简单提一下这个是什么,这个是Gradle出包脚本的一些通用指令,assemble这个指令,可以理解成就是出包指令,而assemble_release等,带了后缀的,都是指出包不同的版本,release就是release版本,不带后缀就是所有版本都生成。执行后,会在一个build文件夹下面(不设置的话就是默认),生成aar。
这个位置你可能有时候看不到Tasks,这个时候一般是因为你还有其他的Gradle task已经在执行了,这种情况,本界面的上方会提示你说为什么task列表没显示,这个时候进去,把“其他task执行期间不许执行”这个选项取消掉就行
执行task后,这个路径下面就会生成我们要打aar了,剩下的就是Unity里面的流程了
Unity使用aar
随便建一个Unity工程,把aar文件放到Plugins/Android目录下即可 但是这个时候实际上打包会报错,因为我们之前在aar里面引用了classes.jar包,但是Unity自己打包apk的时候也会引用他,这样就重复引用了,所以需要删除掉aar里面的classes.jar包,直接用压缩包的形式打开aar文件(本质就是一个压缩包) 注意删的不是这里的classes.jar,是libs里面的,这里的是我们自己写的代码生成的jar。 之后我们要做的就是些C#代码去掉java代码了
using System;
using UnityEngine;
using UnityEngine.UI;
public class JavaConnector : MonoBehaviour
{
private readonly string className = "com.jodebug.myapplication.TutorialTest";
public Text javaCallUi;
public Text javaCallbackUi;
private int _callCount = 0;
public void CallJava()
{
try
{
var pluginObj =
new AndroidJavaClass(className).CallStatic<AndroidJavaObject>("GetInstance", gameObject.name);
pluginObj.Call("UnityCall");
_callCount++;
javaCallUi.text = "call:" + _callCount.ToString();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
public void JavaPluginCallback(string text)
{
javaCallbackUi.text = "back:" + text;
}
}
这里隐藏了我绑定按钮点击事件的过程,这个有点儿Unity基础的应该都不难,简单解释下代码就是每次点击的时候我Unity自己显示一个调用次数+1,因为在java层被调用的时候,我让java层也反过来调用了Unity层,如果互通了的话,javacallback也会更新显示,这个脚本需要绑定到场景中的任意一个物体上(不关心名字,是因为名字已经动态传给java层了)至此,代码写完,Unity出包测试
最终效果
初始我放随便写的两个数字11,后面每次点击都会显示当前点击了几次,回调触发了几次
|