学习AR应用开发有一段时间了,自己开发了一款简单的APP来练手,在这里分享给大家。

APP链接:https://www.coolapk.com/apk/173761

前面介绍了Unity3D部分的实现,现在就来介绍Android原生部分的编码实现。

1.APP基础UI框架及交互逻辑




avalonia android 添加Assets avatarify安卓教程_Unity3D



target name,target name就是vuforia创建的识别图的名称。




avalonia android 添加Assets avatarify安卓教程_Unity3D_02



详情页加载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>



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>


@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的名称;


第二个参数是脚本中定义函数名称;


第三个参数是传递给函数的参数(可空)。




avalonia android 添加Assets avatarify安卓教程_Unity3D_03



avalonia android 添加Assets avatarify安卓教程_Unity3D_04



5)添加关闭方法


@OnClick(R.id.btnClose)
public void onViewClicked() {
    finish();
}



到这里可以运行查看效果了,但是细心的人会发现一个问题,就是当点击关闭按钮即调用finish()方法退出会 造成整个APP所在进程退出 ,平时我们调用finish()只是当前Activity退出,要找到原因就要查看源码了。



因为我们的Activity继承的是UnityPlayerActivity,在这个类中定义了finish方法,所以在子Activity中调用退出实际是调用了父类的finish方法:


@Override
public void finish() {
    mUnityPlayer.quit();  //问题关键在这里
    super.finish();  //这里是调用Activity的finish方法,即平时正常的调用的方法
}


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();
}


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() {
    }
}




// Setup activity layout
@Override protected void onCreate(Bundle savedInstanceState)
{
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    super.onCreate(savedInstanceState);

    mUnityPlayer = new AndUnityPlayer(this); //将UnityPlayer替换成AndUnityPlayer 
}

大功告成,解决了finish问题。



运行起来的效果就是这样:


avalonia android 添加Assets avatarify安卓教程_教程_05




到这里就介绍完毕了,这几篇教程只是笼统的讲解编写AR APP的简单流程,因为我自己学习AR开发也没有多长时间,所以很多地方讲解的不够细致。