Unity Android平台下插件/SDK开发通用流程
2017-03-24 13:06
1211 查看
本文主要面向对Android开发不甚了解的Unity开发者,介绍了基于最新的Android Studio的标准Android开发环境与项目结构的配置流程,在此基础上,开发者可以快速的进行SDK的接入与插件的开发。
目前国内各大博客上搜到的文章内容基本上都是相互抄来抄去,比如说先是清一色的继承UnityPlayerActivity,然后再配置AndroidManifest文件等等,这些确实有效果,但是具有很大的局限性。例如,如果项目中如果存在两个Android插件或SDK会怎么样?都继承UnityPlayerActivity显然是不行的,启动入口Activity只能有一个,AndroidManifest文件没法这样配置。笔者最近在做毕设,帮同学接了若干个Android下的SDK,包括支付宝,科大讯飞以及二维码扫描的SDK,参考一些国外的优秀博客以及自己的实践,总结出一套SDK接入与插件开发的通用流程,在这里分享给大家。
2.所需类库:UnityPlayer等需要的classes.jar包。在 Unity支持Android下IL2CPP后,UnityPlayer相关的这个jar包位置由原来的`Editor\Data\PlaybackEngines\AndroidPlayer\bin`变成了`Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono(or
il2cpp)\Release\Classes`,选择jar包时需要注意选择对应Backend的版本。
name生成的Package name总是小写的,点击右侧的Edit按钮可以对其进行修改。
2.创建项目点击Finish后进入编辑器界面,空无一物,点击左侧的Project,然后切换至Project视图,如图下图左所示。随后在项目名称上点击右键选择New -> Module来创建一个新的模块,这时新的创建向导会启动,选择Android Library类型,随后输入包名的配置与Mininum SDK,注意这里的Package
Name需要和Unity项目中的Bundle Identifier保持一致(包括大小写),保持一致的原因是Unity在最后打包时会将所有插件里的AndroidManifest.XML进行合并,如果包名不一致就会出错;而Mininum SDK这里需要在Android 3.0(API 11)以上,因为随后会用到Android 3.0之后才支持的Fragment特性,最后点击Finish完成创建,项目结构应该如下图右所示,红框部分是新创建的Library。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/09331cda424abc396a4632205f1284c4)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/12ea6b98e855ecb9403334171320abe0)
3.在新的Library创建完成后,需要删除app相关的内容。点击菜单栏File -> Project Structure,选中左侧的app然后点击上方的`-`号,最后点击OK,稍等一会儿,Gradle Build会完成构建(可以注意到每次进行一次大的操作如增删,Android Studio都会编译一下项目,所以构建的时候请坐和放宽)。回到Project视图,右键点击app,选择删除。展开Library目录如下图中所示,以后所有的开发操作都会在创建的这个Library下面进行。下面对项目的结构进行一些说明。build/outputs/aar/文件下面是构建生产的供Unity使用的aar文件(aar文件和jar文件类似,Unity可以识别);libs文件夹下面是项目以来的类库,可以说各种SDK的jar等等;最后是src文件夹,这里面存放了AndroidManifest以及源码。这些内容有一些是不需要的,例如一些单元测试的内容,我们删掉测试工程以及res下面的Android自带的资源及配置,最后的项目结构如下图右所示,只保留了AndroidManifest.xml。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/d7ddd02695f5ff764d72dedaac96ed27)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/1cbf8e6de34d5e6efe802b06ad484812)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/fa21fe32f59b41b0730db660e8390bf9)
4.接下来是配置AndroidManifest的内容。双击打开AndroidManifest.xml,里面有一些红色的内容,那些是因为刚才各种删除导致的,这里不再需要常规的插入UnityPlayer等一堆东西,删掉其余不相关的内容后如下所示,可以看到内容非常精简,只保留了最基础的东西:
5.最后就是编写我们的插件或者对接第三方SDK了。首先引入Unity的jar包,将classes.jar拷贝到文件夹里libs文件夹下面,通用点击File -> Project Structure,在左侧选择我们的插件,然后在上方选择Dependencies,先删除的现存的所有依赖库,然后点击`+`号 ->Jar Dependency添加Unity的jar包,点击OK完成设置,稍等一会儿就完成了构建。对于第三方SDK的jar包,以同样的方式进行引入。如果第三方依赖库中有so文件,先不需要导入,稍后将会说明如何添加so文件。到这一步,项目、依赖库都设置完毕。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/54356e9c36738b0d90044c66a30b9c14)
![](https://img-blog.csdn.net/20170325161145757?watermark/<br/>b34e<br/>2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWmhhbmdEaTIwMTc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/2c46075418f0da472138cb542c561e39)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/0996460ea9bbce1e6886c5a79d171eab)
最后将aar文件后缀改回为aar拷贝至Unity工程中Plugins/Android文件夹下,不再需要AndroidManifest.xml!
在Unity中编写如下示例代码调用插件的两个方法:
2.AndroidJavaObject.Call()传参的时候必须严格按照类型传递,如果参数是float却填了一个int类型的也会造成调用失败!
3.真机在打开开发者模式后可以用adb logcat -s Unity来获取手机中Unity输出的日志,进而进行定位(adb需要在环境变量里配置好),如下图所示的日志就说明找不到插件类里对应的参数(笔者在操作的时候忘记填参数了):
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/89e0f8daf855155ae4df037aa74f63eb)
4.以这种方式开发出的插件可以多个并存,例如将一些常用功能封装成静态类获取电量,wifi状态等,然后和支付宝,暴风魔镜的SDK并存等等。
5.快速更改插件的包名,点击齿轮并取消勾选Compact Empty Middle Packages,之后项目的结构中包名会变成三层结构,修改对应的结构即可:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/7bae4cda967fed5434ea7ec23d422cfd)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/25/42e95d81f360135939aa8195423f970c)
2.关于Android Fragment的资料:Fragment。
目前国内各大博客上搜到的文章内容基本上都是相互抄来抄去,比如说先是清一色的继承UnityPlayerActivity,然后再配置AndroidManifest文件等等,这些确实有效果,但是具有很大的局限性。例如,如果项目中如果存在两个Android插件或SDK会怎么样?都继承UnityPlayerActivity显然是不行的,启动入口Activity只能有一个,AndroidManifest文件没法这样配置。笔者最近在做毕设,帮同学接了若干个Android下的SDK,包括支付宝,科大讯飞以及二维码扫描的SDK,参考一些国外的优秀博客以及自己的实践,总结出一套SDK接入与插件开发的通用流程,在这里分享给大家。
开发环境
1.开发软件:笔者使用的开发软件是Unity 5.4.3f 和Android Studio 2.3。2.所需类库:UnityPlayer等需要的classes.jar包。在 Unity支持Android下IL2CPP后,UnityPlayer相关的这个jar包位置由原来的`Editor\Data\PlaybackEngines\AndroidPlayer\bin`变成了`Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono(or
il2cpp)\Release\Classes`,选择jar包时需要注意选择对应Backend的版本。
项目构建
1.启动Android Studio新建一个Project,会弹出创建工程向导,这里可以随意填写Package Name和Mininum SDK,最后让选择的Activity类型也可以随意。因为我们并不会用到现在创建的这个项目,我们只是在其结构上再创建一个Library作为我们的Plugin。这里值得注意的是,根据你填写的Company domain和Applicationname生成的Package name总是小写的,点击右侧的Edit按钮可以对其进行修改。
2.创建项目点击Finish后进入编辑器界面,空无一物,点击左侧的Project,然后切换至Project视图,如图下图左所示。随后在项目名称上点击右键选择New -> Module来创建一个新的模块,这时新的创建向导会启动,选择Android Library类型,随后输入包名的配置与Mininum SDK,注意这里的Package
Name需要和Unity项目中的Bundle Identifier保持一致(包括大小写),保持一致的原因是Unity在最后打包时会将所有插件里的AndroidManifest.XML进行合并,如果包名不一致就会出错;而Mininum SDK这里需要在Android 3.0(API 11)以上,因为随后会用到Android 3.0之后才支持的Fragment特性,最后点击Finish完成创建,项目结构应该如下图右所示,红框部分是新创建的Library。
3.在新的Library创建完成后,需要删除app相关的内容。点击菜单栏File -> Project Structure,选中左侧的app然后点击上方的`-`号,最后点击OK,稍等一会儿,Gradle Build会完成构建(可以注意到每次进行一次大的操作如增删,Android Studio都会编译一下项目,所以构建的时候请坐和放宽)。回到Project视图,右键点击app,选择删除。展开Library目录如下图中所示,以后所有的开发操作都会在创建的这个Library下面进行。下面对项目的结构进行一些说明。build/outputs/aar/文件下面是构建生产的供Unity使用的aar文件(aar文件和jar文件类似,Unity可以识别);libs文件夹下面是项目以来的类库,可以说各种SDK的jar等等;最后是src文件夹,这里面存放了AndroidManifest以及源码。这些内容有一些是不需要的,例如一些单元测试的内容,我们删掉测试工程以及res下面的Android自带的资源及配置,最后的项目结构如下图右所示,只保留了AndroidManifest.xml。
4.接下来是配置AndroidManifest的内容。双击打开AndroidManifest.xml,里面有一些红色的内容,那些是因为刚才各种删除导致的,这里不再需要常规的插入UnityPlayer等一堆东西,删掉其余不相关的内容后如下所示,可以看到内容非常精简,只保留了最基础的东西:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.soulgame.myplugin"> <application android:allowBackup="true" android:supportsRtl="true"></application> </manifest>
5.最后就是编写我们的插件或者对接第三方SDK了。首先引入Unity的jar包,将classes.jar拷贝到文件夹里libs文件夹下面,通用点击File -> Project Structure,在左侧选择我们的插件,然后在上方选择Dependencies,先删除的现存的所有依赖库,然后点击`+`号 ->Jar Dependency添加Unity的jar包,点击OK完成设置,稍等一会儿就完成了构建。对于第三方SDK的jar包,以同样的方式进行引入。如果第三方依赖库中有so文件,先不需要导入,稍后将会说明如何添加so文件。到这一步,项目、依赖库都设置完毕。
编写代码
不要再继承UnityPlayerActivity了!具体原因会在后面的参考资料里给出。首先贴一段Android Studio里的示例代码,创建一个MyPluginClass类,这里简单的用到了一个static的Instance作为这个类访问的入口(类似单例),在Unity中只需要拿到Instance进行操作即可,里面涉及到一些Android原生的Fragment的操作,具体含义可以Google一下:package com.soulgame.myplugin; import android.app.Fragment; import android.os.Bundle; import com.unity3d.player.UnityPlayer; public class MyPluginClass extends Fragment { private static final String TAG = "MyPlugin"; private static MyPluginClass Instance = null; private String gameObjectName; public static MyPluginClass GetInstance(String gameObject) { if(Instance == null) { Instance = new MyPluginClass(); Instance.gameObjectName = gameObject; UnityPlayer.currentActivity.getFragmentManager().beginTransaction().add(Instance, TAG).commit(); } return Instance; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); // 这一句很重要,保存对该Fragment的引用,防止在旋转屏幕等操作时时丢失引用(Fragment隶属于Activity) } //示例方法一:简单的向Unity回调 public void SayHello() { UnityPlayer.UnitySendMessage(gameObjectName,"PluginCallBack","Hello Unity!"); } //示例方法二:计算传入的参数并返回计算结果 public int CalculateAdd(int one, int another) { return one + another; } }编写完成,将插件编译导出,选中Android Studio右侧的Gradle,选中如图所示的选项编译输出,稍等一会儿,在左侧的Project面板可以看到相关的aar文件了,这个aar文件就是最终输出给Unity使用的aar包,拿到aar包之后,需要进行一项关键的操作,将其后缀改为压缩格式(zip或rar)打开压缩包删除掉libs/下面的classes.jar(原因是Unity在打包的时候会再次拷贝安装目录下的classes.jar到项目中造成冲突)!如果插件使用到了so文件,将对应平台的so文件拷贝至libs下面,如下图右所示:
最后将aar文件后缀改回为aar拷贝至Unity工程中Plugins/Android文件夹下,不再需要AndroidManifest.xml!
在Unity中编写如下示例代码调用插件的两个方法:
using UnityEngine; using UnityEngine.UI; using System.Collections; public class PluginManager : MonoBehaviour { public string className = "com.soulgame.myplugin.MyPluginClass"; public Text callbackText = null; public Text resultText = null; private AndroidJavaObject pluginObject = null; void Start() { #if UNITY_ANDROID && !UNITY_EDITOR pluginObject = new AndroidJavaClass(className).CallStatic<AndroidJavaObject>("GetInstance", gameObject.name); pluginObject.Call("SayHello"); resultText.text = pluginObject.Call<int>("CalculateAdd", 22, 33).ToString(); #endif } public void PluginCallBack(string text) { callbackText.text = text; } }编写完成后,设置好Platform和Bundle Identifier以及Mininum API Level(和插件保持一致),到真机上测试即可。
注意事项
1.UnityPlayer.UnitySendMessage()方法接受三个参数,每一个都不能为null!如果不想填就用string.Empty。2.AndroidJavaObject.Call()传参的时候必须严格按照类型传递,如果参数是float却填了一个int类型的也会造成调用失败!
3.真机在打开开发者模式后可以用adb logcat -s Unity来获取手机中Unity输出的日志,进而进行定位(adb需要在环境变量里配置好),如下图所示的日志就说明找不到插件类里对应的参数(笔者在操作的时候忘记填参数了):
4.以这种方式开发出的插件可以多个并存,例如将一些常用功能封装成静态类获取电量,wifi状态等,然后和支付宝,暴风魔镜的SDK并存等等。
5.快速更改插件的包名,点击齿轮并取消勾选Compact Empty Middle Packages,之后项目的结构中包名会变成三层结构,修改对应的结构即可:
参考资料
1.关于插件中继承Fragment而不是UnityPlayerActivity的原因:Unity Android plugin tutorial 。2.关于Android Fragment的资料:Fragment。
相关文章推荐
- Unity Android平台下插件/SDK开发通用流程
- Unity—Android通用SDK(交互)开发流程
- Unity原生平台插件开发简介(Android/iOS)
- unity android项目如何快速接入平台支付的SDK
- android 浏览器插件开发 - 流程(1)
- android 浏览器插件开发 - 流程(1)
- 深入浅出 - Android系统移植与平台开发(四)- Android启动流程
- 关于android Widgets桌面小插件的开发大概流程
- ArcGIS Runtime SDK for Android 10.2.5新开发平台安装配置指南
- Android开发环境搭建:离线安装ADT插件和安装SDK
- iOS-android-windowsphone等移动终端平台开发流程图
- android 浏览器插件开发 - 流程(1)
- 基于插件开发的Android实现流程
- 【React Native开发】React Native 控件之Modal详解-Android/iOS双平台通用(56)
- 【Unity】ios平台IAP内购和沙箱测试流程详解(开发中遇到的坑)
- 关于Unity -Vuforia -Android 开发 ,平台的搭建(极品菜鸟完整版)
- ionic开发之Android平台echo插件编写
- Unity项目工程集成友盟分析统计SDK(支持iOS与Android平台)
- 搭建Android开发环境:直接使用官网提供的 ADT Bundle(带Eclipse、ADT插件、SDK)
- 深入浅出 - Android系统移植与平台开发(四)- Android启动流程