Tworzenie pierwszego działania na potrzeby okularów AI

Obsługiwane urządzenia z XR
Ten przewodnik pomoże Ci tworzyć aplikacje na te typy urządzeń z XR.
Okulary z AI

Aplikacja na okulary z AI jest oparta na istniejącym interfejsie API Activity framework API na Androidzie i zawiera dodatkowe koncepcje, które obsługują unikalne aspekty okularów z AI. W przeciwieństwie do gogli XR, które uruchamiają pełny pakiet APK na urządzeniu, okulary z AI używają specjalnej aktywności, która działa w ramach istniejącej aplikacji na telefonie. Ta aktywność jest wyświetlana z urządzenia hosta na okulary z AI.

Aby utworzyć aplikację na okulary z AI, rozszerz istniejącą aplikację na telefon tworząc nową aktywność Activity wyświetlaną na okularach z AI. Ta aktywność służy jako główny punkt wejścia do aplikacji na okularach z AI. Takie podejście upraszcza proces tworzenia, ponieważ możesz udostępniać i ponownie wykorzystywać logikę biznesową między aplikacjami na telefon i okulary z AI.

Zgodność wersji

Sprawdź wymagania dotyczące zgodności pakietu Android SDK z pakietem Jetpack XR SDK.

Zależności

Dodaj te zależności biblioteki dla okularów z AI:

Dynamiczny

dependencies {
    implementation "androidx.xr.runtime:runtime:1.0.0-alpha12"
    implementation "androidx.xr.glimmer:glimmer:1.0.0-alpha11"
    implementation "androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha11"
    implementation "androidx.xr.projected:projected:1.0.0-alpha06"
    implementation "androidx.xr.arcore:arcore:1.0.0-alpha12"
}

Kotlin

dependencies {
    implementation("androidx.xr.runtime:runtime:1.0.0-alpha12")
    implementation("androidx.xr.glimmer:glimmer:1.0.0-alpha11")
    implementation("androidx.xr.glimmer:glimmer-google-fonts:1.0.0-alpha11")
    implementation("androidx.xr.projected:projected:1.0.0-alpha06")
    implementation("androidx.xr.arcore:arcore:1.0.0-alpha12")
}

Zadeklaruj aktywność w pliku manifestu aplikacji

Podobnie jak w przypadku innych typów aktywności, musisz zadeklarować aktywność w pliku manifestu aplikacji, aby system mógł ją zobaczyć i uruchomić.

<application>
  <activity
      android:name="com.example.xr.projected.GlassesMainActivity"
      android:exported="true"
      android:requiredDisplayCategory="xr_projected"
      android:label="Example AI Glasses activity">
      <intent-filter>
          <action android:name="android.intent.action.MAIN" />
      </intent-filter>
  </activity>
</application>

Najważniejsze informacje o kodzie

  • Określa xr_projected dla atrybutu android:requiredDisplayCategory aby poinformować system, że ta aktywność powinna używać kontekstu wyświetlanego do uzyskiwania dostępu do sprzętu z podłączonego urządzenia.

Utwórz aktywność

Następnie utworzysz małą aktywność, która może wyświetlać coś na okularach z AI, gdy wyświetlacz jest włączony.

@OptIn(ExperimentalProjectedApi::class)
class GlassesMainActivity : ComponentActivity() {

    private var displayController: ProjectedDisplayController? = null
    private var isVisualUiSupported by mutableStateOf(false)
    private var areVisualsOn by mutableStateOf(true)
    private var isPermissionDenied by mutableStateOf(false)

    // Register the permissions launcher using the ProjectedPermissionsResultContract.
    private val requestPermissionLauncher: ActivityResultLauncher<List<ProjectedPermissionsRequestParams>> =
        registerForActivityResult(ProjectedPermissionsResultContract()) { results ->
            if (results[Manifest.permission.CAMERA] == true) {
                isPermissionDenied = false
                initializeGlassesFeatures()
            } else {
                // Handle permission denial.
                isPermissionDenied = true
            }
        }

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

        lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onDestroy(owner: LifecycleOwner) {
                displayController?.close()
                displayController = null
            }
        })

        if (hasCameraPermission()) {
            initializeGlassesFeatures()
        } else {
            requestHardwarePermissions()
        }

        setContent {
            GlimmerTheme {
                HomeScreen(
                    areVisualsOn = areVisualsOn,
                    isVisualUiSupported = isVisualUiSupported,
                    isPermissionDenied = isPermissionDenied,
                    onRetryPermission = { requestHardwarePermissions() },
                    onClose = { finish() }
                )
            }
        }
    }

    private fun initializeGlassesFeatures() {
        lifecycleScope.launch {
            // Check device capabilities
            val projectedDeviceController = ProjectedDeviceController.create(this@GlassesMainActivity)
            isVisualUiSupported = projectedDeviceController.capabilities.contains(CAPABILITY_VISUAL_UI)

            val controller = ProjectedDisplayController.create(this@GlassesMainActivity)
            displayController = controller
            val observer = GlassesLifecycleObserver(
                context = this@GlassesMainActivity,
                controller = controller,
                onVisualsChanged = { visualsOn -> areVisualsOn = visualsOn }
            )
            lifecycle.addObserver(observer)
        }
    }

    private fun hasCameraPermission(): Boolean {
        return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) ==
                PackageManager.PERMISSION_GRANTED
    }

    private fun requestHardwarePermissions() {
        val params = ProjectedPermissionsRequestParams(
            permissions = listOf(Manifest.permission.CAMERA),
            rationale = "Camera access is required to overlay digital content on your physical environment."
        )
        requestPermissionLauncher.launch(listOf(params))
    }
}

