Aqara Camera SDK Integration Guide

Version: v1.0.5 Update Date: December 2025 Platform: Android


Table of Contents


1. Overview

Aqara Camera SDK is an intelligent camera solution provided by Lumi United, helping developers quickly integrate Aqara series camera features such as device provisioning, real-time preview, playback, cloud storage, and more into your Android applications.

Architecture Diagram

┌─────────────────────────────────────────────────────────┐
│                  Your Application (Host App)            │
├─────────────────────────────────────────────────────────┤
│                  Aqara Camera SDK                       │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐   │
│  │  Provisioning│  │  Camera      │  │  Cloud       │   │
│  │  Module      │  │  Control     │  │  Storage     │   │
│  │  Access      │  │  Camera      │  │  Cloud       │   │
│  └──────────────┘  └──────────────┘  └──────────────┘   │
├─────────────────────────────────────────────────────────┤
│                  Aqara Core SDK                         │
│      (Network Communication / User Management /         │
│       Device Management)                                │
└─────────────────────────────────────────────────────────┘

2. Features

Feature Module Description
🔗 Device Provisioning Supports AP provisioning, Bluetooth provisioning, and more
📹 Real-time Preview High-definition real-time video streaming
🔊 Two-way Audio Supports two-way voice communication with camera
📼 Video Playback Local SD card video playback
☁️ Cloud Storage Cloud video storage and playback
🔔 Message Push Motion detection, doorbell call, and other event notifications
⚙️ Device Settings Video quality, motion detection sensitivity, and other parameter configurations

3. Requirements

Requirement Minimum Version Recommended Version
Android SDK API 26 (Android 8.0) API 34 (Android 14)
Kotlin 1.8.0 2.1.0
Java 11 11
Gradle 7.4 7.4.2
Android Gradle Plugin 7.4.0 7.4.2

Supported CPU Architectures

  • arm64-v8a
  • armeabi-v7a

4. Quick Integration

4.1 Add Maven Repository

Add the Aqara Maven repository in the project root settings.gradle:

pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
        // Aqara Maven Repository
        maven {
            url 'https://public-maven.aqara.com/repository/lumi-release/'
            credentials {
                username = 'aqara_guest'
                password = 'tMQ_BNN!z54W.2S'
            }
        }
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
        // Aqara Maven Repository
        maven {
            url 'https://public-maven.aqara.com/repository/lumi-release/'
            credentials {
                username = 'aqara_guest'
                password = 'tMQ_BNN!z54W.2S'
            }
        }
    }
}

Add plugin dependencies in the project root build.gradle:

buildscript {
    dependencies {
        // Aqara SDK Unified Initialization Plugin (Required)
        classpath "com.lumi.plugin:module-init:3.0.0"
    }
}

plugins {
    id 'com.android.application' version '7.4.2' apply false
    id 'org.jetbrains.kotlin.android' version '2.1.0' apply false
}

4.2 Add Dependencies

Add dependencies in app/build.gradle:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

// Apply Aqara SDK Unified Initialization Plugin (Required)
apply plugin: 'lumi-module-init'

android {
    namespace 'com.your.package.name'
    compileSdk 34

    defaultConfig {
        minSdk 26
        targetSdk 34
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }

    kotlinOptions {
        jvmTarget = '11'
    }

    // Resolve so library conflicts
    packagingOptions {
        pickFirst 'lib/arm64-v8a/libc++_shared.so'
        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
    }
}

