使用 ARCore 和 Kotlin 开发 Android 增强现实应用入门指南

环境准备

1. 工具与设备要求

  • Android Studio:Arctic Fox 或更高版本

  • 设备 :支持 ARCore 的 Android 设备(查看支持列表

  • 依赖库

    gradle 复制代码
    // build.gradle (Module级)
    dependencies {
        implementation 'com.google.ar:core:1.35.0'
        implementation 'com.google.ar.sceneform:core:1.17.1'
        implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.17.1'
    }

基础实现步骤

1. 配置 AndroidManifest.xml

xml 复制代码
<!-- 添加权限和AR特性 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.ar" android:required="true" />

<application>
    <!-- 声明AR元数据 -->
    <meta-data
        android:name="com.google.ar.core"
        android:value="required" />
</application>

2. 创建完整布局文件

xml 复制代码
<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/arFragment"
        android:name="com.google.ar.sceneform.ux.ArFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

3. 完整 Kotlin 主活动代码

kotlin 复制代码
// MainActivity.kt
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.ar.core.ArCoreApk
import com.google.ar.core.Config
import com.google.ar.core.Session
import com.google.ar.sceneform.AnchorNode
import com.google.ar.sceneform.rendering.ModelRenderable
import com.google.ar.sceneform.ux.ArFragment
import com.google.ar.sceneform.ux.TransformableNode

class MainActivity : AppCompatActivity() {
    private lateinit var arFragment: ArFragment
    private var isArSupported = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        checkARSupport()
        setupARScene()
    }

    // 检查AR支持性
    private fun checkARSupport() {
        val availability = ArCoreApk.getInstance().checkAvailability(this)
        when {
            availability.isSupported -> {
                isArSupported = true
                ArCoreApk.getInstance().requestInstall(this, true)
            }
            availability.isTransient -> {
                // 如果状态是暂时未知,延迟后重新检查
                Handler(Looper.getMainLooper()).postDelayed({
                    checkARSupport()
                }, 200)
            }
            else -> {
                Toast.makeText(this, "设备不支持AR", Toast.LENGTH_LONG).show()
                finish()
            }
        }
    }

    // 初始化AR场景
    private fun setupARScene() {
        arFragment = supportFragmentManager.findFragmentById(R.id.arFragment) as ArFragment

        // 配置AR会话
        arFragment.arSceneView.scene.addOnUpdateListener { frameTime ->
            arFragment.arSceneView.scene
                .getCamera()
                ?.let { camera ->
                    // 在此处添加每帧更新的逻辑
                }
        }

        // 设置点击监听器
        arFragment.setOnTapArPlaneListener { hitResult, plane, motionEvent ->
            placeModel(hitResult.createAnchor())
        }
    }

    // 放置3D模型
    private fun placeModel(anchor: Anchor) {
        ModelRenderable.builder()
            .setSource(this, Uri.parse("model.sfb")) // 替换为你的模型路径
            .build()
            .thenAccept { modelRenderable ->
                val anchorNode = AnchorNode(anchor)
                anchorNode.setParent(arFragment.arSceneView.scene)

                val modelNode = TransformableNode(arFragment.transformationSystem)
                modelNode.renderable = modelRenderable
                modelNode.setParent(anchorNode)

                modelNode.select() // 自动显示变换控制器
            }
            .exceptionally { throwable ->
                Toast.makeText(this, "模型加载失败: ${throwable.message}", Toast.LENGTH_LONG).show()
                null
            }
    }
}

4. 模型资源配置

  1. 准备模型文件

    • .obj.mtl 文件放入 app/src/main/assets

    • 创建 model.sfa 描述文件:

      json 复制代码
      // model.sfa
      {
        "resources": [
          {
            "filename": "model.obj",
            "material": "model.mtl"
          }
        ]
      }
  2. 配置 Gradle 转换任务

    gradle 复制代码
    plugins {
        id 'com.google.ar.sceneform.plugin'
    }
    
    sceneform.asset(
        'src/main/assets/model.obj',
        'default',
        'src/main/assets/model.sfa',
        'src/main/assets/model.sfb'
    )

高级功能扩展

1. 平面检测可视化

kotlin 复制代码
// 在setupARScene()中添加:
arFragment.arSceneView.planeRenderer.isVisible = true
arFragment.arSceneView.planeRenderer.material
    .thenAccept { material ->
        material.setFloat3("color", Color(0.3f, 0.7f, 0.3f))
    }

2. 光照估计

kotlin 复制代码
// 在每帧更新中获取光照信息
arFragment.arSceneView.scene.addOnUpdateListener { frameTime ->
    val frame = arFragment.arSceneView.arFrame
    val lightEstimate = frame?.lightEstimate
    lightEstimate?.let {
        val intensity = it.pixelIntensity
        // 根据光照强度调整模型材质
    }
}

常见问题解决

1. 黑屏问题排查

  • 检查相机权限是否动态申请:

    kotlin 复制代码
    // 在onCreate()中添加权限检查
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) 
        != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, 
            arrayOf(Manifest.permission.CAMERA), 
            REQUEST_CAMERA_PERMISSION)
    }

2. 模型位置偏移

  • 调整模型原点:

    kotlin 复制代码
    modelNode.localPosition = Vector3(0f, 0.5f, 0f) // 在Y轴上抬高0.5米

完整项目结构

复制代码
app/
├── src/
│   ├── main/
│   │   ├── assets/
│   │   │   ├── model.obj
│   │   │   ├── model.mtl
│   │   │   └── model.sfa
│   │   ├── java/
│   │   │   └── com.example.arapp/
│   │   │       └── MainActivity.kt
│   │   └── res/
│   │       └── layout/
│   │           └── activity_main.xml
└── build.gradle

运行与调试

  1. 设备要求

  2. 调试技巧

    kotlin 复制代码
    // 启用调试模式
    arFragment.arSceneView.arFrame?.let { frame ->
        Log.d("AR_DEBUG", "跟踪状态: ${frame.camera.trackingState}")
    }

下一步学习方向

  • 手势交互:实现模型的旋转/缩放/平移
  • 遮挡处理:使用深度API实现真实遮挡效果
  • 多人共享:通过Cloud Anchors实现多设备协同

建议从简单模型开始,逐步添加复杂功能。

相关推荐
androidwork5 小时前
Kotlin与机器学习实战:Android端集成TensorFlow Lite全指南
android·机器学习·kotlin·tensorflow
ALex_zry7 小时前
程序运行报错分析文档
android·c++
投笔丶从戎7 小时前
Kotlin Multiplatform--04:经验总结(持续更新)
android·开发语言·kotlin
stevenzqzq7 小时前
kotlin flow的写法
android·kotlin·flow
悠哉清闲7 小时前
Kotlin 协程 (三)
android·开发语言·kotlin
androidwork7 小时前
在 Android 中实现支持多手势交互的自定义 View(Kotlin 完整指南)
android·kotlin·交互
我怀里的猫7 小时前
kotlin 将一个list按条件分为两个list(partition )
开发语言·kotlin·list
悠哉清闲8 小时前
Kotlin 协程 (二)
android·开发语言·kotlin
说码解字8 小时前
Kotlin 协程
java·前端·kotlin