学习AR应用开发有一段时间了,自己开发了一款简单的APP来练手,在这里分享给大家。
APP链接:https://www.coolapk.com/apk/173761
前面介绍了Unity3D部分的实现,现在就来介绍Android原生部分的编码实现。
1.APP基础UI框架及交互逻辑
首页就是简单的ViewPager+Fragment,其中数据用RecyclerView展示。点击某项Item进入详情页,并传入参数
target name,target name就是vuforia创建的识别图的名称。
详情页加载SVG图片,这里使用VectorDrawable做了一个简单的颜色变换效果,点击下方的按钮就会调用Unity做的AR功能。
2.原生调用Unity
1)新建Activity继承UnityPlayerActivity
public class UnityMainActivity extends UnityPlayerActivity {}
2)新建布局文件activity_unity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000" tools:context="com.cdh.paperup.ui.UnityMainActivity"> <FrameLayout android:id="@+id/flUnityContainer" android:layout_width="match_parent" android:layout_height="match_parent"/> <Button android:id="@+id/btnClose" android:layout_width="28dp" android:layout_height="28dp" android:layout_margin="10dp" android:background="@mipmap/btn_close"/> </RelativeLayout>FrameLayout用于加载UnityPlayer显示Unity场景,Button用于关闭按钮。
3)接着在AndroidManifest中定义
<activity android:name=".ui.UnityMainActivity" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale|layoutDirection|density" android:launchMode="singleTask" android:screenOrientation="landscape"> <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> </activity>4)在Activity中添加UnityPlayer并调用
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_unity_main); ButterKnife.bind(this); key = getIntent().getStringExtra("key"); //key即targetName flUnityContainer.addView(mUnityPlayer); //添加UnityPlayer到布局中 mUnityPlayer.requestFocus(); mUnityPlayer.UnitySendMessage("TargetManager", "ConfigTrackable", key); //调用Unity方法 }mUnityPlayer.UnitySendMessage(String, String, String)这个就是Android原生调用Unity的方法:
第一个参数是Unity脚本所在GameObject的名称;
第二个参数是脚本中定义函数名称;
第三个参数是传递给函数的参数(可空)。
5)添加关闭方法
@OnClick(R.id.btnClose) public void onViewClicked() { finish(); }
因为我们的Activity继承的是UnityPlayerActivity,在这个类中定义了finish方法,所以在子Activity中调用退出实际是调用了父类的finish方法:
@Override public void finish() { mUnityPlayer.quit(); //问题关键在这里 super.finish(); //这里是调用Activity的finish方法,即平时正常的调用的方法 }进入mUnityPlayer.quit()方法:
public void quit() { if(GoogleVrApi.b() != null) { GoogleVrApi.a(); } this.q = 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.n.unregisterReceiver(this.g); } this.g = null; if(l.c()) { this.removeAllViews(); } this.kill(); //调用了kill方法 g(); }可以看到一个kill方法,顾名思义就是这里真正执行销毁的方法,进入查看:
protected void kill() { Process.killProcess(Process.myPid()); //销毁当前进程 }看到原来是这里销毁了当前所在进程,找到原因就好解决问题了。
新建class继承UnityPlayer,UnityPlayer中的kill方法是protected修饰,所以可以在子类重新kill方法:
public class AndUnityPlayer extends UnityPlayer { public AndUnityPlayer(Context context) { super(context); } @Override protected void kill() { } }修改UnityPlayerActivity中的onCreate方法:
// Setup activity layout @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); mUnityPlayer = new AndUnityPlayer(this); //将UnityPlayer替换成AndUnityPlayer }大功告成,解决了finish问题。
运行起来的效果就是这样:
到这里就介绍完毕了,这几篇教程只是笼统的讲解编写AR APP的简单流程,因为我自己学习AR开发也没有多长时间,所以很多地方讲解的不够细致。