dependencies {
    // ==================== Aqara SDK Core Dependencies ====================

    // Core SDK (Required) - Provides basic network, user management, etc.
    implementation 'com.lumi.external:core:2.2.9'

    // ==================== Provisioning SDK (Optional) ====================

    // Device Provisioning SDK
    implementation 'com.lumi.module.smart_connect:connect:3.4.129'
    implementation 'com.lumi.module.access:access:3.4.129'
    implementation 'com.lumi.api:access:3.4.129'

    // ==================== Camera SDK (Required) ====================

    // Camera SDK
    implementation 'com.lumi.sdk:camera:3.2.448.10'
    implementation 'com.lumi.api:camera:3.2.448.10'

    // ==================== Other Required Dependencies ====================

    // Router Module
    implementation 'com.lumi.module.router:router:1.0.24'
    implementation 'com.lumi.sdk:device-router:1.0.5'

    // Device Control Plugin
    implementation 'com.lumi.sdk:rmextra:1.1.66.2'

    // System Properties
    implementation 'com.lumi.lib.sysprop:sysprop:1.0.0'

    // Device Management
    implementation 'com.lumi.module:devicekit:1.0.22'

    // ARouter (Page routing, required)
    implementation 'com.alibaba:arouter-api:1.5.2'
}

4.3 Configure AndroidManifest

Add necessary configurations in AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- Network Permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

    <!-- Storage Permissions (for video screenshots and recordings) -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <!-- Bluetooth Permissions (for provisioning) -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Location Permissions (for provisioning) -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <!-- Microphone Permission (for two-way audio) -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <application
        android:name=".YourApplication"
        android:allowBackup="false"
        android:networkSecurityConfig="@xml/network_security_config"
        android:usesCleartextTraffic="true"
        tools:replace="android:allowBackup,android:networkSecurityConfig">

        <!-- FileProvider Configuration (for file sharing) -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/lm_rm_extra_file_paths" />
        </provider>

    </application>
</manifest>

Create the network security configuration file res/xml/network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

Create the file path configuration res/xml/lm_rm_extra_file_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external" path="." />
    <external-files-path name="external_files" path="." />
    <cache-path name="cache" path="." />
    <files-path name="files" path="." />
</paths>

4.4 Configure ProGuard Rules

Add to proguard-rules.pro:

# ==================== Aqara SDK ProGuard Rules ====================

# Core SDK
-keep class com.lumi.** { *; }
-keep class com.lumiunited.** { *; }
-dontwarn com.lumi.**
-dontwarn com.lumiunited.**

# ARouter
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

# FastJSON
-keep class com.alibaba.fastjson.** { *; }
-dontwarn com.alibaba.fastjson.**

# RxJava
-keep class io.reactivex.** { *; }
-dontwarn io.reactivex.**

# Keep Entity Classes
-keep class * implements java.io.Serializable { *; }
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

5. SDK Initialization

5.1 Application Initialization

Initialize in your Application class:

import android.app.Application
import com.alibaba.android.arouter.launcher.ARouter
import com.lumi.api.camera.AppConfigManager
import com.lumi.arms.lifecycle.delegate.AppManager
import com.lumiunited.CameraSDKInit

class YourApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        // 2. Initialize ARouter (enable logs only in Debug mode)
        if (BuildConfig.DEBUG) {
            ARouter.openLog()
            ARouter.openDebug()
        }
        ARouter.init(this)

        // 3. Initialize Lifecycle Manager
        AppManager.instance.init(this)

        // 4. Initialize Camera SDK
        CameraSDKInit.init(this)
    }
}

5.2 Core SDK Initialization

Core initialization is required before using SDK features (recommended to perform on splash screen or home page):

import com.lumi.external.LumiCoreManager
import com.lumi.external.manager.session.ILumiUserInfo
import com.lumi.module.camera.CameraSDKManager
import com.lumi.module.camera.utils.JumpToWebPageUtils
import com.lumiunited.CameraSDKInit
import io.reactivex.plugins.RxJavaPlugins

class SplashActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Set SDK Mode
        CameraSDKManager.setSDKMode(true)

        // Set RxJava Global Error Handler
        RxJavaPlugins.setErrorHandler { it.printStackTrace() }

        // Initialize SDK
        initAqaraSDK()
    }

    private fun initAqaraSDK() {
        // ==================== Configuration Parameters ====================
        // The following parameters need to be obtained from Aqara Developer Platform
        // Documentation: https://opendoc.aqara.com/docs/developmanual/addDevice/appSDK.html

        val appId = "YourAppId"              // Apply from Developer Platform
        val appKey = "YourAppKey"            // Apply from Developer Platform
        val appRequestDomain = "https://aiot-rpc.aqara.cn"  // API Domain
        val baseH5Url = "https://cdn.aqara.com/cdn/app/mainland/h5/index.html#"
        val baseImageUrl = "https://cdn.aqara.com/cdn/common/mainland/prd/statics/default"

        // User Information (obtained from your server)
        val userId = "UserId"
        val token = "UserToken"
        val positionId = "PositionId"

        // Region Configuration
        val area = "CHN"                     // Country/Region Code
        val supportDeviceArea = "CHN"        // Device Supported Region
        val language = "zh"                  // Language (zh/en)

        // ==================== Extension Configuration ====================
        val extension = HashMap<String, String>().apply {
            // Use local device plugin resources
            put("RMSDK_K_LOCAL_RES", "true")
            put("RMExtraSDK_K_CONFIG_LOAD_TYPE", "0")
            put("BaseH5UrlV2", JumpToWebPageUtils.getH5UrlV2())
        }

        // Initialize RN Extensions
        CameraSDKInit.initRnExtensions(extension)

        // ==================== Core Initialization ====================
        LumiCoreManager.getInstance().init(
            application,
            true,  // Enable logs
            LumiCoreManager.LumiCoreSDKConfig.builder()
                .appId(appId)
                .appKey(appKey)
                .baseUrl(appRequestDomain)
                .baseImageUrl(baseImageUrl)
                .baseH5Url(baseH5Url)
                .sdkChannel("YourAppName")           // Your application name
                .clientId(getDeviceUniqueId())       // Device unique identifier
                .extensions(extension)
                .userInfo(object : ILumiUserInfo {
                    override fun getUserId(): String = userId
                    override fun getUserToken(): String = token
                    override fun getArea(): String = area
                    override fun getSupportDeviceArea(): String = supportDeviceArea
                    override fun getLanguage(): String = language
                })
                .build()
        )

        // ==================== Additional Initialization ====================
        CameraSDKInit.initLinkBridge()
        CameraSDKInit.initPosition(positionId)
        CameraSDKInit.initH5UrlParams(this, appRequestDomain)
    }

    private fun getDeviceUniqueId(): String {
        // Return device unique identifier, recommend using AndroidId or custom UUID
        return Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
    }
}

6. Feature APIs

6.1 Device Provisioning

Provides device provisioning flow with UI:

import com.lumi.moudle.access.LumiAccessSDKManager
import com.lumi.moudle.access.callback.LumiResultCallBack
import java.lang.ref.WeakReference

/**
 * Start Device Provisioning Page
 * 
 * @param deviceModel Device model, e.g., "lumi.camera.agl002"
 * @param positionId Position ID
 * @param coapServer CoAP server address
 */
fun startDeviceAccess(deviceModel: String, positionId: String, coapServer: String) {
    // Set provisioning information
    LumiAccessSDKManager.getInstance().setAccessInfo(positionId, coapServer)

    // Start provisioning page
    LumiAccessSDKManager.getInstance().gotoAccessConfigModule(
        this,
        deviceModel,
        object : LumiResultCallBack {

            override fun success(activity: WeakReference<Activity>, message: String?) {
                // Provisioning successful
                activity.get()?.finish()

                // Parse device information
                message?.let {
                    val deviceInfo = JSON.parseObject(it)
                    val did = deviceInfo.getString("did")          // Device ID
                    val model = deviceInfo.getString("model")      // Device model
                    val deviceName = deviceInfo.getString("deviceName")  // Device name

                    // After successful provisioning, directly open camera control page
                    openCameraPage(did, model, deviceName)
                }
            }

            override fun fail(errorCode: Int?, errorMessage: String?) {
                // Provisioning failed
                Log.e("Access", "Provisioning failed: code=$errorCode, msg=$errorMessage")
                Toast.makeText(this@YourActivity, "Provisioning failed: $errorMessage", Toast.LENGTH_SHORT).show()
            }
        }
    )
}

6.2 Camera Control Page

Open camera real-time preview and control page:

import com.lumi.module.camera.api.LumiCameraSDK

/**
 * Open Camera Control Page
 * 
 * @param deviceId Device ID (did)
 * @param deviceModel Device model
 * @param deviceName Device name (for page title display)
 */
fun openCameraPage(deviceId: String, deviceModel: String, deviceName: String) {
    LumiCameraSDK.getRouter().startCameraPage(
        deviceModel,    // Device model
        deviceId,       // Device ID
        deviceName,     // Device name
        false           // Whether to hide title bar
    )
}

Complete Usage Example

class CameraListActivity : AppCompatActivity() {

    // Device list data
    private val cameraList = mutableListOf<CameraDevice>()

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

        // Provisioning button
        findViewById<Button>(R.id.btn_add_camera).setOnClickListener {
            // Open G4 Doorbell provisioning
            startDeviceAccess(
                deviceModel = "lumi.camera.agl002",
                positionId = "your_position_id",
                coapServer = "aiot-coap.aqara.cn"
            )
        }

        // Device list click
        recyclerView.setOnItemClickListener { position ->
            val camera = cameraList[position]
            openCameraPage(
                deviceId = camera.did,
                deviceModel = camera.model,
                deviceName = camera.name
            )
        }
    }

    private fun startDeviceAccess(deviceModel: String, positionId: String, coapServer: String) {
        LumiAccessSDKManager.getInstance().setAccessInfo(positionId, coapServer)
        LumiAccessSDKManager.getInstance().gotoAccessConfigModule(
            this,
            deviceModel,
            object : LumiResultCallBack {
                override fun success(activity: WeakReference<Activity>, message: String?) {
                    activity.get()?.finish()
                    message?.let {
                        val info = JSON.parseObject(it)
                        // Add to list
                        cameraList.add(CameraDevice(
                            did = info.getString("did"),
                            model = info.getString("model"),
                            name = info.getString("deviceName")
                        ))
                        // Refresh list
                        adapter.notifyDataSetChanged()
                    }
                }

                override fun fail(errorCode: Int?, errorMessage: String?) {
                    Toast.makeText(this@CameraListActivity, "Add failed", Toast.LENGTH_SHORT).show()
                }
            }
        )
    }

    private fun openCameraPage(deviceId: String, deviceModel: String, deviceName: String) {
        LumiCameraSDK.getRouter().startCameraPage(deviceModel, deviceId, deviceName, false)
    }

    data class CameraDevice(
        val did: String,
        val model: String,
        val name: String
    )
}

7. Supported Device List

Product Name Device Model Region Product Type
Smart Camera G3 lumi.camera.gwpagl01 Mainland China Gateway Camera
Camera Hub G3 lumi.camera.gwpgl1 Overseas Gateway Camera
Smart Camera G2H (Gateway) lumi.camera.gwagl02 Mainland China Gateway Camera
Smart Camera G2H lumi.camera.gwag03 Overseas Gateway Camera
Smart Camera G2H Pro lumi.camera.acn003 Mainland China Gateway Camera
Camera Hub G2H Pro lumi.camera.agl001 Overseas Gateway Camera
Smart Camera G100 lumi.camera.acn016 Mainland China Regular Camera
Camera G100 lumi.camera.agl005 Overseas Regular Camera
Smart Camera G5 Pro (PoE Gateway) lumi.camera.acn009 Mainland China PoE Wired
Camera Hub G5 Pro (PoE) lumi.camera.acn010 Overseas PoE Wired
Smart Camera G5 Pro (Wi-Fi Gateway) lumi.camera.agl003 Mainland China Wi-Fi
Camera Hub G5 Pro (Wi-Fi) lumi.camera.agl004 Overseas Wi-Fi
Smart Video Doorbell G4 lumi.camera.acn005 Mainland China Video Doorbell
Smart Video Doorbell G4 lumi.camera.agl002 Overseas Video Doorbell
Smart Video Doorbell G410 (Gateway) lumi.camera.acn017 Mainland China Video Doorbell
Doorbell Camera Hub G410 lumi.camera.agl006 Overseas Video Doorbell
Smart Camera E1 lumi.camera.acn007 Mainland China Regular Camera
Camera E1 lumi.camera.acn006 Overseas Regular Camera
Smart Camera G350 lumi.camera.agl010 Overseas -
Smart Camera G400 lumi.camera.agl013 Overseas -

