[Android SDK 5.6.19] DeepAR never triggers initialized() in custom integration (React Native + custom camera)

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.

:white_check_mark: 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()
}

:test_tube: 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

:red_question_mark:Questions:

  1. Are there any known issues in SDK v5.6.19 where AREventListener.initialized() is silently skipped?
  2. Could React Native’s lifecycle delay or JS context cause DeepAR to initialize improperly?
  3. 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.