Android XR

สร้างประสบการณ์ที่ยึดกับโลกจริงสำหรับแว่นตา XR แบบมีสาย

ลำโพง

เกี่ยวกับ

เกี่ยวกับการเสวนา

ก้าวข้ามขีดจำกัดของพื้นที่หน้าจอและยึดแอปของคุณไว้ในโลกแห่งความเป็นจริงด้วย Android XR เซสชันนี้จะสอนวิธีสร้างประสบการณ์ Android XR ที่รับรู้ข้อมูลเชิงพื้นที่โดยใช้ Jetpack Compose Glimmer และ Geospatial API ของ ARCore เราจะเริ่มด้วยการอธิบายวิธีรับท่าทางเชิงพื้นที่ของอุปกรณ์ด้วย ARCore จากนั้น คุณจะได้เห็นวิธีที่คอมโพเนนต์ UI ขั้นต่ำของ Glimmer สามารถยึดกับสถานที่ในโลกจริงผ่านระบบการระบุตำแหน่งด้วยภาพ (VPS) เราจะรวมข้อมูลเหล่านี้เพื่อสร้างประสบการณ์เชิงพื้นที่ที่รับรู้ถึงตำแหน่งและใช้งานง่าย

สรุป

  • Android XR นำประสบการณ์ดิจิทัลมาสู่สภาพแวดล้อมจริงในอุปกรณ์ต่างๆ ตั้งแต่แว่นตาอัจฉริยะไปจนถึงแว่นตา XR แบบมีสาย แอปที่เข้ากันได้กับ Android แบบ 2 มิติที่มีอยู่จะทำงานบนชุดหูฟัง XR และแว่นตา XR แบบมีสายได้โดยมีการปรับเปลี่ยนเพียงเล็กน้อย
  • Jetpack Compose Glimmer มีคอมโพเนนต์และสไตล์ที่ปรับแต่งมาสำหรับจอแสดงผลแบบมองทะลุผ่านเลนส์ ฟังก์ชันตัวช่วยในตัวจะปรับสีของแบรนด์ให้เป็นเฉดสีที่ปลอดภัยต่อแว่นตาเพื่อรักษาการมองเห็นและคอนทราสต์ในสภาพแสงต่างๆ
  • ไลบรารี Glimmer เพิ่มคอมโพเนนต์ใหม่ๆ เช่น ตัวแบ่งหน้าและกลุ่มปุ่ม Depth API ช่วยแยกองค์ประกอบที่ซ้อนกันบนจอแสดงผลแบบมองทะลุซึ่งสีดำมีความโปร่งใส
  • คอมโพสิเบิล Subspace จะวางอินเทอร์เฟซในพื้นที่ 3 มิติและติดตาม Anchor ของ ARCore ผ่านเป้าหมายการติดตามได้ เช่น คิวอาร์โค้ดที่ติดตาม
  • Geospatial API ใน ARCore รวมข้อมูล Street View และการวัดค่า GPS เพื่อระบุตำแหน่งอุปกรณ์อย่างแม่นยำในพื้นที่ที่รองรับ คุณสามารถแนบคอมโพเนนต์ Glimmer กับ Anchor เชิงพื้นที่ในชีวิตจริงได้โดยใช้พิกัดจากคำค้นหา Places API

แหล่งข้อมูล

Gemini Notebook

หัวข้อ

  • android-xr
  • jetpack-compose
  • วิบวับ
  • arcore
  • geospatial-api
  • augmented-reality

ข้อความถอดเสียง

ข้อมูลเบื้องต้นเกี่ยวกับ Android XR

  • สวัสดีทุกคน ยินดีต้อนรับสู่เซสชันแรกในเส้นทาง Android XR ที่งาน Android Developer Summit

  • ใช่เลย

  • เราตื่นเต้นมากที่ได้เห็นหลายๆ คนเรียนรู้เกี่ยวกับ Android XR

  • ฉันชื่อ Yasmine Quintana Evjen และมี Paul Hoover กับ Dereck Bridie มาร่วมพูดคุยด้วยในวันนี้

  • และหัวข้อของเซสชันนี้จะเกี่ยวกับ Android XR ทั้งหมด รวมถึงวิธีสร้างประสบการณ์ในโลกจริงที่ยึดตามพื้นที่ด้วย Jetpack Compose Glimmer และ ARCore สำหรับ Jetpack XR

  • แต่ก่อนอื่น เรามาทำความรู้จัก Android XR กันแบบคร่าวๆ ก่อน

  • Android XR เป็นแพลตฟอร์มใหม่ที่กำหนดนิยามใหม่ของวิธีที่ผู้ใช้โต้ตอบกับแอปของคุณ โดยก้าวข้ามหน้าจอและเข้าสู่พื้นที่รอบตัว

  • เราออกแบบแพลตฟอร์มมาเพื่อนำประสบการณ์ดิจิทัลมาสู่สภาพแวดล้อมจริงโดยตรง

  • ไม่ว่าจะเป็นการวางซ้อนที่มองเห็นได้ง่ายซึ่งช่วยปรับปรุงการแสดงตนในโลกจริงหรือสภาพแวดล้อมที่สมจริงแบบไม่สิ้นสุด

  • นี่คือระบบนิเวศของ Android แบบเปิดที่เราสร้างร่วมกันมาหลายปี และตอนนี้ผืนผ้าใบก็มีขนาดใหญ่เท่ากับห้องและกว้างขวางเท่ากับจินตนาการของคุณ

  • เรามองว่า XR เป็นสเปกตรัมของอุปกรณ์ต่างๆ ตั้งแต่แว่นตาอัจฉริยะ ซึ่งมอบประสบการณ์การใช้งานแบบเสริมประสิทธิภาพน้ำหนักเบาบนแว่นตาที่มีจอแสดงผลและเสียง ไปจนถึงชุดหูฟังที่สมจริงและแว่นตา XR แบบมีสาย ซึ่งช่วยให้คุณมีสมาธิ ทำงานได้อย่างมีประสิทธิภาพ และมอบความสามารถด้านความบันเทิงที่สมจริง

  • อุปกรณ์ใหม่ล่าสุดในตระกูล Android XR คือ XREAL AURA ซึ่งพร้อมจำหน่ายแล้ววันนี้

  • อุปกรณ์นี้มีน้ำหนักเบาและมีประสิทธิภาพสูง ช่วยให้คุณได้รับประสบการณ์การใช้งาน XR ที่คุ้นเคยของ Android

  • วิสัยทัศน์ของเราสำหรับแพลตฟอร์มนี้คือ หากคุณพัฒนาแอปสำหรับ Android อยู่แล้ว คุณก็พร้อมที่จะพัฒนาแอปสำหรับ XR

  • เราต้องการช่วยให้คุณสร้างแอปบน Android XR ได้ง่ายๆ โดยใช้โมเดลแอป ไลบรารี และเครื่องมือเดียวกับที่คุณคุ้นเคย

  • แอปที่เข้ากันได้กับ Android แบบ 2 มิติที่มีอยู่จะทำงานบนชุดหูฟัง Android XR และแว่นตา XR แบบมีสายได้โดยไม่ต้องแก้ไขหรือแก้ไขเพียงเล็กน้อย

Jetpack XR SDK และเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์

  • และเพื่อสร้างประสบการณ์ XR ที่ยอดเยี่ยมซึ่งให้ความรู้สึกเหมือนอยู่ที่บ้าน เราจึงมีชุดไลบรารีที่สร้างขึ้นสำหรับแพลตฟอร์ม XR โดยเฉพาะ

  • สําหรับนักพัฒนาแอปที่คุ้นเคยกับการสร้างประสบการณ์การใช้งานบนแพลตฟอร์มที่สมจริงอื่นๆ คุณสามารถสร้างด้วย OpenXR และการรองรับเครื่องมือ 3 มิติของเรา เช่น Unity, Godot และ Unreal

  • มาพูดถึงการสร้างด้วยไลบรารี Android กัน

  • เรามี Jetpack XR SDK ซึ่งเป็นชุดไลบรารี Kotlin ที่ช่วยคุณขยายแอปไปยัง XR ในประสบการณ์การใช้งานแบบสมจริงและเทคโนโลยีความจริงเสริม (AR)

  • มาดูคลังภาพที่สมจริงกัน

  • ไลบรารี Jetpack XR ของเราจะเข้าสู่เวอร์ชันเบต้าและเวอร์ชันเสถียรในปีนี้ ซึ่งจะช่วยให้คุณมั่นใจในการเริ่มสร้างประสบการณ์ XR ที่สมจริง

  • เลเยอร์การรับรู้คือ ARCore สำหรับ Jetpack XR

  • ไลบรารีนี้ให้ข้อมูลเกี่ยวกับโลกจริง เช่น ตำแหน่งของพื้นผิวเรียบอย่างโต๊ะ และตำแหน่งมือของผู้ใช้

  • โดยสามารถติดตามจุดในพื้นที่ 3 มิติ และให้ข้อมูลดังกล่าวแก่แอปเมื่อได้รับสิทธิ์ที่เหมาะสม

  • จากนั้นก็มี Jetpack XR SceneCore ซึ่งมีกราฟฉากสำหรับการวางเนื้อหาเชิงพื้นที่

  • ไลบรารีนี้สามารถแสดงเอนทิตีในพื้นที่ 3 มิติ และมีลักษณะเชิงพื้นที่สำหรับการวางกราฟฉากที่แม่นยำ

  • และ Jetpack Compose สำหรับ XR มี Composable พื้นที่ย่อยใหม่ที่สร้างขึ้นสำหรับ 3 มิติโดยเฉพาะ

  • นักพัฒนาแอป Android ที่คุ้นเคยกับเลย์เอาต์ Compose อยู่แล้ว เช่น การสร้างด้วยแถวและคอลัมน์ จะพบว่าการจัดเลย์เอาต์ UI เชิงพื้นที่นั้นใช้งานง่าย

  • การสร้างแถวเชิงพื้นที่ช่วยให้คุณจัดวางแผงเชิงพื้นที่หลายแผงติดกันได้โดยไม่ต้องคำนวณตำแหน่งหรือขนาดด้วยตนเอง

  • การใช้ Composable พื้นที่ย่อย เช่น แผงเชิงมิติพื้นที่หรือ Orbiter จะช่วยให้คุณขยายคอมโพเนนต์ 2 มิติไปยังพื้นที่ 3 มิติใหม่นี้ได้อย่างง่ายดาย

  • และแน่นอนว่า Composable ของพื้นที่ย่อยสามารถทำได้มากกว่าแค่แสดงเนื้อหา 2 มิติ

  • Compose สำหรับ XR รองรับวิดีโอเชิงมิติพื้นที่และโมเดล 3 มิติผ่านพื้นผิวภายนอกเชิงมิติพื้นที่และโมเดล glTF เชิงมิติพื้นที่

การสร้าง UI ด้วย Jetpack Compose Glimmer

  • ทีนี้เรามาพูดถึงแอป Augmented กันบ้าง

  • ไลบรารี Jetpack Projected ช่วยให้คุณปรับปรุงแอปบนอุปกรณ์เคลื่อนที่ที่มีอยู่เพื่อใช้ประโยชน์จากฮาร์ดแวร์แว่นตาอัจฉริยะ เช่น เซ็นเซอร์และจอแสดงผล

  • สุดท้ายคือ Jetpack Compose Glimmer ซึ่งเป็นชุดเครื่องมือ UI สำหรับสร้างประสบการณ์การใช้งาน Android XR ที่เพิ่มประสิทธิภาพสำหรับแว่นตา

  • Jetpack Compose Glimmer ประกอบด้วยสไตล์และคอมโพเนนต์ที่พร้อมใช้งานสำหรับการสร้างประสบการณ์ XR

  • เราเปิดตัว Glimmer เมื่อปีที่แล้วและได้ขยายความสามารถอย่างต่อเนื่อง ซึ่งรวมถึงทักษะ Agentic เพื่อช่วยคุณสร้างแอปแว่นตาที่มีจอแสดงผลด้วย Glimmer

    android skills add display-glasses-with-jetpack-compose-glimmer
  • เราได้รับฟังความคิดเห็นของคุณตั้งแต่เปิดตัว

  • เราทราบมาว่าคุณต้องการให้เราขยาย Jetpack Compose Glimmer ให้ครอบคลุมมากกว่าแว่นตาอัจฉริยะ

  • เรายินดีที่จะประกาศว่าเราได้ทำการเปลี่ยนแปลงเพื่อรองรับประสบการณ์การใช้งานที่ยึดตามตำแหน่งเชิงพื้นที่ได้ดียิ่งขึ้นด้วย Glimmer ซึ่งเราจะเจาะลึกในภายหลังในการพูดคุยนี้

  • งานของเราในการเพิ่มประสิทธิภาพ Glimmer เริ่มต้นด้วยการสร้างแพลตฟอร์มใหม่สำหรับการแสดงผลในรูปแบบ XR ที่หลากหลาย ตั้งแต่จอแสดงผลไปจนถึงแว่นตา XR แบบมีสาย

  • การเพิ่มแพลตฟอร์มใหม่นี้ช่วยให้คุณปรับแต่ง UI ได้อย่างยืดหยุ่นมากขึ้น

  • และเพื่อเพิ่มความโดดเด่นให้กับแบรนด์แอปของคุณ เราได้เพิ่มสีแบบกำหนดเองลงในคอมโพเนนต์ Glimmer

  • ใช้สิ่งเหล่านี้เพื่อแสดงสไตล์ของแบรนด์ในแอป XR

  • ไลบรารี Glimmer ของ Jetpack Compose มีฟังก์ชันตัวช่วยที่แปลงสีเป้าหมายและสีของแบรนด์เป็นสีที่ปลอดภัยสำหรับแว่นตา

  • ทั้งนี้เพื่อให้มั่นใจว่าการแสดงผลบนจอแสดงผลแบบมองทะลุผ่านเลนส์จะมีความชัดเจนที่สุด

  • มาดูการทำงานจริงกัน

  • เราต้องการเปลี่ยนสีปุ่มที่โฟกัสสำหรับแอปแว่นตานี้ ซึ่งฉันจะเลือกสีโปรดที่สวยงามสีหนึ่ง

    val brandColor = Color(0xFFFFAABB)
    val focusedColor = ButtonDefaults.focusedColor(brandColor)
    
    Column(…) {
       LeadingImageCard(
           focusable = false,
           …
       ) {
           …
       }
       ButtonGroup(...) {
           Button(
               onClick = {},
               leadingIcon = { … },
               focusedColor = focusedColor,
           ) { Text("Add to cart") }
    
           /* Rest of the buttons */
       }
    }
  • โปรดทราบว่าเมื่อเพิ่มสีลงในโค้ด ฟังก์ชันตัวช่วยของ Glimmer จะปรับสีให้เป็นสีที่ปลอดภัยสำหรับแว่นตาเพื่อการมองเห็นที่ดีที่สุด

  • ทั้งหมดนี้สร้างขึ้นภายในไลบรารี Jetpack Compose Glimmer เพื่อให้มั่นใจว่าคุณกำลังสร้างประสบการณ์ที่ดูดีในสภาพแวดล้อมต่างๆ

  • ใน Android Studio คุณสามารถใช้โปรแกรมจำลองเพื่อดูภาพว่า UI ของแว่นตาจะมีลักษณะอย่างไรในพื้นหลังต่างๆ เช่น สภาพแวดล้อมที่มีแสงสว่าง มืด หรือมีสิ่งรบกวน

  • การอัปเดตเหล่านี้เป็นเพียงจุดเริ่มต้นเท่านั้น

  • โอเค ไม่ใช่นะ

  • ทีมของฉันบอกว่าคุณจะไม่ขำกับเรื่องนี้ แต่ฉันก็ยังคงยึดมั่นในเรื่องนี้

  • แต่ตอนนี้ฉันจะส่งต่อให้ Paul เพื่อบอกคุณเพิ่มเติมเกี่ยวกับ Jetpack Compose Glimmer

หลักการออกแบบ UI สำหรับแว่นตาที่มีจอแสดงผล

  • ทดสอบๆ โอเค

  • ฉันต้องกดปุ่มถัดไป

  • ขอบคุณนะ Yasmine

  • โอเค

  • ดังที่ Yasmine กล่าวไว้ Jetpack Compose Glimmer มีองค์ประกอบพื้นฐานสำหรับการพัฒนาแอปพลิเคชันที่ปรับแต่งมาสำหรับแว่นตาที่มีจอแสดงผล

  • คอมโพเนนต์ของเราผสานรวมแนวทางปฏิบัติแนะนำที่สร้างขึ้นสำหรับจอแสดงผลแบบ Optical See-Through และเราได้สร้างคอมโพเนนต์เหล่านี้ลงใน API โดยตรงสำหรับคุณ เพื่อช่วยให้นักพัฒนาซอฟต์แวร์ทุกคนสร้างประสบการณ์การใช้งาน Optical See-Through ที่สวยงามและใช้งานได้จริง

  • เมื่อออกแบบและสร้างแอปสำหรับอุปกรณ์แบบมองทะลุผ่านเลนส์เช่นนี้ คุณต้องคำนึงถึงสิ่งต่างๆ ต่อไปนี้

  • ประการแรกคือเป็นจอแสดงผลแบบมองทะลุได้ ซึ่งหมายความว่าไม่มีสีดำ

  • เมื่อมองเห็นโลกได้ สีดำจะโปร่งใส

  • ดังนั้นคุณจึงไม่สามารถใช้พื้นหลังสีเข้มเพื่อรักษาคอนทราสต์สำหรับ UI, ข้อความ และเนื้อหาได้

  • แม้ว่าสีดำจะมองไม่เห็น แต่คุณสามารถใช้สีดำเพื่อบดบังเนื้อหาดิจิทัลอื่นๆ ได้

  • ในเฟรมเวิร์ก UI ของ Glimmer เรามี Depth API ที่ช่วยให้คุณแยกองค์ประกอบ UI ออกจากกันได้อย่างง่ายดายและให้ความรู้สึกถึงลำดับชั้น

  • คุณจะเห็นว่าความลึกของการ์ดในกองนี้ช่วยให้การ์ดแต่ละใบแยกออกจากกันได้อย่างไร

  • นักวิทยาศาสตร์ด้านการมองเห็นของเราได้ระบุอัตราส่วนคอนทราสต์เป้าหมายสำหรับข้อความและไอคอนที่มองเห็นได้ในสภาพแสงส่วนใหญ่

  • อย่างที่ Yasmine แสดงให้เห็น เราสามารถสร้างสิ่งนี้หรือเราได้สร้างสิ่งนี้ไว้ในเฟรมเวิร์ก เพื่อให้คุณมั่นใจได้ว่าเมื่อปรับแต่งสีของแพลตฟอร์ม อินเทอร์เฟซจะอ่านง่ายสำหรับผู้ใช้

  • เราได้สร้างแนวทางปฏิบัติแนะนำเหล่านี้และแนวทางปฏิบัติแนะนำอื่นๆ ไว้ในคลังคอมโพเนนต์ที่กำลังขยายตัว

  • เราเพิ่งเปิดตัวคอมโพเนนต์ใหม่ๆ มากมาย

  • หนึ่งในคอมโพเนนต์ใหม่ล่าสุดของเราคือคอมโพเนนต์เพจเจอร์ที่มีการเปลี่ยนภาพเคลื่อนไหวและท่าทางสัมผัสที่ราบรื่นในตัว

    val pagerState =
      rememberGlimmerPagerState(pageCount = { 10 })
    
    GlimmerHorizontalPager(pagerState) { page ->
       /* Card Content */
    }
  • หากคุณคุ้นเคยกับเพจเจอร์แนวนอนของ Compose คอมโพเนนต์นี้จะดูคุ้นเคยมาก

  • นอกจากนี้ เรายังได้เปิดตัวการ์ดรูปแบบใหม่ 4 แบบที่ออกแบบมาเพื่อการผสานรวมกับเพจเจอร์ สแต็ก และอื่นๆ ได้อย่างราบรื่น ควบคู่ไปกับ UI ของ Glimmer อื่นๆ

  • การ์ดรูปภาพนำและการ์ดรูปภาพตามจะแสดงข้อความและรูปภาพติดกัน

  • ดังนั้น ให้ใช้การ์ดรูปแบบต่างๆ เหล่านี้เมื่อคุณมีข้อความและข้อมูลภาพในปริมาณที่เท่ากัน

  • เราได้แยกการ์ดรูปภาพออกเป็นตัวแปรการ์ดของตัวเอง

  • เลย์เอาต์นี้เหมาะที่สุดเมื่อคุณมีรูปภาพขนาดใหญ่ที่มีข้อความหรือคำบรรยายเพียงบรรทัดเดียว เช่น เครื่องมือเลือกวิดีโอนี้

  • ตัวแปรการ์ดการดำเนินการจะฝังปุ่มเดียวลงในการ์ด

  • ใช้ตัวเลือกนี้เมื่อต้องการให้ผู้ใช้ทราบอย่างแน่ชัดว่าจะเกิดอะไรขึ้นเมื่อเปิดใช้งานการ์ด เช่น ในเครื่องมือเลือกปลายทางนี้

  • กลุ่มปุ่มช่วยให้คุณใส่ปุ่มจำนวนมากไว้ในพื้นที่ขนาดเล็กได้

    ButtonGroup {
       Button(onClick = {}) { Text("Button 1") }
       Button(onClick = {}) { Text("Button 2") }
       Button(onClick = {}) { Text("Button 3") }
       Button(onClick = {}) { Text("Button 4") }
       Button(onClick = {}) { Text("Button 5") }
    }
  • เพียงใช้โค้ดง่ายๆ นี้ คุณก็จะได้การเปลี่ยนภาพที่สวยงาม ลักษณะการเลื่อน สคริมที่ซ่อนขอบและแสดงเมื่อจำเป็นเท่านั้น และอินพุตที่กำหนดเส้นทางจากแว่นตาไปยังตัวควบคุมโดยอัตโนมัติ

  • กลุ่มปุ่มยังสามารถมีปุ่มไอคอนและปุ่มเปิด/ปิดใหม่ได้ด้วย

    var buttonChecked by remember { mutableStateOf(false) }
    
    ToggleButton(
      checked = buttonChecked,
      leadingIcon = { Icon(FavoriteIcon) },
      onCheckedChange = { buttonChecked = it }
    ) {
      Text(if (buttonChecked) "On" else "Off")
    }
  • คุณจะเห็นปุ่มทุกประเภทของเราที่ใช้สร้างตัวควบคุมสื่อนี้ได้ที่นี่

  • และตอนนี้คุณสามารถทดสอบ UI บนพื้นหลังต่างๆ ได้อย่างง่ายดาย

  • โปรแกรมจำลองแว่นตาช่วยให้คุณใส่ภาพมุมมอง 360 และเลื่อนไปรอบๆ เพื่อทดสอบกับพื้นหลังต่างๆ พื้นหลังที่วุ่นวาย และแสงสว่างหรือความมืดได้

  • กลุ่มปุ่มเหมาะสำหรับใช้ในมุมมองรายละเอียดเช่นนี้เพื่อแสดงการดำเนินการตามบริบท

  • เมื่อแตะ คุณสามารถใช้การเปลี่ยนองค์ประกอบที่แชร์เพื่อไปยังสถานะมุมมองแบบละเอียด จากนั้นใช้ท่าทางสัมผัสย้อนกลับของระบบเพื่อกลับไปยังมุมมองก่อนหน้า

  • ดีมากเลย

  • นอกจากนี้ เรายังได้เพิ่มตัวบ่งชี้การป้อนข้อมูลด้วยเสียงและกล่องโต้ตอบการแจ้งเตือนด้วย

  • สรุปก็คือมีสิ่งใหม่ๆ มากมาย

  • แต่ตอนนี้เราได้เห็นสิ่งใหม่ๆ บางอย่างแล้ว มาสร้างอะไรบางอย่างกันดีกว่า

ภาพรวมของ Anchor ตามตำแหน่ง

  • นอกเหนือจากการใช้ Glimmer เพื่อสร้างแว่นตาอัจฉริยะแล้ว เรายังใช้ Glimmer เพื่อสร้างประสบการณ์การใช้งานแว่นตา XR แบบมีสายได้ด้วย

  • และเราต้องการให้คุณสร้างประสบการณ์ที่ช่วยเสริมโลกรอบตัวคุณ โดยเริ่มจาก Anchor ตามตำแหน่งในโลกจริง

  • สมมติว่าคุณอยู่ในเมืองใหม่ อาจจะเดินทางไปร่วมงานประชุมนักพัฒนาซอฟต์แวร์ และต้องการหาร้านอาหารในเมืองรอบๆ ตัวคุณ

  • คุณสามารถขอให้แอปการนำทางที่ชื่นชอบค้นหาร้านอาหารใกล้เคียงและคะแนนของร้านอาหารเหล่านั้นได้

  • ข้อมูลสามารถวางซ้อนบนสถานที่ได้โดยตรง ซึ่งจะให้บริบท ข้อมูลเชิงลึก และคำแนะนำ

  • คุณจะเห็นคอมโพเนนต์ Glimmer ล่าสุดของเราที่ชื่อว่าเครื่องหมายไอคอนได้ที่นี่

  • ซึ่งช่วยให้คุณไฮไลต์องค์ประกอบสำคัญในโลกจริงและจับคู่กับคอมโพเนนต์อื่นๆ ของ Glimmer เช่น การ์ดนี้ได้

  • ในตัวอย่างนี้ ระบบจะใส่คำอธิบายประกอบจุดที่น่าสนใจโดยใช้ Google Maps, Places และ Geospatial API

  • คุณ Dereck มาแสดงวิธีตั้งค่าให้ทุกคนดูกัน

  • มาเริ่มกันเลย

  • โอเค

  • โอเค

  • ดังนั้นตามที่ Paul ได้กล่าวไว้ก่อนหน้านี้ เรามาเริ่มสร้างกันเลย

  • เราจะใช้เอกสารประกอบสำหรับนักพัฒนาซอฟต์แวร์ใน developer.android.com/xr และจะดูไลบรารีคอมโพเนนต์ Glimmer ของ Jetpack Compose

  • คุณจึงจะเห็นภาพรวมของคอมโพเนนต์ทั้งหมดที่มีใน Glimmer

  • มาเริ่มกันที่ UI ส่วนนี้ที่ Paul แสดงให้เห็นก่อนหน้านี้

  • เราจึงจะใช้ Glimmer UI เพื่อสร้างตัวบอกสถานะเชิงพื้นที่และกล่องข้อมูล

  • มาเริ่มกันด้วยการระบุคอมโพเนนต์ที่เราจะใช้

  • ทางด้านซ้าย คุณจะเห็นเครื่องหมายไอคอน และทางด้านขวา เราจะใช้การ์ดที่อธิบายสถานที่

  • ดังนั้น หากคุณไปที่ Android Studio คุณจะดูตัวอย่างแผงนี้ได้เหมือนกับคอมโพเนนต์ Compose อื่นๆ และดูการเปลี่ยนแปลงแบบเรียลไทม์ได้

  • ดังที่กล่าวไว้ก่อนหน้านี้ คุณสามารถดูตัวอย่าง UI ในสภาพแวดล้อมพื้นหลังประเภทต่างๆ ทั้งหมด และตรวจสอบว่าคอนทราสต์ของ UI เพียงพอในสถานการณ์หลายประเภท เช่น สภาพแวดล้อมที่มืดและสว่าง

  • เมื่อตั้งค่า Canvas แล้ว เราจะสร้างแถว ใส่เครื่องหมายไอคอนลงในแถวโดยเว้นระยะห่าง และใส่การ์ดที่มีข้อความตัวอย่าง

  • และนี่คือทั้งหมดที่เราอยากบอกคุณ

  • หากคุณพอใจกับตัวอย่าง 2 มิติ เราจะเริ่มทำเครื่องหมายบางอย่างในโลกจริง และเราจะทำเช่นนั้นโดยการปรับ UI ให้เข้ากับพื้นที่ทำงาน

  • ซึ่งหมายความว่าเราจะจัดวางในรูปแบบ 3 มิติแทน 2 มิติ

  • ดังนั้น UI เชิงมิติพื้นที่จะอยู่ในพื้นที่ย่อย ซึ่งเป็นพื้นที่ 3 มิติที่อยู่ด้านหน้าผู้ใช้

    Subspace {
      SpatialPanel {
        VideoPlayer()
      }
    }
  • และโดยค่าเริ่มต้น พื้นที่ย่อยจะจัดวางเนื้อหาในระยะที่ผู้ใช้มองเห็นได้สบายตา

  • ก่อนที่เราจะแสดงวิธีใช้ Geospatial API ให้คุณดู ลองวางบางอย่างไว้ใกล้ๆ ก่อน

  • ดังนั้น Subspace Composable ที่ฉันพูดถึงก่อนหน้านี้จึงมีพารามิเตอร์ที่ไม่บังคับซึ่งช่วยให้คุณระบุเป้าหมายการติดตามได้

    val state by
      qrCode.state.collectAsState()
    Subspace(FollowTarget.anchor(anchor)) {
      SpatialPanel {
        Row {
          IndicatorDot()
          Spacer()
          QrCodeCard(state)
        }
      }
    }
  • ดังนั้น หากต้องการแนบวัตถุกับโลกจริง ก่อนอื่นคุณจะต้องสร้าง Anchor ที่ได้จาก ARCore สำหรับ Jetpack XR

  • และในตัวอย่างนี้ ฉันใช้ฟีเจอร์การจดจำคิวอาร์โค้ด

  • ซึ่งจะช่วยให้คุณอ่านและติดตามคิวอาร์โค้ดได้ เพื่อให้เนื้อหาติดตามคิวอาร์โค้ดนั้นไปรอบๆ พื้นที่ และเราจะแนบ UI ที่เห็นก่อนหน้านี้

การผสานรวม Geospatial API และ Google Maps Platform

  • ตกลง

  • ฉันได้แสดงวิธีวางเนื้อหาดิจิทัลในโลกจริงที่อยู่ใกล้เคียงให้คุณดูแล้ว

  • ลองกลับไปดูตัวอย่างของ Paul กัน

  • ส่วนตัวแล้วฉันมาจากเนเธอร์แลนด์

  • ฉันไม่ค่อยคุ้นเคยกับ Mountain View

  • ดังนั้น หลังจากกิจกรรมนี้ ฉันอยากช่วยคุณสร้างแอปที่จะช่วยคุณค้นหาร้านกาแฟสนุกๆ

  • มาดูกันว่าเราจะช่วยผู้ใช้ค้นหาจุดชาร์จได้อย่างไรด้วย Geospatial API ซึ่งตอนนี้อยู่ใน ARCore สำหรับ Jetpack XR

  • ดังนั้น Geospatial API ที่เปิดตัวครั้งแรกบนสมาร์ทโฟนจึงพร้อมใช้งานบน Android XR ด้วยเช่นกัน

  • โดยจะใช้ข้อมูลจาก Google Street View และรวมเข้ากับการวัด GPS เพื่อระบุตำแหน่งของอุปกรณ์ในพื้นที่ที่รองรับ

  • ดังนั้น Geospatial API จึงสามารถใช้เพื่อระบุตำแหน่งและทิศทางของผู้ใช้ได้อย่างแม่นยำบนแว่นตาอัจฉริยะ และช่วยให้สามารถใช้กรณีการใช้งานการนำทางแบบเลี้ยวต่อเลี้ยวที่มีความแม่นยำสูงได้

  • และในอุปกรณ์ที่สมจริง เช่น แว่นตา XR แบบมีสาย Geospatial API ช่วยให้คุณสร้างประสบการณ์ที่วางตำแหน่งได้อย่างถูกต้องในโลกจริง

  • ตัวอย่างเช่น คุณสามารถยึดเนื้อหาเชิงพื้นที่ไว้กับอาคารหรือสร้างทัวร์ชมเมืองแบบเฉพาะทางได้

  • มาเริ่มต้นใช้งาน Geospatial API ด้วย 3 ขั้นตอนนี้กันเลย

  • วิธีแรกคือคุณจะสร้างโปรเจ็กต์ Google Cloud Platform และกำหนดค่าการตรวจสอบสิทธิ์ในแอป

  • จากนั้นเมื่อกำหนดค่าและเปิดใช้ Geospatial API ในแอปแล้ว คุณจะขอสิทธิ์จากผู้ใช้เพื่อดึงข้อมูลตำแหน่งโดยใช้ความละเอียดสูง

  • จากนั้นหลังจากกำหนดค่าเซสชันให้ใช้ Geospatial API แล้ว คุณก็พร้อมใช้งาน

  • คุณดูรายละเอียดทั้งหมดเกี่ยวกับเอกสารประกอบสำหรับนักพัฒนาซอฟต์แวร์เกี่ยวกับ Geospatial API ได้ในหน้านักพัฒนาซอฟต์แวร์ Android XR ที่ปรับปรุงใหม่

  • เรามาเริ่มด้วยการใช้ตำแหน่งของผู้ใช้เพื่อขอ Places API จาก Google Maps Platform เพื่อค้นหาร้านกาแฟดีๆ ใกล้ผู้ใช้กัน

  • ก่อนอื่น ผู้ใช้อยู่ที่ไหน

  • เราจะขอให้ Geospatial API รับข้อมูลอัปเดตอย่างต่อเนื่องเกี่ยวกับตำแหน่งของผู้ใช้

    produceState<AppStatus>(Initializing) {
      val geospatial = Geospatial.getInstance(session)
    
      val wait = geospatial.state.onEach {
         value = WaitingForGeospatial(it.geospatialTrackingState)
      }.first {
         it.geospatialTrackingState == Geospatial.GeospatialTrackingState.RUNNING
      }
    
      val accuracyWait = geospatial.state.onEach {
         value = WaitingForGeospatialAccuracy(it)
      }.first { it.horizontalAccuracy < horizontalAccuracyRequirement }
    
      value = WaitingForPlacesResults
      val result = client.findNearby(context, accWait.geospatialPose)
      value = Done(result)
    
    }
  • ดังนั้น เราจะเข้าถึงออบเจ็กต์เชิงพื้นที่ทางภูมิศาสตร์ผ่านเซสชัน XR

  • หลังจากนั้น เราจะรอให้ Geospatial เริ่มทำงานขณะที่เริ่มต้นเซ็นเซอร์ที่จำเป็นและเชื่อมต่อกับ Cloud API

  • จากนั้นเราจะรอให้ความแม่นยำถึงระดับหนึ่ง

  • ดังนั้น ระดับความแม่นยำจึงอาจดีขึ้นเมื่อมีการวัดค่า GPS หรือเมื่อระบบกำหนดตำแหน่งด้วยภาพพบข้อมูลที่ตรงกันในตำแหน่งของผู้ใช้

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

  • จากนั้นเราก็พร้อมที่จะทำการค้นหาด้วย Places API โดยใช้ค่าตำแหน่งจาก Geospatial API

    val bounds = CircularBounds.newInstance(
      LatLng(pose.latitude, pose.longitude),
      100.0, // radius, in meters
    )
    val placeFields = listOf(
      Place.Field.ID, Place.Field.DISPLAY_NAME,
      Place.Field.RATING, Place.Field.LOCATION,
    )
    return placesClient.searchNearby(
      SearchNearbyRequest.builder(bounds, placeFields)
        .setIncludedTypes(listOf(PlaceTypes.CAFE))
        .setMaxResultCount(10)
        .build()
    ).await()
  • ดังนั้น เราจะใช้ SearchNearbyRequest กับ Places API เพื่อค้นหาสถานที่รอบๆ ตำแหน่งของผู้ใช้ที่เราได้รับมาก่อนหน้านี้ และเราจะค้นหาผลลัพธ์ภายในระยะ 100 เมตร

  • เราจะดึงรหัสของสถานที่ ชื่อที่แสดง คะแนน และตำแหน่งของสถานที่นั้น

  • และสุดท้าย เราจะทำการค้นหาด้วยพารามิเตอร์ที่ระบุ รวมถึงตัวกรองประเภทสถานที่

  • ข้อมูลก็มีเพียงเท่านี้ ต่อไปเราจะกลับไปที่ UI

  • ดังนั้นเราจะต้องหาวิธีวางเครื่องหมายและกล่องข้อมูลจากก่อนหน้านี้ และเราจะใช้ Anchor เชิงพื้นที่สำหรับสิ่งนั้น

  • กลับมาที่โค้ดอีกครั้ง เราจะเข้าถึง Geospatial API โดยใช้เซสชัน XR จากนั้นเราจะสร้าง Anchor เชิงพื้นที่โดยใช้ละติจูดและลองจิจูดที่เฉพาะเจาะจงซึ่งได้จากผลการค้นหาก่อนหน้านี้

    val anchorResult by produceState<AnchorResult?>(null) {
     val geospatial = Geospatial.getInstance(session)
     value = geospatial.createAnchorOnSurface(
       place.location.latitude, place.location.longitude,
       surface = GeospatialSurface.TERRAIN,
       altitudeAboveSurface = 3.0,
       eastUpSouthQuaternion = Quaternion()
     )
    }
  • ดังนั้นในตัวอย่างนี้ เราได้ระบุระดับความสูงไว้ที่ 3 เมตรเหนือภูมิประเทศที่พิกัดเหล่านั้น แต่คุณยังสามารถแนบกับหลังคาที่รองรับได้ด้วย ซึ่งหมายความว่าระบบจะกำหนดค่าระดับความสูงโดยสัมพันธ์กับหลังคาของอาคารที่ตำแหน่งนั้น

  • ดังนั้น คุณยังสามารถหมุน Anchor โดยใช้ควอเทอร์เนียน ซึ่งระบุค่าการหมุนของ Anchor ได้ด้วย

  • แต่เราจะใช้ค่าเริ่มต้นในตัวอย่างนี้เนื่องจากเราจะทำให้ UI หมุนไปหาผู้ใช้

  • จากนั้นเราจะแนบ UI ของ Glimmer จากก่อนหน้านี้เข้ากับ Anchor นี้ ซึ่งจะช่วยให้คุณมีองค์ประกอบพื้นฐานสำหรับประสบการณ์ที่ยึดตามพื้นที่

    when (anchorResult) {
     is AnchorCreateSuccess ->
       Subspace(FollowTarget.anchor(anchorResult.anchor)) {
         SpatialPanel(SubspaceModifier.rotateToLookAtUser()) {
           PlaceIndicator(place)
         }
       }
    
     else ->
       Log.e("Demo", "Failed to create anchor $anchorResult")
    }
  • ดังนั้นเราจึงเชื่อว่า Geospatial API จะช่วยมอบประสบการณ์การค้นหาเส้นทางที่ยอดเยี่ยม และการออกแบบด้วย Glimmer จะช่วยสร้างประสบการณ์ของผู้ใช้ที่เข้าใจง่ายซึ่งสร้างขึ้นมาเพื่อจอแสดงผลแบบโปร่งใสโดยเฉพาะ

  • ดูข้อมูลเพิ่มเติมเกี่ยวกับ Geospatial API ได้ที่ developer.android.com/xr ซึ่งอัปเดตล่าสุด

  • และฉันจะส่งต่อให้ Yasmine เพื่อสรุปช่วงสุดท้าย

สรุปและแหล่งข้อมูลสำหรับนักพัฒนาซอฟต์แวร์

  • ในเซสชันนี้ เราได้พูดถึงความสามารถบางอย่างของ Android XR ได้แก่ ARCore สำหรับ Jetpack XR และ Jetpack Compose Glimmer

  • เราตื่นเต้นกับฟีเจอร์ใหม่ๆ ที่ Android XR จะนำมาสู่แว่นตา XR แบบใช้สาย

  • นักพัฒนาแอปกำลังสร้างแอปสำหรับ Android XR อยู่แล้ว และเราหวังว่าจะได้เห็นผลงานสร้างสรรค์ของคุณใน Google Play Store

  • หากต้องการเริ่มต้นใช้งาน โปรดดูเอกสารประกอบสำหรับนักพัฒนาซอฟต์แวร์ของเรา รับแรงบันดาลใจจากการทดสอบ XR และเริ่มใช้งานด้วย Codelab

  • เราได้วางแผนเซสชัน XR, การสาธิต และเวิร์กช็อปที่ยอดเยี่ยมไว้มากมายสำหรับคุณทุกคน

  • โปรดติดตามและดูข้อมูลเกี่ยวกับการสร้างแอปสำหรับ Android XR ในประสบการณ์การใช้งานแบบสมจริงและเทคโนโลยีความจริงเสริม (AR)

  • ในนามของทีม Android XR ขอขอบคุณทุกท่านที่มาร่วมงานในวันนี้ และหวังว่าคุณจะเพลิดเพลินกับช่วงเวลาที่เหลือในงาน Android Developer Summit

  • ขอบคุณมาก

