Android(安卓)Unity3D 相互交互,及退出继承UnityPlayerActivity的Crash问题
这是我第一次写博文,只是我做过项目的一些技术点,也就相当于自己的笔记,希望能对看到文章的你有用。
公司项目比较多使用AR,一般我们都是使用第三方SDK,使用的EasyAR。它有两种方式来实现AR功能,第一种是用JNI,使用NDK(自行百度google查找相关技术文章),第二种是Android和Unity3D的交互,Ar图形,模型视频等由Unity3D来完成,Android来处理 加载创建 扫描 脱卡等事件处理(着重讲这部分)。
Unity导出的项目:
我记录Android这部分的操作 不记录Unity3D的
首先你要让Unity的工程师导出一份Android项目给你,当然导出的AS项目(我没用过Eclipse的方式)
lib文件下面是要使用的Jar包
src中包括了assets,jniLibs和java文件夹下的UnityPlayerActivity,UnityPlayerNativeActivity,UnityPlayerProxyActivity.建议使用UnityPlayerActivity.java,assets文件中是unity的一些资源文件,包括了场景和渲染的一些文件,jniLibs当然是所用到的.so文件了
- 如果你已经有Android的工程项目了,此时你只需要把assets的文件和lib中的文件,和jniLibs的文件拷贝到你的项目中去,然后把需要配置的类和权限在AndroidManifest.xml中配置一下(EasyAR需要用到摄像头的权限,在6.0以上的版本也无需去申请权限,SDK中有集成了。如果你不放心 可以再去申请)
- 没有项目,那么只需要把unity的导出项目直接导入到你的Android Studio中即可。
下面就是我导入完成后的项目结构图
ArMapActivity的布局
先介绍一下 两者之间的调用方法的方式:
Android调用Unity的方法
UnityPlayer.UnitySendMessage("ImageTargetManager", "LoadNativeAssetBundle", json);
- 第一个参数"ImageTargetManager"是Unity Object对象,需要在Unity对象上绑定脚本】
- 第二个参数"LoadNativeAssetBundle"是Unity 中定义的方法名 (这两个都是Unity工程师会提供给你的)
- 第三个参数是定义方法的参数(可空)。
Unity调用Android的方法
先在Android自定义一个方法
Android代码
/** * Unity调用此方法并把参数jsonString 调用给Android * @param jsonString */ public void Unity3DSendMessage(String jsonString) { Log.i("TAG", "[Unity3DSendMessage] " + jsonString); final JsonRetrun entity = new Gson().fromJson(jsonString, JsonRetrun.class); switch (entity.getActionName()) { case "sceneLoaded": break; case "loadModelAssetCompleted": break; case "imageTargetBound": break; case "imageTargetBoundFail": break; case "TargetFound": break; case "TargetLost": break; default: break; } }
Unity代码
AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");AndroidJavaObject jo = jc.GetStatic ("ArMapActivity");jo.Call ("Unity3DSendMessage","");
jo.call(String str1,String str2);第一个参数是Android的方法名,第二个参数是传递给Android的参数
到这边已经把Android交互Unity的方法方式介绍完成了
发现的一个坑
当你使用玩AR时 点击系统返回或者是自定义的ImageButton返回时, 如果你调用的是onDestroy方法,你会发现应用出现了Crash,如果你单单在点击事件中 finish();该Activity,也会出现Crash。
UnityPlayerActivity中onDestory方法是这么写的
@Override protected void onDestroy() { mUnityPlayer.quit(); super.onDestroy(); }
这样写 会使后面的代码不执行了,从而造成Crash
对mUnityPlayer.quit()方法的反编译之后 发现quit方法是这样的
public void quit() { this.k = true; if(!this.e.e()) { this.pause(); } this.a.a(); try { this.a.join(4000L); } catch (InterruptedException var1) { this.a.interrupt(); } if(this.g != null) { this.h.unregisterReceiver(this.g); } this.g = null; if(l.c()) { this.removeAllViews(); } if(i.b) { i.g.a(this.h); } this.kill(); h();}
注意倒数第二行的this.kill()方法,不看实现可以猜出应该是杀进程的。所以...
我google百度了不少时间发现了 可以在该Activity的AndroidManifest.xml中设置一个新的进程。这样,就不会影响你本身项目的进程
AndroidManifest设置.png这样设置之后,虽然解决了不会崩溃问题,但是有时候退出Activity时会卡住一段时间。
我在搜索mUnityPlayer.quit()的时候还看到别人针对这个问题做了另外一种解决,就是重写UnityPlayer类的kill方法(就是上面提到的kill方法,然后再去调用自己重写的方法即可
重写的例子如下:
public class MyUnityPlayer extends UnityPlayer { public MyUnityPlayer(ContextWrapper contextWrapper) { super(contextWrapper); } //不执行父类的方法 @Override protected void kill() { }}
然后在有Unity的ArMapActivity中
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mUnityPlayer = new MyUnityPlayer(this); layoutUnity.addView(mUnityPlayer); mUnityPlayer.requestFocus(); }
这样子,就能解决退出Activity不Crash,并且响应速度也比较快。
更多相关文章
- Android(安卓)Quantity Strings 的 getQuantityString方法取值问
- 【Android】webView 使用 系统自带搜索对话框问题
- Android报表解决方案 使用开源组件iChartjs(二)
- Android(安卓)AOP实现原理全解析
- Android(安卓)4.3实现类似iOS在音乐播放过程中如果有来电则音乐
- Android(安卓)VR Player(全景视频播放器) [1]:项目介绍
- Android:Service生命周期方法与Service启动方式bindService与Star
- Android异步接口测试
- Android(安卓)图片压缩策略详解,有效解决 Android(安卓)程序 OOM