一、知识点学习

Unity 项目中一些需要访问安卓操作系统的功能,比如获取电量,wifi 状态等,需要 Unity 启动安卓系统的 BroadcastReceiver 监听状态,并在状态更新后通知到 Unity 界面。这就需要一种 Unity 与 Android 互相调用的机制,直观地看就是 C# 与 Java 互相调用的方法。

有 Unity 与 Android 互相调用需求的项目需要在两个开发环境中同时进行,创建两个工程,这时就涉及到如何将两个工程连接起来,有两种方式来连接:

  • Android 工程生成 aar/jar 文件,复制到 Unity 工程中,最终使用 Unity 的 Build 机制生成 apk。
  • Unity 工程将所有内容和代码导出为一个 Android gradle 项目,然后使用 Android Studio 打开项目进行开发,最终使用 Android Studio 打包 apk。

对比一下两者的优缺点:

Unity 使用 jar/aar 库

Unity 导出 gradle 项目

Unity 与 Android 依赖性

Unity 只依赖 Android 库文件,分割清晰,需要同步的文件只有库文件

Android 依赖 Unity 导出的场景数据,需要同步的文件太多

开发调试速度

Android 库文件比较小,调试较快

Unity 工程较大,同步较慢,调试周期长

Build机制

Unity 内置的 Android Build 机制,类似于 eclipse 编译 Android 项目

Android Studio gradle

Build灵活性

较差,无法深度定制,库有依赖时需要将全部依赖显式拷贝到 Unity 工程中

非常自由,可以使用最新的 Android Build 机制

如何打包apk

Unity Build 机制直接打包

Android Studio 打包

本项目使用的是第一种方法,因为这个项目中 Unity 工程特别大,导出 Unity 工程的代价太大。但也遇到了库文件依赖问题,不过由于依赖项不是很多,可以手动解决。以下是解决思路:

Unity 调用 Android

Unity官方文档说明需要通过Plugin的方式调用Java代码,但实际上不需要引入任何Plugin就可以调用Java代码。只是一般情况下需要调用的都是封装好的库,这时才需要将 jar 或者 aar 放到 Unity 项目中,然后通过 C# 来访问其中的内容。

jar 或者 aar 文件可以放在Unity任意目录下,为了方便管理,都放在了 Assets/Plugins/Android 目录下。

C# 调用 Java 方法,获取 Java 字段

C# 调用 Java 的底层原理是使用JNI调用,Unity已经提供了很方便的接口:

  • 创建对象:C#中使用 AndroidJavaObject 类封装 Java 对象,new 一个 AndroidJavaObject 对象相当于调用对应的 Java 对象的构造函数。借助 C# 可变参数列表,可以给 Java 对象的构造函数传递任意数量的参数。
// 第一个参数是 Java 类的完整包名,剩下的其他参数会传递给构造方法。
AndroidJavaObject jo = new AndroidJavaObject("java.lang.String", "some_string");
  • 调用对象方法:使用 AndroidJavaObject 类的 Call 方法,有泛型与非泛型的两个版本。
// 泛型版本,目的是指定返回值的类型
int hash = jo.Call<int>("hashCode");
// 非泛型版本,处理返回值是void的情况。
jo.Call("aMethodReturnVoid"); // String中没有返回void的简单方法。。。
  • 获取类,主要用于获取静态字段或调用静态方法,常用来获取 UnityPlayer。
// 传入类的完整包名
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  • 获取静态字段,只有泛型版本,因为不会有void类型的字段。。。
AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");

二、项目实操环节:

  • 第一步,Unity Part:

新建个 Unity 工程 ,如图实现UI:

绑定一下 按钮 的点击逻辑:

public void onClickCopy()
{Debug.LogWarning("unity copy");// 注意这里的 class 路径 需要跟后面 AS 工程的 JAVA 脚本要对应上!!using (AndroidJavaClass androidClass = new AndroidJavaClass("com.example.moduleb.MainActivity")){// 这里的方法是否是static的也要注意!不是static的,用Call方法!androidClass.CallStatic("copyTextToClipboard", "test text");}
}public void onClickPaste()
{Debug.Log("unity paste ");// 注意这里的 class 路径 需要跟后面 AS 工程的 JAVA 脚本要对应上!!using (AndroidJavaClass androidClass = new AndroidJavaClass("com.example.moduleb.MainActivity")){// 这里的方法是否是static的也要注意!不是static的,用Call方法!string s = androidClass.CallStatic<string>("getTextFromClipboard");Debug.LogWarning("unity paste s=" + s);}
}

