I’m working on integrating DeepAR SDK v5.6.19 into my custom React Native Android app using a native module. I followed all documented steps (license key, rendering surface, OpenGL view), but AREventListener.initialized() is never called, and DeepAR stays stuck in an uninitialized state.
Environment
SDK Version: 5.6.19 (.aar)
Android compileSdkVersion: 34
package com.communax.app
import ai.deepar.ar.*
import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.media.Image
import android.opengl.GLSurfaceView
import android.os.Handler
import android.os.Looper
import android.util.AttributeSet
import android.util.Log
import android.view.SurfaceHolder
import android.widget.FrameLayout
import java.util.concurrent.atomic.AtomicBoolean
class DeepARCameraView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {
private val TAG = "DeepARCameraView"
private val surfaceView = GLSurfaceView(context)
private var deepAR: DeepAR? = null
private var cameraGrabber: CameraGrabber? = null
private var pendingSurfaceHolder: SurfaceHolder? = null
private var surfaceWidth = 0
private var surfaceHeight = 0
private var isDeepARInitialized = false
private var isRendererReady = false
private val isDeepARFullyReady = AtomicBoolean(false)
private val deepAREngineInitialized = AtomicBoolean(false)
private val eventListener = object : AREventListener {
override fun initialized() {
Log.d(TAG, "✅ DeepAR initialized callback fired!")
deepAREngineInitialized.set(true)
postDelayed({ tryToInitializeRenderSurface() }, 300)
}
override fun error(type: ARErrorType?, msg: String?) {
Log.e(TAG, "❌ DeepAR Error: $type - $msg", Throwable(msg))
}
override fun faceVisibilityChanged(p0: Boolean) {
Log.d(TAG, "👤 faceVisibilityChanged: $p0")
}
override fun imageVisibilityChanged(p0: String?, p1: Boolean) {
Log.d(TAG, "🖼 imageVisibilityChanged: $p0, $p1")
}
override fun frameAvailable(p0: Image?) {
Log.d(TAG, "📸 frameAvailable")
}
override fun effectSwitched(p0: String?) {
Log.d(TAG, "✨ effectSwitched: $p0")
}
override fun screenshotTaken(p0: Bitmap?) {
Log.d(TAG, "📸 screenshotTaken")
}
override fun videoRecordingStarted() {
Log.d(TAG, "🎥 videoRecordingStarted")
}
override fun videoRecordingFinished() {
Log.d(TAG, "✅ videoRecordingFinished")
}
override fun videoRecordingFailed() {
Log.e(TAG, "❌ videoRecordingFailed")
}
override fun videoRecordingPrepared() {
Log.d(TAG, "🔧 videoRecordingPrepared")
}
override fun shutdownFinished() {
Log.d(TAG, "🛑 shutdownFinished")
}
}
init {
setupSurfaceView()
}
private fun setupSurfaceView() {
surfaceView.setEGLContextClientVersion(2)
surfaceView.setPreserveEGLContextOnPause(true)
surfaceView.setZOrderOnTop(false)
surfaceView.holder.setFormat(PixelFormat.TRANSLUCENT)
surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
Log.d(TAG, "🟢 surfaceCreated()")
pendingSurfaceHolder = holder
postDelayed({ tryToInitializeRenderSurface() }, 100)
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
Log.d(TAG, "🟡 surfaceChanged(): $width x $height")
surfaceWidth = width
surfaceHeight = height
pendingSurfaceHolder = holder
postDelayed({ tryToInitializeRenderSurface() }, 100)
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
Log.d(TAG, "🔴 surfaceDestroyed()")
try {
deepAR?.setRenderSurface(null, 0, 0)
} catch (e: Exception) {
Log.e(TAG, "Error clearing render surface", e)
}
}
})
addView(surfaceView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
Log.d(TAG, "🔗 View attached, initializing DeepAR")
if (deepAR == null) {
initializeDeepAR()
}
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
Log.d(TAG, "🧹 View detached, releasing resources")
cameraGrabber?.stop()
deepAR?.release()
deepAR = null
}
private fun initializeDeepAR() {
val context = SafeContextProvider.getActivity() ?: run {
Log.e(TAG, "❌ Activity is null!")
return
}
Log.d(TAG, "🧩 Initializing DeepAR with context: ${context::class.java.name}")
if (context == null) {
Log.e(TAG, "❌ SafeContextProvider.getActivity() returned null — DeepAR needs Activity context.")
return
}
try {
deepAR = DeepAR(context)
Log.d(TAG, "✅ DeepAR instance created: $deepAR")
Log.d(TAG, "📦 App ID = ${context.packageName}")
Log.d(TAG, "📦 Deepar = ${deepAR}")
val licenseKey = "e214e27f0092981f591a339aba8ee632fda4620e96dca6b2241ea3a8128b8cb7f636664c47bf52f2"
deepAR?.setLicenseKey(licenseKey)
Log.d(TAG, "🔑 License key set")
val pkgName = context.packageName
Log.d(TAG, "🔒 License Key Length = ${licenseKey.length}")
Log.d(TAG, "🔒 License Key (first 8) = ${licenseKey.take(8)}...")
Log.d(TAG, "📦 Package name: ${context.packageName}")
Log.d(TAG, "🔍 Context class: ${context::class.java.name}")
Log.d("DeepAR", "🛠 Initializing DeepAR with context: $context")
deepAR?.initialize(context, eventListener)
Log.d(TAG, "📡 Called deepAR.initialize()")
surfaceView.setRenderer(DeepARRenderer(deepAR!!) {
Log.d(TAG, "✅ Renderer callback: Renderer initialized")
isDeepARInitialized = true
isRendererReady = true
postDelayed({ tryToInitializeRenderSurface() }, 300)
})
surfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY)
surfaceView.requestRender()
cameraGrabber = CameraGrabber(context, deepAR!!, isDeepARFullyReady)
Handler(Looper.getMainLooper()).postDelayed({
if (!deepAREngineInitialized.get()) {
Log.e(TAG, "🛑 DeepAR initialized() never called — LICENSE/CONTEXT/SURFACE ISSUE")
Log.d(TAG, "🔍 Diagnostics: pkg=${context.packageName}, isActivity=${context is Activity}, surfaceValid=${surfaceView.holder.surface?.isValid == true}")
}
}, 5000)
} catch (e: Exception) {
Log.e(TAG, "❌ Exception during DeepAR initialization", e)
}
}
private fun tryToInitializeRenderSurface(attempt: Int = 1) {
val holder = pendingSurfaceHolder ?: surfaceView.holder
val deepar = deepAR
val isSurfaceValid = holder.surface?.isValid == true
Log.d(TAG, """
🔍 Attempt $attempt:
➤ DeepAR initialized: $isDeepARInitialized
➤ Renderer ready: $isRendererReady
➤ Engine initialized: ${deepAREngineInitialized.get()}
➤ Surface valid: $isSurfaceValid
""".trimIndent())
if (isDeepARInitialized && isRendererReady && deepAREngineInitialized.get() && isSurfaceValid && deepar != null) {
try {
deepar.setRenderSurface(holder.surface, surfaceWidth, surfaceHeight)
Log.d(TAG, "✅ Render surface set successfully")
isDeepARFullyReady.set(true)
cameraGrabber?.start()
} catch (e: Exception) {
Log.e(TAG, "❌ Failed to set render surface", e)
}
} else if (attempt < 10) {
postDelayed({ tryToInitializeRenderSurface(attempt + 1) }, 300)
} else {
Log.e(TAG, "❌ Max render attempts reached")
}
}
fun isDeepARReady(): Boolean = isDeepARFullyReady.get()
}
Observations:
- I can confirm that:
- The
DeepAR
object is created successfully - The
setRenderSurface()
is called after the surface is created - No crashes — but
AREventListener.initialized()
is never called - This blocks
receiveFrame()
with error:IllegalStateException: DeepAR not yet initialize
- The
Questions:
- Are there any known issues in SDK v5.6.19 where
AREventListener.initialized()
is silently skipped? - Could React Native’s lifecycle delay or JS context cause DeepAR to initialize improperly?
- Can you confirm that SDK v5.6.19 only supports Android compileSdkVersion 34+? (Because many androidx.camera and media3 dependencies now fail below 34)
There are no visible logs or exceptions from DeepAR when initialized() never fires — which makes it hard to detect configuration issues. A more explicit warning or failure reason would help a lot here.