Najważniejsze informacje o kodzie

  • Wybiera korzystanie z interfejsów API w bibliotece Jetpack Projected.
  • GlassesMainActivity rozszerza ComponentActivity, tak jak można oczekiwać w przypadku tworzenia aplikacji mobilnych.
  • Ponieważ nie wszystkie okulary z AI mają wyświetlacz, sprawdza, czy urządzenie ma wyświetlacz, za pomocą ProjectedDeviceController.
  • Blok setContent w funkcji onCreate definiuje główny element drzewa interfejsu użytkownika Composable dla aktywności. Zaimplementujesz element HomeScreen composable za pomocą Jetpack Compose Glimmer.
  • Inicjuje interfejs użytkownika podczas metody onCreate aktywności (zobacz cykl życia działania).
  • Aby przygotować się na funkcje związane z aparatem, które mają dostęp do sprzętu okularów, prosi o uprawnienia do sprzętu przez zarejestrowanie modułu uruchamiającego uprawnienia, zdefiniowanie funkcji hasCameraPermission i requestHardwarePermissions oraz sprawdzenie, czy uprawnienia zostały przyznane przed wywołaniem initializeGlassesFeatures.

Zaimplementuj element Composable

Utworzona aktywność odwołuje się do funkcji typu „composable” HomeScreen, którą musisz zaimplementować. Poniższy kod używa Jetpack Compose Glimmer do zdefiniowania elementu Composable, który może wyświetlać tekst na wyświetlaczu okularów z AI:

@Composable
fun HomeScreen(
    areVisualsOn: Boolean,
    isVisualUiSupported: Boolean,
    isPermissionDenied: Boolean,
    onRetryPermission: () -> Unit,
    onClose: () -> Unit,
    modifier: Modifier = Modifier
) {
    Box(
        modifier = modifier
            .surface(focusable = false)
            .fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        if (isPermissionDenied) {
            Card(
                title = { Text("Permission Required") },
                action = { Button(onClick = onClose) { Text("Exit") } }
            ) {
                Text("Camera access is needed to use AI glasses features.")
                Button(onClick = onRetryPermission) { Text("Retry") }
            }
        } else if (isVisualUiSupported) {
            Card(
                title = { Text("Android XR") },
                action = {
                    Button(onClick = onClose) {
                        Text("Close")
                    }
                }
            ) {
                if (areVisualsOn) {
                    Text("Hello, AI Glasses!")
                } else {
                    Text("Display is off. Audio guidance active.")
                }
            }
        } else {
            Text("Audio Guidance Mode Active")
        }
    }
}

Najważniejsze informacje o kodzie

  • Jak zdefiniowano wcześniej w aktywności, funkcja HomeScreen zawiera treść Composable, którą użytkownik widzi, gdy wyświetlacz okularów z AI jest włączony.
  • Komponent Text Jetpack Compose Glimmer wyświetla tekst "Hello, AI Glasses!" na wyświetlaczu okularów.
  • Komponent Button Jetpack Compose Glimmer zamyka aktywność, wywołując finish() przez onClose w aktywności okularów z AI.

Sprawdź, czy okulary z AI są połączone

Aby sprawdzić, czy okulary z AI użytkownika są połączone z jego telefonem przed uruchomieniem aktywności, użyj ProjectedContext.isProjectedDeviceConnected metody. Ta metoda zwraca Flow<Boolean>, którą aplikacja może obserwować, aby otrzymywać aktualizacje w czasie rzeczywistym dotyczące stanu połączenia.

Uruchom aktywność

Teraz, gdy masz już podstawową aktywność, możesz ją uruchomić na okularach. Aby uzyskać dostęp do sprzętu okularów, aplikacja musi uruchomić aktywność z określonymi opcjami, które informują system o użyciu kontekstu wyświetlanego, jak pokazano w tym kodzie:

val options = ProjectedContext.createProjectedActivityOptions(context)
val intent = Intent(context, GlassesMainActivity::class.java)
context.startActivity(intent, options.toBundle())

Metoda createProjectedActivityOptions w ProjectedContext generuje opcje niezbędne do uruchomienia aktywności w kontekście wyświetlanym. Parametr context może być kontekstem z telefonu lub okularów.

Dalsze kroki

Teraz, gdy masz już pierwszą aktywność na okulary z AI, możesz poznać inne sposoby rozszerzania jej funkcjonalności: