精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

CXR SDK實戰(zhàn)指南:跨設(shè)備AR應(yīng)用開發(fā) 原創(chuàng)

發(fā)布于 2025-10-16 22:21
瀏覽
0收藏

CXR SDK實戰(zhàn)指南:跨設(shè)備AR應(yīng)用開發(fā)

前言

當"屏幕"從二維平面擴展到三維空間,當應(yīng)用不再被框在 16:9 的矩形里,而是漂浮在客廳、會議室甚至你的視野中央,開發(fā)范式也隨之被重塑。在這個過程中,CXR SDK為開發(fā)者提供了完整的跨設(shè)備AR應(yīng)用開發(fā)解決方案:

  • CXR-M(移動端SDK):用于移動設(shè)備(如手機、平板)與AR眼鏡進行通信和控制的軟件開發(fā)工具包
  • CXR-S(眼鏡端SDK):用于AR眼鏡設(shè)備端實現(xiàn)功能和與移動端通信的軟件開發(fā)工具包

過去幾年,我們見證了AR眼鏡從概念走進生產(chǎn)線,也目睹了開發(fā)者面對新硬件時的手足無措:環(huán)境配置碎片化、跨設(shè)備協(xié)同復雜、性能瓶頸隱蔽、調(diào)試手段匱乏。CXR SDK為開發(fā)者提供了完整的解決方案:

  • CXR-M(移動端)確保移動設(shè)備能高效地發(fā)送指令和接收數(shù)據(jù)
  • CXR-S(眼鏡端)負責眼鏡端的功能實現(xiàn)和與移動端的無縫通信

你將從本文獲得什么

  • 一條可落地的復現(xiàn)路線(Windows 10 環(huán)境)
  • CXR-M移動端與CXR-S眼鏡端SDK的正確集成方式
  • 手機與AR眼鏡跨設(shè)備通信的最小可用Demo
  • 工程化與性能優(yōu)化清單,以及我在復現(xiàn)過程中的取舍與思考

注:本文將詳細介紹如何正確使用CXR SDK(包括CXR-M和CXR-S)構(gòu)建跨設(shè)備AR應(yīng)用,確保技術(shù)描述的準確性和專業(yè)性

我的開發(fā)思路與取舍

在接觸AR設(shè)備開發(fā)之前,我主要做傳統(tǒng)移動端開發(fā)。跨設(shè)備AR開發(fā)最大的挑戰(zhàn)不是技術(shù)復雜度,而是設(shè)備間的狀態(tài)同步通信協(xié)議的穩(wěn)定性。我的解決思路是:

  1. 先打通通信鏈路,再優(yōu)化渲染效果 - 確保命令能正確傳遞比視覺效果更重要
  2. 模塊化設(shè)計 - 將通信、渲染、UI分離,便于后續(xù)擴展和維護
  3. 漸進式實現(xiàn) - 從基礎(chǔ)功能開始,逐步擴展到復雜交互場景

環(huán)境配置與工具安裝

CXR SDK開發(fā)環(huán)境的搭建是一個簡單但關(guān)鍵的過程。首先需要安裝以下核心開發(fā)工具:

1、開發(fā)工具要求與安裝

Android Studio配置

  • 要求版本≥2023.1.1
  • 確保安裝了Kotlin插件
  • 配置Android SDK API Level 28+

Visual Studio Code配置(可選)

  • 推薦版本≥1.80.0
  • 推薦安裝以下擴展:Kotlin擴展、Android擴展

CXR SDK實戰(zhàn)指南:跨設(shè)備AR應(yīng)用開發(fā)-AI.x社區(qū)

3、項目創(chuàng)建方式

CXR SDK項目創(chuàng)建主要通過Android Studio完成:

  1. 打開Android Studio,點擊"新建項目"
  2. 選擇"Empty Activity"模板
  3. 填寫項目名稱、包名等基本信息
  4. 確保選擇Kotlin作為開發(fā)語言
  5. 點擊"完成"創(chuàng)建項目

項目結(jié)構(gòu)與開發(fā)流程

1、項目架構(gòu)詳解

一個標準的CXR SDK項目包含以下結(jié)構(gòu):

cxr-project/
├── app/
│   ├── build.gradle.kts    # 應(yīng)用依賴配置
│   ├── src/main/
│   │   ├── AndroidManifest.xml  # 權(quán)限配置
│   │   ├── java/com/example/cxrremotecontrol/  # Kotlin/Java源碼
│   │   └── res/           # 資源文件
├── build.gradle.kts       # 項目級Gradle配置
├── settings.gradle.kts    # 倉庫配置
└── gradle.properties      # Gradle屬性配置
## 開發(fā)與調(diào)試實戰(zhàn)

### 1、Android Studio調(diào)試技巧

**基礎(chǔ)調(diào)試配置**

1. 連接Android設(shè)備或啟動模擬器
2. 在Android Studio中點擊"運行"按鈕
3. 使用Logcat查看應(yīng)用日志

**常見調(diào)試命令**