รหัส

ข้อมูลโค้ด

ข้อมูลโค้ด Shell ที่ 04:39 ใน "การสร้าง UI ด้วย Jetpack Compose Glimmer"
android skills add display-glasses-with-jetpack-compose-glimmer
ข้อมูลโค้ด Kotlin ที่นาที 05:49 ใน "การสร้าง UI ด้วย Jetpack Compose Glimmer"
val brandColor = Color(0xFFFFAABB)
val focusedColor = ButtonDefaults.focusedColor(brandColor)

Column(…) {
   LeadingImageCard(
       focusable = false,
       …
   ) {
       …
   }
   ButtonGroup(...) {
       Button(
           onClick = {},
           leadingIcon = { … },
           focusedColor = focusedColor,
       ) { Text("Add to cart") }

       /* Rest of the buttons */
   }
}
ข้อมูลโค้ด Kotlin ที่ 08:37 ใน "หลักการออกแบบ UI สำหรับแว่นตาที่มีจอแสดงผล"
val pagerState =
  rememberGlimmerPagerState(pageCount = { 10 })

GlimmerHorizontalPager(pagerState) { page ->
   /* Card Content */
}
ข้อมูลโค้ด Kotlin ที่นาที 09:50 ใน "หลักการออกแบบ UI สำหรับแว่นตาที่มีจอแสดงผล"
ButtonGroup {
   Button(onClick = {}) { Text("Button 1") }
   Button(onClick = {}) { Text("Button 2") }
   Button(onClick = {}) { Text("Button 3") }
   Button(onClick = {}) { Text("Button 4") }
   Button(onClick = {}) { Text("Button 5") }
}
ข้อมูลโค้ด Kotlin ที่นาที 10:13 ใน "หลักการออกแบบ UI สำหรับแว่นตาที่มีจอแสดงผล"
var buttonChecked by remember { mutableStateOf(false) }

ToggleButton(
  checked = buttonChecked,
  leadingIcon = { Icon(FavoriteIcon) },
  onCheckedChange = { buttonChecked = it }
) {
  Text(if (buttonChecked) "On" else "Off")
}
ข้อมูลโค้ด Kotlin ที่ 13:55 ใน "ภาพรวมของ Anchor ตามตำแหน่ง"
Subspace {
  SpatialPanel {
    VideoPlayer()
  }
}
ข้อมูลโค้ด Kotlin ที่นาที 14:16 ใน "ภาพรวมของ Anchor ตามตำแหน่ง"
val state by
  qrCode.state.collectAsState()
Subspace(FollowTarget.anchor(anchor)) {
  SpatialPanel {
    Row {
      IndicatorDot()
      Spacer()
      QrCodeCard(state)
    }
  }
}
ข้อมูลโค้ด Kotlin ที่นาที 16:43 ใน "Geospatial API and Google Maps Platform integration"
produceState<AppStatus>(Initializing) {
  val geospatial = Geospatial.getInstance(session)

  val wait = geospatial.state.onEach {
     value = WaitingForGeospatial(it.geospatialTrackingState)
  }.first {
     it.geospatialTrackingState == Geospatial.GeospatialTrackingState.RUNNING
  }

  val accuracyWait = geospatial.state.onEach {
     value = WaitingForGeospatialAccuracy(it)
  }.first { it.horizontalAccuracy < horizontalAccuracyRequirement }

  value = WaitingForPlacesResults
  val result = client.findNearby(context, accWait.geospatialPose)
  value = Done(result)

}
ข้อมูลโค้ด Kotlin ที่นาที 17:27 ใน "การผสานรวม Geospatial API และ Google Maps Platform"
val bounds = CircularBounds.newInstance(
  LatLng(pose.latitude, pose.longitude),
  100.0, // radius, in meters
)
val placeFields = listOf(
  Place.Field.ID, Place.Field.DISPLAY_NAME,
  Place.Field.RATING, Place.Field.LOCATION,
)
return placesClient.searchNearby(
  SearchNearbyRequest.builder(bounds, placeFields)
    .setIncludedTypes(listOf(PlaceTypes.CAFE))
    .setMaxResultCount(10)
    .build()
).await()
ข้อมูลโค้ด Kotlin ที่นาที 18:09 ใน "การผสานรวม Geospatial API และ Google Maps Platform"
val anchorResult by produceState<AnchorResult?>(null) {
 val geospatial = Geospatial.getInstance(session)
 value = geospatial.createAnchorOnSurface(
   place.location.latitude, place.location.longitude,
   surface = GeospatialSurface.TERRAIN,
   altitudeAboveSurface = 3.0,
   eastUpSouthQuaternion = Quaternion()
 )
}
ข้อมูลโค้ด Kotlin ที่ 18:53 ใน "การผสานรวม Geospatial API และ Google Maps Platform"
when (anchorResult) {
 is AnchorCreateSuccess ->
   Subspace(FollowTarget.anchor(anchorResult.anchor)) {
     SpatialPanel(SubspaceModifier.rotateToLookAtUser()) {
       PlaceIndicator(place)
     }
   }

 else ->
   Log.e("Demo", "Failed to create anchor $anchorResult")
}