ใช้บริบทที่คาดการณ์ไว้เพื่อเข้าถึงฮาร์ดแวร์แว่นตา AI

อุปกรณ์ XR ที่ใช้ได้
คำแนะนำนี้จะช่วยให้คุณสร้างประสบการณ์การใช้งานสำหรับอุปกรณ์ XR ประเภทต่างๆ เหล่านี้ได้
แว่นตา AI

หลังจากขอและได้รับสิทธิ์ที่จำเป็นแล้ว แอปจะ เข้าถึงฮาร์ดแวร์แว่นตา AI ได้ กุญแจสำคัญในการเข้าถึงฮาร์ดแวร์ของแว่นตา (แทนที่จะเป็นฮาร์ดแวร์ของโทรศัพท์) คือการใช้บริบทที่คาดการณ์ไว้

คุณรับบริบทที่คาดการณ์ได้ 2 วิธีหลักๆ ขึ้นอยู่กับตำแหน่งที่โค้ดทำงาน ดังนี้

รับบริบทที่คาดการณ์ไว้หากโค้ดทำงานในกิจกรรมแว่นตา AI

หากโค้ดของแอปทำงานจากภายในกิจกรรมบนแว่นตา AI บริบทกิจกรรมของโค้ดเองจะเป็นบริบทที่คาดการณ์ไว้แล้ว ในสถานการณ์นี้ การเรียกใช้ภายในกิจกรรมนั้นจะเข้าถึงฮาร์ดแวร์ของแว่นตาได้อยู่แล้ว

รับบริบทที่คาดการณ์ไว้หากโค้ดทำงานในคอมโพเนนต์แอปโทรศัพท์

หากส่วนใดส่วนหนึ่งของแอปที่อยู่นอกกิจกรรมแว่นตา AI (เช่น กิจกรรมในโทรศัพท์หรือบริการ) ต้องเข้าถึงฮาร์ดแวร์ของแว่นตา ส่วนนั้นจะต้องขอรับบริบทที่คาดการณ์ไว้อย่างชัดเจน โดยใช้วิธีการ createProjectedDeviceContext() ดังนี้

// From a phone Activity, get a context for the AI glasses
try {
    val glassesContext = ProjectedContext.createProjectedDeviceContext(this)
    // Now use glassesContext to access glasses' system services
} catch (e: IllegalStateException) {
    // Projected device was not found
}

ตรวจสอบความถูกต้อง

หลังจากสร้างบริบทที่คาดการณ์แล้ว ให้ตรวจสอบ ProjectedContext.isProjectedDeviceConnected แม้ว่าวิธีนี้จะแสดงผลเป็น true แต่บริบทที่คาดการณ์ไว้จะยังคงใช้ได้กับอุปกรณ์ที่เชื่อมต่อ และกิจกรรมหรือบริการในแอปโทรศัพท์ (เช่น CameraManager) จะเข้าถึงฮาร์ดแวร์ของแว่นตา AI ได้

ล้างข้อมูลเมื่อยกเลิกการเชื่อมต่อ

บริบทที่คาดการณ์จะเชื่อมโยงกับวงจรของอุปกรณ์ที่เชื่อมต่อ ดังนั้นระบบจะทำลายบริบทเมื่ออุปกรณ์ตัดการเชื่อมต่อ เมื่ออุปกรณ์ยกเลิกการเชื่อมต่อ ProjectedContext.isProjectedDeviceConnected จะแสดง false แอปของคุณ ควรรอรับการเปลี่ยนแปลงนี้และล้างบริการของระบบ (เช่น CameraManager) หรือทรัพยากรที่แอปสร้างขึ้นโดยใช้บริบทที่ฉายนั้น

เริ่มต้นใหม่เมื่อเชื่อมต่ออีกครั้ง

เมื่ออุปกรณ์แว่นตา AI เชื่อมต่ออีกครั้ง แอปจะรับอินสแตนซ์บริบทที่ฉายอีกรายการได้โดยใช้ createProjectedDeviceContext() จากนั้น เริ่มต้นบริการหรือทรัพยากรของระบบอีกครั้งโดยใช้บริบทที่ฉายใหม่

เข้าถึงเสียงโดยใช้บลูทูธ

ปัจจุบันแว่นตา AI จะเชื่อมต่อกับโทรศัพท์เป็นอุปกรณ์เสียงบลูทูธมาตรฐาน ทั้งชุดหูฟังและโปรไฟล์ A2DP (Advanced Audio Distribution Profile) รองรับการใช้งาน การใช้วิธีนี้จะช่วยให้แอป Android ใดก็ตามที่ รองรับอินพุตหรือเอาต์พุตเสียงทำงานบนแว่นตาได้ แม้ว่าจะไม่ได้ สร้างขึ้นเพื่อรองรับแว่นตาโดยเฉพาะก็ตาม ในบางกรณี การใช้บลูทูธอาจเหมาะกับ Use Case ของแอปมากกว่า เพื่อเป็นทางเลือกแทนการเข้าถึงฮาร์ดแวร์ของแว่นตา โดยใช้บริบทที่ฉาย

เช่นเดียวกับอุปกรณ์เสียงบลูทูธมาตรฐานอื่นๆ โทรศัพท์จะเป็นตัวควบคุมสิทธิ์ในการให้สิทธิ์ RECORD_AUDIO ไม่ใช่แว่นตา

ถ่ายภาพด้วยกล้องของแว่นตา AI

หากต้องการบันทึกรูปภาพด้วยกล้องของแว่นตา AI ให้ตั้งค่าและเชื่อมโยงImageCapture Use Case ของ CameraX กับกล้องของแว่นตาโดยใช้บริบทที่ถูกต้องสำหรับแอปของคุณ ดังนี้

private fun startCamera() {
    // Get the CameraProvider using the projected context.

    val cameraProviderFuture = ProcessCameraProvider.getInstance(
        ProjectedContext.createProjectedDeviceContext(this)
    )

    cameraProviderFuture.addListener({
        // Used to bind the lifecycle of cameras to the lifecycle owner
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

        // Select the camera. When using the projected context, DEFAULT_BACK_CAMERA maps to the AI glasses' camera.
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
    
        // Check for the presence of a camera before initializing the ImageCapture use case.
       if (!cameraProvider.hasCamera(cameraSelector)) {
            Log.w(TAG, "The selected camera is not available.")
            return@addListener
        }

        // Get supported streaming resolutions.
        val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)
        val camera2CameraInfo = Camera2CameraInfo.from(cameraInfo)
        val cameraCharacteristics = camera2CameraInfo.getCameraCharacteristic(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)

        // Define the resolution strategy.
        val targetResolution = Size(1920, 1080)
        val resolutionStrategy = ResolutionStrategy(
            targetResolution,
            ResolutionStrategy.FALLBACK_RULE_CLOSEST_LOWER)

        val resolutionSelector = ResolutionSelector.Builder()
            .setResolutionStrategy(resolutionStrategy)
            .build()

        // If you have other continuous use cases bound, such as Preview or ImageAnalysis, you can use  Camera2 Interop's CaptureRequestOptions to set the FPS
        val fpsRange = Range(30, 30)
        val captureRequestOptions = CaptureRequestOptions.Builder()
                .setCaptureRequestOption(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,fpsRange)
                .build()

        // Initialize the ImageCapture use case.
        val imageCapture = ImageCapture.Builder()
            // Optional: Configure resolution, format, etc.
            .setResolutionSelector(resolutionSelector)
            .build()

        try {
            // Unbind use cases before rebinding
            cameraProvider.unbindAll()

            // 4. Bind use cases to camera
            cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageCapture)

        } catch(exc: Exception) {
            // This catches exceptions like IllegalStateException if use case binding fails
            Log.e(TAG, "Use case binding failed", exc)
        }

    }, ContextCompat.getMainExecutor(this))
}

