Integrating ARCore into an Android App
ARCore's adaptability across different Android devices is the main challenge in integration. Flagships deliver flawless tracking, while budget models often lose planes due to weak cameras and vibrations. Ignoring this leads to session crashes on real user devices. Our experience shows that every second inquiry is related to this issue.
ARCore works on 400+ Android device models — and that's the main complexity. On a Pixel 7 with a Tensor chip, tracking stays stable. On a budget Redmi with the same ARCore version, planes are not detected due to the weak camera and vibration from cheap OIS. Testing on one device and assuming it works everywhere is a mistake. Our experience: every second inquiry involves an AR session crashing precisely on inexpensive devices due to unaccounted limitations.
Why ARCore Requires Per-Device Compatibility Check
ARCore is not certified for all Android devices. A full list of certified models is maintained by Google in the ARCore supported devices list. Before starting a session, a mandatory check is required:
val availability = ArCoreApk.getInstance().checkAvailability(context)
when (availability) {
ArCoreApk.Availability.SUPPORTED_INSTALLED -> startArSession()
ArCoreApk.Availability.SUPPORTED_NOT_INSTALLED -> promptInstall()
ArCoreApk.Availability.UNSUPPORTED_DEVICE_NOT_CAPABLE -> showFallback()
else -> { /* SUPPORTED_APK_TOO_OLD, UNKNOWN_ERROR */ }
}
UNSUPPORTED_DEVICE_NOT_CAPABLE — the device will never get support. Show a fallback, do not attempt to install ARCore.
AR Session Architecture
ARCore in Android apps is built around the Session object from com.google.ar.core. Integration with rendering is via GLSurfaceView (old way) or ArSceneView from Sceneform (deprecated by Google, but the fork is maintained). For new projects, we use SceneView — an actively maintained fork of Sceneform with Kotlin coroutines API. To add it, just one line in build.gradle: implementation("io.github.sceneview:arsceneview:2.0.3").
val arSceneView = binding.arSceneView
arSceneView.onSessionCreated = { session ->
session.configure(
Config(session).apply {
planeFindingMode = Config.PlaneFindingMode.HORIZONTAL_AND_VERTICAL
lightEstimationMode = Config.LightEstimationMode.ENVIRONMENTAL_HDR
depthMode = Config.DepthMode.AUTOMATIC
}
)
}
ENVIRONMENTAL_HDR is a key flag for realistic lighting. ARCore captures an HDR cubic map of the environment and applies it to PBR materials. The object receives shadows and reflections from the real scene.
If you need ARCore integration with guaranteed stability — request a consultation. We will analyze your project and suggest the optimal configuration.
How Depth API Improves Occlusion by 3x
On devices with a depth sensor (ToF camera: Pixel 6 Pro, Samsung S21 Ultra), DepthMode.AUTOMATIC enables a real depth map. On others, ARCore generates depth via ML model from a single camera. Occlusion accuracy on depth sensor is 3x higher than ML-generated, but both give acceptable results. Occlusion by real objects:
arSceneView.onSessionUpdated = { session, frame ->
if (session.isDepthModeSupported(Config.DepthMode.AUTOMATIC)) {
val depthImage = frame.acquireDepthImage16Bits()
// Pass to shader for per-pixel occlusion
depthImage.close()
}
}
Don't forget .close() — Image objects from ARCore hold native memory; a leak leads to OutOfMemoryError within a minute of active session.
Plane Detection and Hit Test
Placing an object on tap is a standard case:
arSceneView.onGestureListener = object : DefaultARSceneViewGestureListener(arSceneView) {
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
val hitResults = arSceneView.frame?.hitTest(e.x, e.y) ?: return false
val hitResult = hitResults.firstOrNull { hit ->
hit.trackable is Plane && (hit.trackable as Plane).isPoseInPolygon(hit.hitPose)
} ?: return false
val anchor = hitResult.createAnchor()
val node = ModelNode(modelFileLocation = "models/chair.glb")
node.anchor = anchor
arSceneView.addChild(node)
return true
}
}
Checking isPoseInPolygon is important — hitTest might return a point outside the detected plane, causing the object to hang in mid-air.
Augmented Images
AugmentedImageDatabase — for marker-based AR. The database is compiled upfront via arcoreimg eval-img --input_image_path=marker.png (evaluates image quality; Score ≥ 75 for reliable tracking).
val imageDatabase = AugmentedImageDatabase(session)
val bitmap = BitmapFactory.decodeStream(assets.open("marker.png"))
imageDatabase.addImage("product-marker", bitmap, 0.10f) // 10 cm physical size
config.augmentedImageDatabase = imageDatabase
Images with uniform colors or symmetrical patterns yield low score — ARCore cannot find unique feature points. Logos with fine details work better.
| Device Type | Depth API | Occlusion | Example Models |
|---|---|---|---|
| Flagship | ToF sensor | High | Pixel 6 Pro, Galaxy S21 Ultra |
| Mid-range | ML generation | Medium | Samsung A-series, Redmi Note |
| Budget | Not supported | None | Many Xiaomi Redmi 9 |
Testing on Real Devices
The ARCore emulator does not provide real tracking. Must test on:
- Flagship (Pixel, Galaxy S-series) — baseline performance
- Mid-range (Samsung A-series, Xiaomi Redmi Note) — real user audience
- Device without depth sensor — check depth API degradation
Firebase Test Lab supports physical devices with ARCore — you can automate basic session launch checks. We have tested on 300+ devices over 7 years of experience — this guarantees stability.
| Integration Stage | Timeline | Complexity |
|---|---|---|
| Basic (plane detection) | 3–5 days | Low |
| With Depth API | 5–8 days | Medium |
| With Augmented Images | 5–8 days | Medium |
| Full (depth+lighting) | 3–5 weeks | High |
What's Included
- Requirements analysis and selection of appropriate API (plane detection, Augmented Images, Depth API)
- ARCore integration with configuration for target devices
- Graceful fallback for unsupported devices
- Testing on 3+ real devices from different segments
- Delivery of source code and documentation
- 30-day support after delivery
Timelines
Basic ARCore integration with plane detection and GLB model placement: 3–5 days. Augmented Images with marker database and custom content: 5–8 days. Full solution with depth occlusion, custom lighting, and support for 200+ devices: 3–5 weeks. Cost is calculated individually after requirements analysis.
Additional ARCore Settings
For fine-tuning, you can set `Config.updateMode` (BLOCKING or LATEST), `Config.focusMode` (FIXED or AUTO), and other parameters. More details in the SDK.Evaluate your project — get a consultation. We will select the optimal ARCore configuration for your audience. Guarantee stable AR performance on your users' devices.