```bash
# 查看設(shè)備日志
adb logcat | grep CXR

# 安裝應(yīng)用到設(shè)備
adb install -r app-debug.apk

# 清理應(yīng)用數(shù)據(jù)
adb shell pm clear com.example.cxrremotecontrol
open "https://jsar.netlify.app/playground?url=http://localhost:8080/main.xsml"

2、實時重載與熱更新

JSAR DevTools 把“寫代碼→看效果”壓縮成一秒循環(huán):只要一保存,場景自動熱重載,眼鏡里即刻呈現(xiàn)最新畫面;若腳本出錯,IDE 內(nèi)立刻用紅線標出堆棧,無需摘頭顯也能一次定位;同時左上角實時滾動幀率與內(nèi)存曲線,性能瓶頸一目了然。三大能力合一,讓 AR 開發(fā)像網(wǎng)頁刷新一樣簡單,真正“所寫即所見,所錯即所標,所慢即所顯”。

JSAR開發(fā)工具與CXR SDK的區(qū)別與關(guān)系

在開始實踐之前,我們需要明確JSAR開發(fā)工具鏈和CXR SDK的區(qū)別與關(guān)系:

JSAR開發(fā)工具鏈

  • 定位:一套完整的AR應(yīng)用開發(fā)環(huán)境和工具集
  • 主要功能:項目創(chuàng)建、代碼編輯、調(diào)試、預覽、打包部署
  • 使用場景:用于開發(fā)AR眼鏡上運行的應(yīng)用界面和交互邏輯

CXR SDK

  • 定位:兩套獨立的軟件開發(fā)工具包
    • CXR-M:移動端SDK,用于手機等移動設(shè)備
    • CXR-S:眼鏡端SDK,用于AR眼鏡設(shè)備
  • 主要功能:實現(xiàn)設(shè)備間通信、數(shù)據(jù)傳輸、功能調(diào)用
  • 使用場景:當需要手機與AR眼鏡之間進行通信和協(xié)同工作時使用

正確的技術(shù)選型

  • 開發(fā)AR眼鏡應(yīng)用界面:使用JSAR開發(fā)工具鏈
  • 實現(xiàn)手機控制AR眼鏡:使用CXR-M(移動端)+ CXR-S(眼鏡端)SDK組合

CXR-M SDK移動端集成實戰(zhàn)

基于官方文檔,我實現(xiàn)了完整的Android端集成。以下是關(guān)鍵配置和代碼:

Maven倉庫配置(settings.gradle.kts)

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven { url = uri("https://maven.rokid.com/repository/maven-public/") }
        google()
        mavenCentral()
    }
}

依賴配置(app/build.gradle.kts)

android {
    defaultConfig {
        minSdk = 28  // CXR-M SDK要求
        targetSdk = 34
    }
}

   dependencies {
    // CXR-M SDK核心依賴
    implementation("com.rokid.cxr:client-m:1.0.1-20250812.080117-2")
    
    // 網(wǎng)絡(luò)通信依賴(SDK推薦版本)
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    implementation("com.squareup.okhttp3:okhttp:4.9.3")
    implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
    implementation("com.squareup.okio:okio:2.8.0")
    implementation("com.google.code.gson:gson:2.10.1")
    
    // Kotlin標準庫
    implementation("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
}

權(quán)限配置(AndroidManifest.xml)

<!-- CXR-M SDK 所需權(quán)限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

動態(tài)權(quán)限申請(MainActivity.kt)

class MainActivity : AppCompatActivity() {
    companion object {
        private const val REQUEST_CODE_PERMISSIONS = 100
    }
    
    // Android 12+ 藍牙權(quán)限適配
    private val requiredPermissions = mutableListOf(
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.BLUETOOTH,
        Manifest.permission.BLUETOOTH_ADMIN
    ).apply {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            add(Manifest.permission.BLUETOOTH_SCAN)
            add(Manifest.permission.BLUETOOTH_CONNECT)
        }
    }.toTypedArray()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        requestPermissions()
        setupUI()
    }
    
    private fun requestPermissions() {
        val permissionsToRequest = requiredPermissions.filter {
            ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
        }
        
        if (permissionsToRequest.isNotEmpty()) {
            ActivityCompat.requestPermissions(this, permissionsToRequest.toTypedArray(), REQUEST_CODE_PERMISSIONS)
        }
    }
}

我的踩坑經(jīng)驗

  1. Android 12+ 藍牙權(quán)限變化:新增了 BLUETOOTH_SCANBLUETOOTH_CONNECT 權(quán)限,必須同時申請
  2. Maven倉庫訪問:國內(nèi)網(wǎng)絡(luò)可能需要配置代理,建議使用阿里云鏡像加速
  3. minSdk版本:CXR-M SDK要求最低API 28,低于此版本無法編譯
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    namespace = "com.example.jsarremotecontrol"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.example.jsarremotecontrol"
        minSdk = 28
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("com.google.android.material:material:1.11.0")
    implementation("androidx.constraintlayout:constraintlayout:2.1.4")
    
    // CXR-M SDK
    implementation("com.rokid.cxr:client-m:1.0.1-20250812.080117-2")
    
    // 網(wǎng)絡(luò)通信依賴
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
    implementation("com.squareup.okhttp3:okhttp:4.9.3")
    implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
    implementation("com.squareup.okio:okio:2.8.0")
    implementation("com.google.code.gson:gson:2.10.1")
    
    // Kotlin
    implementation("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
    
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}

CXR-M SDK移動端集成實戰(zhàn)

CXR-M SDK是專門為移動設(shè)備設(shè)計的SDK,用于與AR眼鏡進行通信和控制。以下是關(guān)鍵配置和代碼:

Maven倉庫配置(settings.gradle.kts)

pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        maven {
            url = uri("https://maven.rokid.com/repository/maven-public/")
        }
        mavenCentral()
    }
}

依賴導入(build.gradle.kts)

//...Other Settings
android {
    //...Other Settings
    defaultConfig {
        //...Other Settings
        minSdk = 28
    }
   //...Other Settings
    
}
dependencies {
   //...Other Settings
    implementation("com.rokid.cxr:client-m:1.0.1-20250812.080117-2")
}

跨設(shè)備通信Demo:手機與AR眼鏡協(xié)同工作

以下是一個完整的跨設(shè)備通信方案,包括移動端和眼鏡端的實現(xiàn):

A. 移動端UI與通信實現(xiàn)

布局文件(activity_main.xml)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="CXR 遠程控制"
        android:textSize="20sp"
        android:textStyle="bold"
        android:gravity="center"
        android:layout_marginBottom="24dp" />

    <TextView
        android:id="@+id/tv_angle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="旋轉(zhuǎn)角度: 0°"
        android:textSize="16sp"
        android:layout_marginBottom="8dp" />

    <SeekBar
        android:id="@+id/seek_angle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="360"
        android:layout_marginBottom="16dp" />

    <Button
        android:id="@+id/btn_connect"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="連接設(shè)備"
        android:layout_marginBottom="8dp" />

    <Button
        android:id="@+id/btn_send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="發(fā)送角度"
        android:layout_marginBottom="16dp" />

    <TextView
        android:id="@+id/tv_status"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="狀態(tài): 未連接"
        android:textSize="14sp"
        android:background="#f0f0f0"
        android:padding="8dp" />

</LinearLayout>

CXR-M SDK通信實現(xiàn)(MainActivity.kt核心部分)

import com.rokid.cxr.client.m.CXRClientM
import com.rokid.cxr.client.m.listener.ConnectionListener
import com.rokid.cxr.client.m.listener.DataListener

class MainActivity : AppCompatActivity() {
    private lateinit var angleSeekBar: SeekBar
    private lateinit var angleTextView: TextView
    private lateinit var connectBtn: Button
    private lateinit var sendBtn: Button
    private lateinit var statusTextView: TextView
    
    private var cxrClient: CXRClientM? = null
    private var isConnected = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        initViews()
        setupListeners()
        initCXRClient()
        requestPermissions()
    }
    
    private fun initCXRClient() {
        // 初始化CXR-M SDK
        cxrClient = CXRClientM.getInstance()
        
        // 設(shè)置連接監(jiān)聽器
        cxrClient?.setConnectionListener(object : ConnectionListener {
            override fun onConnected() {
                runOnUiThread {
                    isConnected = true
                    connectBtn.text = "斷開連接"
                    updateStatus("已連接到眼鏡設(shè)備")
                }
            }
            
            override fun onDisconnected() {
                runOnUiThread {
                    isConnected = false
                    connectBtn.text = "連接設(shè)備"
                    updateStatus("設(shè)備已斷開連接")
                }
            }
            
            override fun onConnectionFailed(errorCode: Int, errorMessage: String) {
                runOnUiThread {
                    isConnected = false
                    connectBtn.text = "連接設(shè)備"
                    updateStatus("連接失敗: $errorMessage")
                }
            }
        })
        
        // 設(shè)置數(shù)據(jù)監(jiān)聽器
        cxrClient?.setDataListener(object : DataListener {
            override fun onDataReceived(data: ByteArray) {
                val message = String(data)
                runOnUiThread {
                    updateStatus("收到消息: $message")
                }
            }
        })
    }
    
    private fun setupListeners() {
        angleSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                angleTextView.text = "旋轉(zhuǎn)角度: ${progress}°"
            }
            override fun onStartTrackingTouch(seekBar: SeekBar?) {}
            override fun onStopTrackingTouch(seekBar: SeekBar?) {}
        })
        
        connectBtn.setOnClickListener {
            if (isConnected) {
                disconnect()
            } else {
                connect()
            }
        }
        
        sendBtn.setOnClickListener {
            sendAngle()
        }
    }
    
    private fun connect() {
        try {
            cxrClient?.connect()
            updateStatus("正在連接眼鏡設(shè)備...")
            
        } catch (e: Exception) {
            updateStatus("連接異常: ${e.message}")
        }
    }
    
    private fun sendAngle() {
        if (!isConnected) {
            updateStatus("請先連接設(shè)備")
            return
        }
        
        val angle = angleSeekBar.progress
        val message = """{"cmd":"rotate","y":$angle,"timestamp":${System.currentTimeMillis()}}"""
        
        webSocket?.send(message)
        updateStatus("已發(fā)送角度: ${angle}°")
    }
    
    private fun updateStatus(message: String) {
        statusTextView.text = "狀態(tài): $message"
    }
}

Android應(yīng)用運行界面,顯示滑桿、連接按鈕、狀態(tài)文本:

CXR SDK實戰(zhàn)指南:跨設(shè)備AR應(yīng)用開發(fā)-AI.x社區(qū)CXR SDK實戰(zhàn)指南:跨設(shè)備AR應(yīng)用開發(fā)-AI.x社區(qū)

B. 眼鏡端實現(xiàn)(使用CXR-S SDK)

CXR-S SDK眼鏡端集成配置

// settings.gradle.kts
pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        maven {
            url = uri("https://maven.rokid.com/repository/maven-public/")
        }
        mavenCentral()
    }
}

// app/build.gradle.kts
dependencies {
    implementation("com.rokid.cxr:cxr-service-bridge:1.0-20250519.061355-45")
}

android {
    defaultConfig {
        minSdk = 28
    }
}

CXR-S SDK眼鏡端實現(xiàn)代碼

import com.rokid.cxr.service.bridge.CXRServiceBridge
import com.rokid.cxr.service.bridge.listener.CXRConnectionListener
import com.rokid.cxr.service.bridge.listener.CXRDataListener

class CXRRemoteControlService : Service() {
    private lateinit var cxrBridge: CXRServiceBridge
    private lateinit var modelController: ModelController
    
    override fun onCreate() {
        super.onCreate()
        initCXRService()
        initModelController()
    }
    
    private fun initCXRService() {
        // 初始化CXR-S SDK
        cxrBridge = CXRServiceBridge.getInstance()
        
        // 設(shè)置連接監(jiān)聽器
        cxrBridge.setConnectionListener(object : CXRConnectionListener {
            override fun onConnected() {
                Log.d("CXRService", "已連接到移動端")
                // 發(fā)送連接成功消息給移動端
                cxrBridge.sendData("眼鏡端已就緒".toByteArray())
            }
            
            override fun onDisconnected() {
                Log.d("CXRService", "與移動端斷開連接")
            }
        })
        
        // 設(shè)置數(shù)據(jù)監(jiān)聽器
        cxrBridge.setDataListener(object : CXRDataListener {
            override fun onDataReceived(data: ByteArray) {
                try {
                    val message = String(data)
                    Log.d("CXRService", "收到消息: $message")
                    
                    // 解析消息并執(zhí)行相應(yīng)操作
                    if (message.startsWith("rotate:")) {
                        val angle = message.substring(7).toFloatOrNull() ?: 0f
                        modelController.rotateToAngle(angle)
                        
                        // 發(fā)送確認消息給移動端
                        cxrBridge.sendData("已設(shè)置角度: $angle".toByteArray())
                    }
                } catch (e: Exception) {
                    Log.e("CXRService", "消息處理失敗: ${e.message}")
                }
            }
        })
        
        // 啟動服務(wù)
        cxrBridge.start()
    }
    
    private fun initModelController() {
        // 初始化模型控制器,用于控制AR場景中的3D模型
        modelController = ModelController()
    }
    
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
    
    override fun onDestroy() {
        super.onDestroy()
        // 停止CXR服務(wù)
        cxrBridge.stop()
    }
}
  private wsManager: WebSocketManager
  private modelController: ModelController
  private isRunning = false

  constructor() {
    this.scene = this.createScene()
    this.wsManager = new WebSocketManager('ws://192.168.1.100:12345/ctrl')
    this.modelController = new ModelController(this.scene)
  }

  async start(): Promise<void> {
    try {
      console.log('啟動JSAR遠程控制應(yīng)用...')
      
      // 加載3D模型
      await this.modelController.loadModel('models/robot.glb')
      
      // 連接WebSocket
      await this.wsManager.connect()
      
      // 設(shè)置消息處理
      this.wsManager.onMessage((data) => {
        this.handleMessage(data)
      })
      
      // 啟動渲染循環(huán)
      this.startRenderLoop()
      
      this.isRunning = true
      console.log('應(yīng)用啟動成功')
      
    } catch (error) {
      console.error('應(yīng)用啟動失敗:', error)
    }
  }

  private handleMessage(data: any) {
    console.log('處理消息:', data)
    
    if (data.cmd === 'rotate' && typeof data.y === 'number') {
      this.modelController.rotateToAngle(data.y)
    }
  }

  private startRenderLoop() {
    const render = () => {
      if (this.isRunning) {
        this.modelController.update()
        requestAnimationFrame(render)
      }
    }
    render()
  }
}

// 應(yīng)用入口
async function main() {
  const app = new JSARRemoteControlApp()
  
  try {
    await app.start()
  } catch (error) {
    console.error('應(yīng)用運行失敗:', error)
  }
}

main().catch(console.error)

// 注意:上述代碼是使用WebSocket作為通信方式的簡化實現(xiàn)
// 在實際應(yīng)用中,當需要與AR眼鏡設(shè)備進行通信時,應(yīng)使用CXR-S SDK(眼鏡端)和CXR-M SDK(移動端)的組合方案

CXR SDK實戰(zhàn)指南:跨設(shè)備AR應(yīng)用開發(fā)-AI.x社區(qū)CXR SDK實戰(zhàn)指南:跨設(shè)備AR應(yīng)用開發(fā)-AI.x社區(qū)

C. CXR SDK通信協(xié)議設(shè)計與實現(xiàn)

CXR SDK設(shè)備間通信協(xié)議

{
  "cmd": "rotate",           // 命令類型
  "y": 180,                 // 旋轉(zhuǎn)角度 (0-360)
  "timestamp": 1640995200000, // 時間戳
  "seq": 12345              // 序列號(可選)
}

通信實現(xiàn)流程

  1. 移動端通過CXR-M SDK與眼鏡端建立連接
  2. 移動端發(fā)送控制指令到眼鏡端
  3. 眼鏡端通過CXR-S SDK接收指令并執(zhí)行相應(yīng)操作
  4. 眼鏡端返回執(zhí)行結(jié)果給移動端

數(shù)據(jù)傳輸優(yōu)化

  1. 使用二進制格式傳輸數(shù)據(jù),提高傳輸效率
  2. 實現(xiàn)數(shù)據(jù)壓縮,減少傳輸數(shù)據(jù)量
  3. 采用請求-響應(yīng)機制,確保數(shù)據(jù)可靠傳輸

D. 開發(fā)階段通信協(xié)議設(shè)計與魯棒性思考

消息協(xié)議設(shè)計

{
  "cmd": "rotate",           // 命令類型
  "y": 180,                 // 旋轉(zhuǎn)角度 (0-360)
  "timestamp": 1640995200000, // 時間戳
  "seq": 12345              // 序列號(可選)
}

我的設(shè)計原則

  1. 極簡JSON協(xié)議:先保證互通,后續(xù)可優(yōu)化為二進制格式
  2. 時間戳防重:避免網(wǎng)絡(luò)延遲導致的重復命令
  3. 序列號保序:確保命令按正確順序執(zhí)行
  4. 錯誤處理:所有網(wǎng)絡(luò)操作都有超時和重試機制

性能優(yōu)化策略

  1. 命令去抖:相同角度命令在100ms內(nèi)只執(zhí)行一次
  2. 平滑插值:模型旋轉(zhuǎn)使用緩動函數(shù),避免突兀跳躍
  3. 連接池管理:WebSocket連接復用,減少握手開銷
  4. 內(nèi)存管理:及時清理不用的3D資源,避免內(nèi)存泄漏

我的踩坑經(jīng)驗

  1. Android WebSocket超時:OkHttp默認超時時間過短,需要設(shè)置為0(無限超時)
  2. JSAR場景API變化:官方API可能更新,需要根據(jù)最新文檔調(diào)整代碼
  3. 網(wǎng)絡(luò)地址配置:開發(fā)時用localhost,真機測試需要改為實際IP地址
  4. 權(quán)限時序:Android權(quán)限申請必須在WebSocket連接之前完成

CXR SDK實戰(zhàn)指南:跨設(shè)備AR應(yīng)用開發(fā)-AI.x社區(qū)

工程化與性能優(yōu)化實戰(zhàn)

1、CXR SDK依賴管理

Gradle版本鎖定策略

// gradle/libs.versions.toml
[versions]
kotlin = "2.1.0"
androidx-appcompat = "1.6.1"
androidx-constraintlayout = "2.1.4"
cxr-m = "1.0.1-20250812.080117-2"
cxr-s = "1.0-20250519.061355-45"

[libraries]
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" }
cxr-m-sdk = { group = "com.rokid.cxr", name = "client-m", version.ref = "cxr-m" }
cxr-s-sdk = { group = "com.rokid.cxr", name = "cxr-service-bridge", version.ref = "cxr-s" }

依賴管理最佳實踐:統(tǒng)一管理版本號,避免依賴沖突。使用libs.versions.toml文件集中管理所有依賴版本,確保CXR SDK與其他庫的兼容性。

2、性能監(jiān)控與優(yōu)化

CXR SDK性能監(jiān)控

import android.util.Log
import java.util.concurrent.TimeUnit

class CXRPerformanceMonitor {
    private var startTime = 0L
    private var messageCount = 0
    private var totalLatency = 0L
    
    fun start() {
        startTime = System.currentTimeMillis()
    }
    
    fun recordMessageReceived() {
        messageCount++
    }
    
    fun recordLatency(latencyMs: Long) {
        totalLatency += latencyMs
    }
    
    fun logPerformanceMetrics() {
        val elapsedTime = System.currentTimeMillis() - startTime
        val messagesPerSecond = if (elapsedTime > 0) {
            (messageCount * 1000.0 / elapsedTime).toInt()
        } else 0
        
        val avgLatency = if (messageCount > 0) {
            totalLatency / messageCount
        } else 0
        
        Log.d("CXRPerformance", "消息吞吐量: $messagesPerSecond 條/秒")
        Log.d("CXRPerformance", "平均延遲: $avgLatency ms")
    }
}

3、CXR SDK錯誤處理與容錯機制

設(shè)備連接錯誤處理

import android.os.Handler
import android.os.Looper
import android.util.Log
import com.rokid.cxr.client.m.CXRClientM

class CXRFaultToleranceManager {
    private var cxrClient: CXRClientM? = null
    private var reconnectAttempts = 0
    private val maxReconnectAttempts = 5
    private val baseReconnectDelay = 1000L
    private val commandQueue = mutableListOf<ByteArray>()
    private var isOfflineMode = false
    
    constructor(cxrClient: CXRClientM) {
        this.cxrClient = cxrClient
    }
    
    fun handleConnectionFailure(errorCode: Int, errorMessage: String) {
        Log.e("CXRConnection", "連接失敗: $errorMessage (錯誤碼: $errorCode)")
        
        when (errorCode) {
            1001 -> Log.d("CXRConnection", "設(shè)備未找到,請確保眼鏡設(shè)備已開啟")
            1002 -> Log.d("CXRConnection", "藍牙權(quán)限不足,請檢查應(yīng)用權(quán)限")
            1003 -> Log.d("CXRConnection", "網(wǎng)絡(luò)連接超時,請檢查網(wǎng)絡(luò)設(shè)置")
            else -> Log.d("CXRConnection", "未知錯誤,請稍后重試")
        }
        
        attemptReconnect()
    }
    
    private fun attemptReconnect() {
        if (reconnectAttempts < maxReconnectAttempts) {
            reconnectAttempts++
            val delay = baseReconnectDelay * (1 shl reconnectAttempts) // 指數(shù)退避
            
            Log.d("CXRConnection", "嘗試重連 ($reconnectAttempts/$maxReconnectAttempts),延遲 ${delay}ms")
            
            Handler(Looper.getMainLooper()).postDelayed({
                cxrClient?.connect()
            }, delay)
        } else {
            // 達到最大重試次數(shù),切換到離線模式
            switchToOfflineMode()
        }
    }
    
    private fun switchToOfflineMode() {
        isOfflineMode = true
        Log.w("CXRConnection", "已切換到離線模式,命令將被緩存")
    }
    
    fun sendDataWithRetry(data: ByteArray) {
        if (isOfflineMode) {
            // 離線模式下緩存命令
            commandQueue.add(data)
            Log.d("CXRConnection", "命令已緩存,等待網(wǎng)絡(luò)恢復")
        } else {
            try {
                cxrClient?.sendData(data)
            } catch (e: Exception) {
                Log.e("CXRConnection", "發(fā)送數(shù)據(jù)失敗: ${e.message}")
                // 緩存失敗的命令
                commandQueue.add(data)
            }
        }
    }
    
    fun onConnectionRestored() {
        isOfflineMode = false
        reconnectAttempts = 0
        Log.d("CXRConnection", "連接已恢復,正在發(fā)送緩存的命令")
        
        // 發(fā)送緩存的命令
        while (commandQueue.isNotEmpty()) {
            val command = commandQueue.removeAt(0)
            try {
                cxrClient?.sendData(command)
                Log.d("CXRConnection", "已發(fā)送緩存命令")
            } catch (e: Exception) {
                Log.e("CXRConnection", "發(fā)送緩存命令失敗: ${e.message}")
            }
        }
    }
}

我的容錯策略

  1. 指數(shù)退避重連:避免頻繁重連造成資源浪費
  2. 命令緩存機制:網(wǎng)絡(luò)中斷時緩存用戶操作
  3. 降級方案:關(guān)鍵功能不可用時提供替代方案
  4. 用戶反饋:及時告知用戶當前狀態(tài)和問題

4、CXR SDK內(nèi)存管理與資源優(yōu)化

在AR應(yīng)用開發(fā)中,內(nèi)存管理至關(guān)重要,特別是對于資源受限的眼鏡設(shè)備。以下是使用CXR SDK時的內(nèi)存優(yōu)化策略:

資源生命周期管理

import android.util.Log
import java.util.WeakHashMap
import java.lang.ref.WeakReference
import com.rokid.cxr.client.m.CXRClientM

class CXRResourceManager {
    private val cxrClient: CXRClientM
    private val activeResources = WeakHashMap<String, WeakReference<Any>>()
    private val resourceUsageThreshold = 80 // 80%內(nèi)存使用率閾值
    private val tag = "CXRResourceManager"
    
    constructor(cxrClient: CXRClientM) {
        this.cxrClient = cxrClient
    }
    
    fun registerResource(resourceId: String, resource: Any) {
        activeResources[resourceId] = WeakReference(resource)
        
        // 檢查內(nèi)存使用情況
        if (isMemoryUsageHigh()) {
            Log.w(tag, "內(nèi)存使用率過高,觸發(fā)資源清理")
            cleanupUnusedResources()
        }
    }
    
    fun releaseResource(resourceId: String) {
        val resourceRef = activeResources.remove(resourceId)
        if (resourceRef != null) {
            val resource = resourceRef.get()
            if (resource != null) {
                // 釋放特定資源
                when (resource) {
                    is ByteArray -> { /* 處理字節(jié)數(shù)組資源 */ }
                    is AutoCloseable -> {
                        try {
                            resource.close()
                            Log.d(tag, "資源已關(guān)閉: $resourceId")
                        } catch (e: Exception) {
                            Log.e(tag, "關(guān)閉資源失敗: ${e.message}")
                        }
                    }
                }
            }
        }
    }
    
    fun cleanupUnusedResources() {
        val keysToRemove = mutableListOf<String>()
        
        for ((key, ref) in activeResources) {
            if (ref.get() == null) {
                keysToRemove.add(key)
                Log.d(tag, "清理未使用資源: $key")
            }
        }
        
        keysToRemove.forEach {
            activeResources.remove(it)
        }
    }
    
    private fun isMemoryUsageHigh(): Boolean {
        val runtime = Runtime.getRuntime()
        val usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024
        val maxMemory = runtime.maxMemory() / 1024 / 1024
        val usagePercentage = (usedMemory * 100) / maxMemory
        
        Log.d(tag, "內(nèi)存使用: $usedMemory MB / $maxMemory MB ($usagePercentage%)")
        
        return usagePercentage > resourceUsageThreshold
    }
    
    fun onDeviceDisconnect() {
        // 設(shè)備斷開連接時釋放所有資源
        Log.d(tag, "設(shè)備斷開連接,釋放所有資源")
        activeResources.clear()
    }
}

踩坑指南與最佳實踐

1、常見問題與解決方案

問題1:Android權(quán)限申請失敗

// 錯誤做法:一次性申請所有權(quán)限
ActivityCompat.requestPermissions(this, allPermissions, REQUEST_CODE)

// 正確做法:分批申請,先申請關(guān)鍵權(quán)限
val criticalPermissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
val optionalPermissions = arrayOf(Manifest.permission.BLUETOOTH_SCAN)

ActivityCompat.requestPermissions(this, criticalPermissions, REQUEST_CODE_CRITICAL)
// 關(guān)鍵權(quán)限通過后再申請可選權(quán)限

問題2:WebSocket連接不穩(wěn)定

// 錯誤做法:連接失敗后立即重試
private fun connect() {
    webSocket = client.newWebSocket(request, listener)
}

// 正確做法:添加心跳檢測和重連機制
private fun startHeartbeat() {
    heartbeatTimer = Timer()
    heartbeatTimer.scheduleAtFixedRate(object : TimerTask() {
        override fun run() {
            if (isConnected) {
                webSocket?.send("""{"type":"ping"}""")
            }
        }
    }, 0, 30000) // 30秒心跳
}

問題3:JSAR場景API變化

// 錯誤做法:硬編碼API調(diào)用
const model = scene.createEntity('model')

// 正確做法:添加API兼容性檢查
function createEntityCompat(scene: any, id: string) {
    if (typeof scene.createEntity === 'function') {
        return scene.createEntity(id)
    } else if (typeof scene.addEntity === 'function') {
        return scene.addEntity(id)
    } else {
        throw new Error('不支持的場景API')
    }
}

2、調(diào)試技巧

Android端調(diào)試

// 使用Timber進行分級日志
Timber.d("WebSocket連接成功")
Timber.w("網(wǎng)絡(luò)延遲較高: ${latency}ms")
Timber.e("連接失敗", exception)

// 使用Stetho進行網(wǎng)絡(luò)調(diào)試
if (BuildConfig.DEBUG) {
    Stetho.initializeWithDefaults(this)
}

JSAR端調(diào)試

// 添加調(diào)試面板
class DebugPanel {
    private panel: HTMLElement
    
    constructor() {
        this.panel = document.createElement('div')
        this.panel.style.cssText = `
            position: fixed; top: 10px; right: 10px;
            background: rgba(0,0,0,0.8); color: white;
            padding: 10px; font-family: monospace;
            z-index: 9999;
        `
        document.body.appendChild(this.panel)
    }
    
    update(fps: number, memory: number, connections: number) {
        this.panel.innerHTML = `
            FPS: ${fps}<br>
            Memory: ${memory}MB<br>
            Connections: ${connections}
        `
    }
}

3、測試策略

單元測試

@Test
fun testMessageParsing() {
    val json = """{"cmd":"rotate","y":180,"timestamp":1640995200000}"""
    val message = MessageParser.parse(json)
    
    assertEquals("rotate", message.cmd)
    assertEquals(180, message.y)
    assertTrue(message.timestamp > 0)
}

集成測試

@Test
fun testCrossDeviceCommunication() {
    // 啟動WebSocket服務(wù)器
    val server = startTestServer()
    
    // 連接Android客戶端
    val androidClient = connectAndroidClient()
    
    // 連接JSAR客戶端
    val jsarClient = connectJSARClient()
    
    // 發(fā)送測試消息
    androidClient.send("""{"cmd":"rotate","y":90}""")
    
    // 驗證JSAR端收到消息
    val receivedMessage = jsarClient.waitForMessage()
    assertEquals(90, receivedMessage.y)
}

總結(jié)與展望

在本實戰(zhàn)指南中,我們詳細探討了如何使用CXR SDK開發(fā)跨設(shè)備AR應(yīng)用,從環(huán)境搭建到性能優(yōu)化,提供了一套完整的開發(fā)流程和最佳實踐。通過本文的學習,你應(yīng)該能夠:

  1. 快速上手CXR SDK:掌握CXR-M移動端SDK和CXR-S眼鏡端SDK的集成方法
  2. 實現(xiàn)跨設(shè)備通信:建立移動端與眼鏡端之間穩(wěn)定高效的數(shù)據(jù)傳輸機制
  3. 優(yōu)化應(yīng)用性能:通過專業(yè)的工程化手段提升應(yīng)用的響應(yīng)速度和資源利用效率
  4. 構(gòu)建穩(wěn)健的AR應(yīng)用:應(yīng)用錯誤處理、容錯機制和內(nèi)存管理策略確保應(yīng)用穩(wěn)定性

CXR SDK為開發(fā)者提供了一套完整、高效的AR應(yīng)用開發(fā)解決方案,其優(yōu)勢在于:

  1. 原生性能:專為AR場景優(yōu)化的底層實現(xiàn),提供卓越的運行效率
  2. 穩(wěn)定可靠:經(jīng)過大規(guī)模實踐驗證的SDK,確保應(yīng)用在各種場景下的穩(wěn)定性
  3. 易用性:簡潔明了的API設(shè)計,降低開發(fā)門檻,提高開發(fā)效率
  4. 全面支持:完整覆蓋移動端和眼鏡端的開發(fā)需求,實現(xiàn)無縫跨設(shè)備交互

未來,CXR SDK將繼續(xù)演進,提供更多高級特性,包括更豐富的AR交互能力、更強大的計算機視覺功能和更智能的設(shè)備協(xié)同機制。我們期待與開發(fā)者一起,共同推動AR技術(shù)在各行業(yè)的創(chuàng)新應(yīng)用。

希望本指南能夠成為你開發(fā)跨設(shè)備AR應(yīng)用的得力助手,祝你在AR開發(fā)之路上取得更多創(chuàng)新成果!

附錄

完整項目結(jié)構(gòu)

CXR-Demo/
├── android-mobile-app/      # 移動端Android應(yīng)用(CXR-M SDK)
│   ├── app/
│   │   ├── src/main/java/com/rokid/demo/
│   │   │   ├── MainActivity.kt        # 主活動
│   │   │   ├── CXRClientManager.kt    # CXR-M客戶端管理
│   │   │   ├── CXRFaultToleranceManager.kt  # 容錯機制
│   │   │   ├── CXRResourceManager.kt  # 資源管理
│   │   │   └── utils/
│   │   ├── build.gradle.kts
│   │   └── settings.gradle.kts
│   └── build.gradle.kts
└── android-glasses-app/     # 眼鏡端Android應(yīng)用(CXR-S SDK)
    ├── app/
    │   ├── src/main/java/com/rokid/demo/
    │   │   ├── MainActivity.kt        # 主活動
    │   │   ├── CXRServiceBridge.kt    # CXR-S服務(wù)橋接
    │   │   ├── CXRRemoteControlService.kt # 遠程控制服務(wù)
    │   │   └── utils/
    │   ├── build.gradle.kts
    │   └── settings.gradle.kts
    └── build.gradle.kts

快速啟動命令

構(gòu)建和運行CXR SDK項目:

  1. 構(gòu)建移動端應(yīng)用
cd android-mobile-app
./gradlew assembleDebug
  1. 安裝移動端應(yīng)用
adb install app/build/outputs/apk/debug/app-debug.apk
  1. 構(gòu)建眼鏡端應(yīng)用
cd android-glasses-app
./gradlew assembleDebug
  1. 安裝眼鏡端應(yīng)用
adb install app/build/outputs/apk/debug/app-debug.apk

參考資源

  • CXR SDK 官方文檔

    • CXR-M 移動端 SDK 文檔:https://custom.rokid.com/prod/rokid_web/57e35cd3ae294d16b1b8fc8dcbb1b7c7/pc/cn/2786298057084a82b170bf725aef6b5d.html
    • CXR-S 眼鏡端 SDK 文檔:https://custom.rokid.com/prod/rokid_web/57e35cd3ae294d16b1b8fc8dcbb1b7c7/pc/cn/9d9dea4799ca4dd2a1176fedb075b6f2.html
  • 技術(shù)棧版本

    • Android SDK: API 28+
    • Kotlin: 2.1.0
    • CXR-M SDK: 1.0.1
    • CXR-S SDK: 1.0.1

免責聲明

本文中的代碼片段與模板僅為教學目的,實際接口以官方最新 SDK 為準。若版本變更,請以 Maven 倉庫與 Release Note 為權(quán)威來源。作者不對因使用本文內(nèi)容而產(chǎn)生的任何問題承擔責任。

?著作權(quán)歸作者所有,如需轉(zhuǎn)載,請注明出處,否則將追究法律責任
標簽
收藏
回復
舉報
回復
相關(guān)推薦
欧美wwwsss9999| 在线免费av网站| 国产精品综合色区在线观看| 亚洲免费人成在线视频观看| 虎白女粉嫩尤物福利视频| 黄视频在线播放| 国产福利精品导航| 日韩av电影在线网| 欧美日韩免费做爰视频| 久久99国产成人小视频| 91精品欧美综合在线观看最新| 欧美不卡在线播放| 精品美女在线观看视频在线观看| 99精品视频在线免费观看| 国产欧美日韩中文字幕在线| 国产第一页在线播放| 欧洲激情综合| 日韩成人黄色av| 樱花草www在线| 日日av拍夜夜添久久免费| 亚洲最快最全在线视频| 视频一区二区三区免费观看| 天堂国产一区二区三区| 极品少妇xxxx精品少妇| 欧美在线视频一区二区| 久草资源在线视频| 99久久夜色精品国产亚洲1000部| 精品小视频在线| 性xxxxxxxxx| 九九热这里有精品| 色狠狠色狠狠综合| 国产极品在线视频| 污污在线观看| 亚洲色图欧洲色图婷婷| 日韩片电影在线免费观看| 日日夜夜精品免费| 国产电影一区二区三区| 成人黄色免费片| 中国黄色一级视频| 日日噜噜夜夜狠狠视频欧美人| 78m国产成人精品视频| 麻豆一区二区三区精品视频| 午夜精品视频一区二区三区在线看| 亚洲午夜未删减在线观看 | 国产三级视频在线播放| 免费视频最近日韩| 国产精品久久久久久久9999| 欧美一区二区三区网站| 美女诱惑黄网站一区| 91sao在线观看国产| 日韩精品手机在线| 亚洲永久字幕| 日本久久久久久| 丁香六月婷婷综合| 久久九九国产| 国产成人啪精品视频免费网| 天堂网中文字幕| 久久狠狠婷婷| 国产精品99久久久久久久久久久久| 综合激情网五月| 天堂蜜桃91精品| 国产成+人+综合+亚洲欧洲| 中文字幕视频网| 久久久久综合| 国产精品视频1区| 在线播放成人av| 国内精品伊人久久久久影院对白| 成人黄色影片在线| av免费在线观看不卡| 国产成人精品亚洲日本在线桃色| 成人黄动漫网站免费| 色婷婷综合视频| 久久综合成人精品亚洲另类欧美| 久久久久欧美| 成年人在线观看网站| 国产精品高潮久久久久无| 男同互操gay射视频在线看| 欧洲成人综合网| 欧美日韩一二三四五区| 我看黄色一级片| 国产精品一区二区三区四区在线观看| 欧美成人r级一区二区三区| 亚洲欧美色图视频| 精品视频免费| 九色91av视频| 日韩在线播放中文字幕| 精品一二三四区| 国产成人免费观看| 国产三级电影在线| 一级特黄大欧美久久久| 男人透女人免费视频| 疯狂欧洲av久久成人av电影| 欧美精品一区二区三区很污很色的 | 国产宾馆实践打屁股91| 欧美日韩一区二区视频在线| 欧洲日本在线| 亚洲不卡av一区二区三区| 热久久精品免费视频| 天堂va在线高清一区| 亚洲人成五月天| 欧美成欧美va| 日韩精品一区第一页| 国产成人一区二区三区免费看| av电影在线播放高清免费观看| 亚洲综合在线视频| www.国产视频.com| 一区二区美女| 久久久久久高潮国产精品视| 午夜视频网站在线观看| 99这里只有久久精品视频| 一本一本久久a久久精品综合妖精| 2020av在线| 777奇米四色成人影色区| 我和岳m愉情xxxⅹ视频| 狠久久av成人天堂| 成人xvideos免费视频| 国产原创av在线| 亚洲一级电影视频| 亚洲精品在线视频播放| 欧洲美女日日| 国产成人综合亚洲91猫咪| 久久精品视频免费播放| 久久久久久久久久影院| 国产一区二区三区在线观看免费| 欧美成人在线免费观看| 欧美1—12sexvideos| 欧美视频精品在线观看| 蜜桃传媒一区二区亚洲av| 欧美婷婷在线| 成人信息集中地欧美| 嫩草研究院在线| 午夜精品福利一区二区三区蜜桃| 激情图片中文字幕| 日韩精品免费一区二区在线观看 | 少妇视频一区| 精品国产制服丝袜高跟| 卡通动漫亚洲综合| 国内精品伊人久久久久影院对白| 亚洲精品8mav| 福利视频亚洲| 尤物九九久久国产精品的分类| 日韩黄色在线播放| 99re6这里只有精品视频在线观看| www.欧美黄色| 91精品啪在线观看国产爱臀| 九九热这里只有精品免费看| 亚洲精品中文字幕有码专区| 中文字幕22页| 成人精品影视| 国产成人精品一区| 成人午夜电影在线观看| 在线区一区二视频| 一级黄色录像毛片| 日韩电影在线一区二区三区| 日本视频一区在线观看| 精品三区视频| 三级精品视频久久久久| 自拍偷拍福利视频| 国产精品理论在线观看| 亚洲另类第一页| 天天综合网91| y111111国产精品久久婷婷| 性爱视频在线播放| 欧美成人免费网站| 日韩网红少妇无码视频香港| ww久久中文字幕| 杨幂毛片午夜性生毛片| 亚洲啊v在线观看| 97中文在线观看| xxxx在线视频| 国产丝袜高跟一区| 一本到在线视频| 亚洲伦理在线精品| 中国极品少妇videossexhd| 亚久久调教视频| 亚洲精品久久区二区三区蜜桃臀| 中文幕av一区二区三区佐山爱| 欧美精品在线第一页| 婷婷五月综合久久中文字幕| 在线观看一区二区精品视频| 熟女av一区二区| 成人av高清在线| 国产精品天天av精麻传媒| 99久久视频| 国模精品娜娜一二三区| 欧美在线va视频| 欧美人在线视频| 激情小说 在线视频| 91精品国产综合久久香蕉的特点| 伊人365影院| 国产精品麻豆99久久久久久| 男人的天堂免费| 日韩在线观看一区二区| 99re6这里有精品热视频| 免费看成人吃奶视频在线| 成人福利视频网| 中文字幕在线高清| 久久精品夜夜夜夜夜久久| 天堂网在线资源| 在线播放欧美女士性生活| 国产性猛交普通话对白| 欧美国产一区在线| 成年女人免费视频| 蜜乳av一区二区三区| heyzo亚洲| 亚洲一级淫片| 欧美精品在线一区| 伊人久久大香线蕉av超碰| 国产成人高清激情视频在线观看 | 亚洲第一中文av| 91久久亚洲| 综合一区中文字幕| 国产精品亚洲二区| 国产精品一区二区av| 四虎国产精品免费久久| 国产91成人在在线播放| 怡红院av在线| 中文字幕免费精品一区| 日韩在线无毛| 精品国产乱码久久| 国产美女主播在线观看| 欧美视频完全免费看| 四虎成人永久免费视频| 亚洲午夜免费电影| 成人h猎奇视频网站| 欧美另类高清videos的特点| 亚洲成在人线免费| 欧美xxxooo| 久久精品视频免费| 亚洲久久久久久| 国产精品夜夜嗨| 中文字幕一区久久| 麻豆国产欧美日韩综合精品二区 | 九色porny丨国产首页在线| 久久久久99精品久久久久| 第一福利在线| 亚洲美女精品成人在线视频| 色香蕉在线视频| 精品日韩一区二区| 亚洲女人18毛片水真多| 日韩一级黄色大片| 精品国产伦一区二区三| 91精品免费在线| 99在线小视频| 欧美xxxxxxxxx| 性猛交xxxx乱大交孕妇印度| 91精品国产综合久久久久久| 国产精品国产三级国产普通话对白| 欧美日韩一区二区在线观看视频 | 欧美大片免费久久精品三p| 国产乱码精品一区二三区蜜臂| 欧美日韩一卡二卡| 在线观看免费观看在线| 在线播放/欧美激情| 99草在线视频| 日韩欧美一区在线| 成人精品在线播放| 亚洲高清在线观看| 日本1级在线| 亚洲免费人成在线视频观看| 国产乱视频在线观看| 中文字幕亚洲综合| 含羞草www国产在线视频| 久久影视电视剧免费网站| caopon在线免费视频| 欧美日韩高清区| 色在线视频观看| 国产精品igao视频| 视频欧美精品| 国产精品二区三区| 亚洲区小说区| 亚洲激情图片| 中国成人一区| 国产视频一视频二| 日韩avvvv在线播放| 91欧美一区二区三区| 大陆成人av片| 男人天堂av电影| 亚洲色图丝袜美腿| 日韩欧美a级片| 在线观看一区不卡| 99久久亚洲精品日本无码 | 亚洲r级在线观看| 国内毛片久久| 涩涩涩999| 国产一区日韩欧美| 欧美精品第三页| 国产美女娇喘av呻吟久久| 一边摸一边做爽的视频17国产| 久久色成人在线| 顶臀精品视频www| 欧美日韩亚洲视频| 99热这里只有精品3| 亚洲女人被黑人巨大进入al| 日本天堂在线观看| 26uuu国产精品视频| 日韩午夜电影免费看| 国产在线一区二| 99久久夜色精品国产亚洲96| 欧美性久久久久| 国产精品夜夜嗨| 日本不卡一区视频| 欧美日韩国产一区二区| 国产三级三级在线观看| 在线播放国产一区中文字幕剧情欧美| 成全电影大全在线观看| 国产日韩精品在线播放| 思热99re视热频这里只精品| 2021国产视频| 蜜桃视频在线观看一区二区| 稀缺小u女呦精品呦| 中文字幕一区二区三区蜜月| 国产精品午夜影院| 欧美成人一级视频| 国产在线观看91| 国产97免费视| 亚洲v天堂v手机在线| 毛片在线视频观看| 日韩1区2区日韩1区2区| 亚洲成人网在线播放| 亚洲精品国产无天堂网2021| 中文字幕在线观看1| 精品香蕉在线观看视频一| 国产后进白嫩翘臀在线观看视频 | 美女扒开腿让男人桶爽久久动漫| 中文字幕中文字幕在线中心一区 | 国产欧美日韩中文字幕| 国产videos久久| 两根大肉大捧一进一出好爽视频| 国产成a人亚洲精| 欧美卡一卡二卡三| 91精品国产综合久久福利| 天堂аⅴ在线地址8| 国产精品大片wwwwww| 中文字幕精品影院| www.亚洲天堂网| 91麻豆成人久久精品二区三区| 激情五月色婷婷| 亚洲电影免费观看高清| 国产丝袜在线播放| 成人资源av| 在线播放日韩| 国产黑丝一区二区| 亚洲国产一区视频| 国模私拍视频在线| 欧美精品久久久久久久久久| 日本精品视频| 激情六月天婷婷| 成人久久18免费网站麻豆| 免费视频网站www| 欧美www视频| √天堂8资源中文在线| 久久99精品久久久久久青青日本 | 国产精品美女久久久久av超清| 欧美日韩在线二区| 亚洲欧美在线精品| 中文字幕一区二区三区四区不卡 | 91精品国产综合久久久蜜臀九色| 日韩成人av网| 裤袜国产欧美精品一区| 日韩成人av网站| 久久精品国产精品亚洲综合| 九九热最新地址| 亚洲成人教育av| 亚洲欧洲高清| 亚洲人成77777| 国产精品一二三区| 影音先锋亚洲天堂| 国产一区二区成人| 99精品国产九九国产精品| 成人在线视频一区二区三区| 99精品视频在线观看| 久久久久在线视频| 日韩小视频在线观看| 91精品国产自产精品男人的天堂| 国产中文字幕视频在线观看| 久久久99精品久久| 国产精品一区二区人人爽| 高清欧美性猛交xxxx| 九一精品国产| aaaaaaaa毛片| 天天免费综合色| 网友自拍视频在线| 国产一区二区三区免费不卡| 日韩成人精品在线| 少妇被躁爽到高潮无码文| 日韩经典一区二区三区| 日韩成人综合网站| www.日本在线播放| 国产精品白丝在线| 日韩av成人| 99国产超薄丝袜足j在线观看| 国产精品毛片一区二区三区| 一区二区三区在线播放视频| 精品国产91九色蝌蚪| 欧美日韩视频免费观看| 蜜桃视频一区二区在线观看| 久久久久久97三级| 亚洲国产精彩视频| 国产精品精品久久久久久|