ประเด็นสำคัญเกี่ยวกับโค้ด

  • รับอินสแตนซ์ของ ProcessCameraProvider โดยใช้บริบทของอุปกรณ์ที่คาดการณ์
  • ภายในขอบเขตของบริบทที่คาดการณ์ไว้ กล้องหลักของแว่นตา AI ซึ่งหันออกด้านนอกจะแมปกับ DEFAULT_BACK_CAMERA เมื่อเลือกกล้อง
  • การตรวจสอบก่อนการเชื่อมโยงใช้ cameraProvider.hasCamera(cameraSelector) เพื่อ ยืนยันว่ากล้องที่เลือกพร้อมใช้งานในอุปกรณ์ก่อนดำเนินการต่อ
  • ใช้ Camera2 Interop กับ Camera2CameraInfo เพื่ออ่าน CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP ที่อยู่เบื้องหลัง ซึ่งอาจมีประโยชน์สำหรับการตรวจสอบขั้นสูงเกี่ยวกับความละเอียดที่รองรับ
  • เราสร้าง ResolutionSelector ที่กำหนดเองขึ้นมาเพื่อควบคุมความละเอียดของรูปภาพเอาต์พุตสำหรับ ImageCapture ได้อย่างแม่นยำ
  • สร้างImageCaptureกรณีการใช้งานที่กำหนดค่าด้วยResolutionSelector
  • เชื่อมโยงกรณีการใช้งาน ImageCapture กับวงจรของกิจกรรม ซึ่งจะจัดการการเปิดและปิดกล้องโดยอัตโนมัติตามสถานะของกิจกรรม (เช่น หยุดกล้องเมื่อกิจกรรมหยุดชั่วคราว)

หลังจากตั้งค่ากล้องของแว่นตา AI แล้ว คุณจะถ่ายภาพด้วยคลาส ImageCapture ของ CameraX ได้ โปรดดูเอกสารประกอบของ CameraX เพื่อดูข้อมูล เกี่ยวกับการใช้ takePicture() เพื่อจับภาพ

บันทึกวิดีโอด้วยกล้องของแว่นตา AI

หากต้องการบันทึกวิดีโอแทนรูปภาพด้วยกล้องของแว่นตา AI ให้แทนที่ คอมโพเนนต์ ImageCapture ด้วยคอมโพเนนต์ VideoCapture ที่เกี่ยวข้อง และแก้ไขตรรกะการดำเนินการจับภาพ

การเปลี่ยนแปลงหลักๆ ได้แก่ การใช้กรณีการใช้งานอื่น การสร้างไฟล์เอาต์พุตอื่น และการเริ่มการจับภาพโดยใช้วิธีการบันทึกวิดีโอที่เหมาะสม ดูข้อมูลเพิ่มเติมเกี่ยวกับ VideoCapture API และวิธีใช้ได้ที่เอกสารประกอบการจับภาพวิดีโอของ CameraX

ตารางต่อไปนี้แสดงความละเอียดและอัตราเฟรมที่แนะนำโดยขึ้นอยู่กับ กรณีการใช้งานของแอป

กรณีการใช้งาน ความละเอียด อัตราเฟรม
การสื่อสารผ่านวิดีโอ 1280 x 720 15 FPS
คอมพิวเตอร์วิทัศน์ 640 x 480 10 FPS
การสตรีมวิดีโอ AI 640 x 480 1 FPS

เข้าถึงฮาร์ดแวร์ของโทรศัพท์จากกิจกรรมแว่นตา AI

กิจกรรมแว่นตา AI ยังเข้าถึงฮาร์ดแวร์ของโทรศัพท์ (เช่น กล้อง หรือไมโครโฟน) ได้ด้วยการใช้ createHostDeviceContext(context) เพื่อรับบริบทของอุปกรณ์โฮสต์ (โทรศัพท์) ดังนี้

// From an AI glasses Activity, get a context for the phone
val phoneContext = ProjectedContext.createHostDeviceContext(this)
// Now use phoneContext to access the phone's hardware

เมื่อเข้าถึงฮาร์ดแวร์หรือทรัพยากรที่เฉพาะเจาะจงกับอุปกรณ์โฮสต์ (โทรศัพท์) ในแอปแบบไฮบริด (แอปที่มีทั้งประสบการณ์การใช้งานบนอุปกรณ์เคลื่อนที่และแว่นตา AI) คุณต้องเลือกบริบทที่ถูกต้องอย่างชัดเจนเพื่อให้แน่ใจว่าแอปจะเข้าถึงฮาร์ดแวร์ที่ถูกต้องได้ โดยทำดังนี้

  • ใช้บริบท Activity จากโทรศัพท์ Activity หรือ ProjectedContext.createHostDeviceContext() เพื่อรับบริบทของโทรศัพท์
  • อย่าใช้ getApplicationContext() เนื่องจากบริบทของแอปพลิเคชัน อาจแสดงบริบทของแว่นตา AI อย่างไม่ถูกต้อง หากกิจกรรมบนแว่นตาเป็นคอมโพเนนต์ที่เปิดตัวล่าสุด