unity 部分暂时完成。

  • 第二步,AS Part:

新建个 AS 工程, no activity 就可以。

进去之后,我们 新建一个 module :

然后 再 src 下 新建接口java脚本:

public static void copyTextToClipboard(final String str) {Activity activity = UnityPlayer.currentActivity;activity.runOnUiThread(new Runnable() {@Overridepublic void run() {ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(Activity.CLIPBOARD_SERVICE);ClipData clipData = ClipData.newPlainText("data", str);clipboard.setPrimaryClip(clipData);Log.i("speedmobile", "DoCopyText text: " + str);}});
}/** 从剪贴板中获取文本*/
public static String getTextFromClipboard() {Activity activity = UnityPlayer.currentActivity;ClipboardManager clipboard = (ClipboardManager)activity.getSystemService(Activity.CLIPBOARD_SERVICE);if (clipboard != null && clipboard.hasPrimaryClip()&& clipboard.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {ClipData cdText = clipboard.getPrimaryClip();ClipData.Item item = cdText.getItemAt(0);return item.getText().toString();}return "null";
}

注意到 这里 用到的 UnityPlayerActivity 是 Unity 的库类 。这个类需要以 Library 导入到 我们这里的 AndroidTools-module 。 导入的做法是:找到 Unity的安装路径 , 搜索 classes.jar 。

我这里的路径是 :C:\Program Files\Unity\Hub\Editor\2018.4.36f1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jar

然后拷贝到我们module - libs 文件夹内, 右键点击 classes.jar 选择 Add As Library

这时候,回头再看我们的java脚本,已经不报错误了。

接下来,需要导出我们当前模块 AndroidTools 为 jar 包 , 给Unity使用。

找到 AndroidTools module 的build.gradle脚本。添加下面task语句:

bundle.gradle 示例:

plugins {id 'com.android.library'
}android {compileSdk 31defaultConfig {minSdk 21targetSdk 31versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"consumerProguardFiles "consumer-rules.pro"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}
}dependencies {implementation 'androidx.appcompat:appcompat:1.3.1'implementation 'com.google.android.material:material:1.4.0'implementation files('libs\\classes.jar')testImplementation 'junit:junit:4.+'androidTestImplementation 'androidx.test.ext:junit:1.1.3'androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}task clearJar(type: Delete) {delete 'build/libs/androidTools.jar'这行表示如果你已经打过一次包了,再进行打包则把原来的包删掉
}task makeJar(type: Copy) {from('build/intermediates/aar_main_jar/release') //这行表示要打包的文件的路径,根据下面的内容,其实是该路径下的classes.jarinto('build/bin/')  //这行表示打包完毕后包的生成路径,也就是生成的包存在哪include('classes.jar')  //看到这行,如果你对分包有了解的话,你就可以看出来这行它只是将一些类打包了rename ('classes.jar', 'androidTools.jar')
}makeJar.dependsOn(clearJar, build)

如图:

然后点击 左边的小箭头,运行导出语句。 执行完之后,可以看到在build/bin 下生成了我们需要的jar包。

然后拷贝这个jar包 到 Unity 工程 Assets/Plugins/Android 下。

  • 第三步,build and run!看 logcat !

success!

附上示例项目地址:

https://github.com/zengzhiwei/Unity2Android4Copy.git

Unity调用安卓接口——实现复制粘贴功能相关推荐

  1. 分享一个unity发布webgl 的复制粘贴功能的插件,unity打包webgl的坑

    unity发布webgl 难免需要复制粘贴功能,而自带的UGUI的InputField是不具备的 所以一直在寻找可用的方案,但是unity webgl相关的资料比较少,找下来记录一下,希望可以帮助大家 ...

  2. android textview 复制粘贴,android app 内 实现文本复制粘贴功能

    如果有一天我后悔了自己的决定,希望一切都还来得及. 在app内实现复制粘贴功能,主要分为两种情况.一种是点击按钮,复制指定的文本.一种是长按文本调用系统的复制功能. (一)主要用于复制一些序列号,邀请 ...

  3. Unity调用安卓相册并支持多选图片

    Unity调用安卓相册并支持多选图片 当在Unity中开发Android应用时,有时需要使用安卓设备的相册功能,以便用户可以选择并上传图片.本篇博客将介绍如何在Unity中调用安卓相册,并支持多选图片 ...

  4. clipboard + element-ui +vue 实现复制粘贴功能与提示

    结合 clipboard.js 实现复制.粘贴功能 剪切功能参考官方文档,个人认为用不太上(有富文本编辑器的时候可能才用得上,也或许不需要自己实现) 想要知道怎么使用,优先参考官方文档(如何指定要复制 ...

  5. 安卓手机如何复制粘贴不重叠_怎么复制粘贴,教您手机怎么复制粘贴

    复制黏贴是日常生活中经常会使用到的功能,手机上我们最常用的功能之一就是复制粘贴,但是很多时候,安卓手机直接复制黏贴是很难的.那么安卓手机如何复制粘贴呢?下面,小编给大家讲解手机复制粘贴的操作技巧. A ...

  6. Unity调用安卓Android的Toast

    需求:在游戏中弹窗消息,调起安卓的Toast 项目中需要做Unity和安卓交互时,经常需要通过安卓Toast来做简单的输出,以便于测试. 方法一:Unity中,C#主导 // Unity调用安卓的土司 ...

  7. 软件测试面试题-如何测试复制粘贴功能

    复制粘贴是电脑最普遍的两个操作了,在面试的过程中,有学生被问到如何测试复制粘贴功能的时候,我个人觉得你可以这样去回答 更多学习资源,公众号主页点击领取资料 查看我评论区置顶 首先,这道题目你甚至可以发 ...

  8. js实现复制粘贴功能

    在项目中使用到复制粘贴功能,虽然网上有很多大牛封装了很多的插件,但是还是想不去使用插件,就像自己来实现这个功能. 初步想法: 1. 获取到需要复制的内容,这里我可以将需要复制的内容放在input或者t ...

  9. 最新js实现复制粘贴功能实例

    功能:实现鼠标点击复制内容 描述:使用与手机网站.pc等端. 实现点击复制粘贴功能的代码实例: function common_copy(text){if(text.indexOf('-') !== ...

最新文章

  1. linux系统yum源,Linux开启安装EPEL YUM源
  2. Linux 2.6 完全公平调度算法CFS(Completely Fair Scheduler) 分析
  3. Linux设备驱动开发详解-Note(5)---Linux 内核及内核编程(1)
  4. Mybatis resultMap空值映射问题解决
  5. H.264参考软件JM12.2RC代码详细流程
  6. HDU1286 找新朋友
  7. redchat怎么编写shell脚本_Linux如何编写shell脚本?
  8. android ipv6 谷歌,Ipv6使用google服务的DNS
  9. L44. 通配符匹配
  10. 阿帕网几台大型计算机网络,阿帕网-互联网的鼻祖(中) | 午夜猫
  11. MCU 8080规格LCD屏显示优化——RGB666
  12. 【Scratch案例实操】Scratch字母排序 scratch编程案例教学 scratch创意编程 少儿编程教案
  13. C++ define的用法
  14. 地磁传感器还可以用于室内定位?
  15. JSP开发模型与MVC设计模型
  16. python访问陌生人qq空间_使用Python+Selenium模拟登录QQ空间
  17. IT码农进入日企之路——模拟试题
  18. linux断开其他用户连接,如何Linux中通过命令行注销其他用户ssh连接
  19. 实训一 思科交换机基础配置
  20. 微星小飞机怎么调风扇转速?

热门文章

  1. 使用缓存django、redis
  2. combo接口(combo接口)
  3. 解读PMP考点:PMP考试中关于合同计算类型的题目
  4. 据说99%的程序猿都不懂得这样表白
  5. 三菱FX5U系列PLC电池安装方法以及GX Works3内相关参数设置
  6. 科恩第一章Friday, October 29, 2021 10:13 AM
  7. VirtualBox网络配置:NAT+Host-Only实现连接外网+主机互通
  8. appium怎么测试ios_使用Appium,Cucumber和Serenity测试iOS应用程序—质量秘诀
  9. 婴幼儿体重在线计算机,【婴儿体重计算器标准_婴儿体重计算器标准专题】- 天鹅到家...
  10. 简述igp和egp_igp egp