💡 For support of more device models, please contact Aqara Business to obtain the corresponding device resource package.


8. Server Domain Configuration

Select the corresponding server domain based on your service region:

8.1 API Request Domain (appRequestDomain)

Region Domain
Mainland China https://aiot-rpc.aqara.cn
United States https://aiot-rpc-usa.aqara.com
Europe https://rpc-eu.aqara.com
South Korea https://rpc-kr.aqara.com
Russia https://rpc-ru.aqara.com

8.2 CoAP Server (coapServer)

Region Domain
Mainland China aiot-coap.aqara.cn
United States coap-usa.aqara.com
Europe coap-eu.aqara.com
South Korea coap-kr.aqara.com
Russia coap-ru.aqara.com

8.3 CDN Resource Domain

Type Domain
H5 Page https://cdn.aqara.com/cdn/app/mainland/h5/index.html#
Image Resources https://cdn.aqara.com/cdn/common/mainland/prd/statics/default

⚠️ Important: appRequestDomain and coapServer must be used together, otherwise device provisioning may fail.


9. FAQ

Q1: Initialization failed with "appId invalid" error

Cause: Incorrect AppId or AppKey configuration.

Solution:

  1. Verify that AppId and AppKey are correctly obtained from Aqara Developer Platform
  2. Check if the package name matches the one used during application
  3. Confirm that the account has permissions for the corresponding device model

Q2: Provisioning failed, device not found

Cause: Network configuration or permission issues.

Solution:

  1. Ensure the phone is connected to 2.4GHz WiFi (some devices do not support 5GHz)
  2. Check if location permission has been granted
  3. Ensure the device has entered provisioning mode
  4. Verify that coapServer configuration is correct

Q3: Camera page shows blank screen

Cause: RN plugin not loaded correctly.

Solution:

  1. Ensure CameraSDKInit.initRnExtensions() is called correctly
  2. Check if the resource files for the corresponding device model exist in the assets/deviceRes directory
  3. Confirm that RMSDK_K_LOCAL_RES is configured as "true"

Q4: No video in real-time preview

Cause: Network or device issues.

Solution:

  1. Check if the device is online
  2. Verify that the phone network is normal
  3. Check if userId and token are valid
  4. Try restarting the device

Q5: Compilation error "Duplicate class"

Cause: Dependency library version conflicts.

Solution: Add the following to build.gradle:

configurations.all {
    resolutionStrategy {
        force 'com.alibaba:arouter-api:1.5.2'
        // Other conflicting libraries...
    }
}

Q6: Android 14 error "Receiver not allowed to receive"

Cause: Android 14 has new restrictions on broadcast receivers.

Solution: Ensure you are using the latest version of the SDK, which has fixed this issue.


Technical Support

If you have any questions, please contact us through the following channels:


© 2025 Aqara. All rights reserved.

lumi LogoCopyright © 2023 Lumi United Technology Co., Ltd. all right reserved,powered by GitbookFile Modify: 2025-12-22 16:35:12

results matching ""

    No results matching ""