Nie tylko pojedyncze funkcje: gwarancja kombinacji funkcji w CameraX 1.5
Czas czytania: 6 minut
Nowoczesne aplikacje aparatu charakteryzują się zaawansowanymi, nakładającymi się na siebie funkcjami. Użytkownicy oczekują, że będą mogli nagrywać filmy w oszałamiającym HDR, rejestrować płynny ruch z szybkością 60 kl./s i uzyskiwać płynne materiały dzięki stabilizacji podglądu – często jednocześnie.
Jako programiści wiemy, że rzeczywistość jest bardziej skomplikowana. Jak możesz zagwarantować, że dane urządzenie faktycznie obsługuje daną kombinację? Do tej pory włączanie wielu funkcji było często loterią. Możesz sprawdzić obsługę poszczególnych funkcji, ale ich połączenie może prowadzić do niezdefiniowanego zachowania lub, co gorsza, do nieudanej sesji aparatu. Ta niepewność zmusza programistów do zachowawczości, co uniemożliwia użytkownikom urządzeń z odpowiednimi możliwościami korzystanie z najlepszych możliwych funkcji.
Na przykład bardzo niewiele urządzeń premium niezawodnie obsługuje jednocześnie HDR i wideo z szybkością 60 kl./s. W związku z tym większość aplikacji unika jednoczesnego włączania obu tych funkcji, aby zapobiec pogorszeniu komfortu użytkowania na większości telefonów.
Aby rozwiązać ten problem, wprowadzamy grupę funkcji w CameraX – nowy interfejs API, który ma wyeliminować te domysły. Możesz teraz sprawdzić, czy dana kombinacja funkcji jest obsługiwana przed skonfigurowaniem aparatu, lub po prostu określić priorytety w CameraX i pozwolić mu włączyć najlepiej obsługiwaną kombinację.
Dla osób, które dopiero zaczynają korzystać z CameraX
Zanim przejdziemy do nowego interfejsu Feature Group API, przypomnijmy sobie, czym jest CameraX. CameraX to biblioteka obsługi Jetpack, która ułatwia tworzenie aplikacji aparatu. Zapewnia spójny i łatwy w użyciu interfejs API, który działa na większości urządzeń z Androidem i jest wstecznie zgodny z Androidem 6.0 (poziom interfejsu API 23). Jeśli dopiero zaczynasz korzystać z CameraX, zalecamy zapoznanie się z oficjalną dokumentacją i wypróbowanie codelabu.
Co możesz tworzyć za pomocą interfejsu Feature Group API
Nie musisz już zgadywać, jakie kombinacje funkcji będą działać. Możesz z pewnością oferować najlepsze możliwe funkcje aparatu, takie jak jednoczesne nagrywanie w HDR i z szybkością 60 kl./s na odpowiednim sprzęcie (np. Pixel 10 Pro), a jednocześnie unikać błędów na urządzeniach, które nie obsługują tej kombinacji.
Za pomocą interfejsu Feature Group API możesz:
- Tworzyć inteligentniejsze, dynamiczne interfejsy: inteligentnie włączać i wyłączać ustawienia w interfejsie na podstawie obsługi sprzętu w czasie rzeczywistym. Jeśli na przykład użytkownik włączy HDR, możesz natychmiast wyszarzyć i wyłączyć opcję 60 kl./s, jeśli ta kombinacja nie jest obsługiwana na danym urządzeniu.
- Zapewniać niezawodny tryb „Wysoka jakość”: skonfiguruj aparat za pomocą listy pożądanych funkcji uporządkowanej według priorytetu. CameraX automatycznie znajduje i włącza najlepiej obsługiwaną kombinację dla danego urządzenia, zapewniając doskonały efekt bez złożonej logiki specyficznej dla urządzenia.
- Zapobiegać awariom sesji aparatu: dzięki wcześniejszemu sprawdzeniu obsługi zapobiegasz próbom skonfigurowania nieobsługiwanej kombinacji przez aparat, co eliminuje częste przyczyny awarii i zapewnia płynne działanie.
Jak to działa: podstawowe komponenty
Nowy interfejs API opiera się na kluczowych dodatkach do SessionConfig i CameraInfo.
- GroupableFeature: ten interfejs API wprowadza zestaw wstępnie zdefiniowanych funkcji, które można grupować, takich jak HDR_HLG10, FPS_60, PREVIEW_STABILIZATION i IMAGE_ULTRA_HDR. Ze względu na ograniczenia obliczeniowe tylko określony zestaw funkcji można grupować z wysokim stopniem niezawodności, jaki zapewnia ten interfejs API. Aktywnie pracujemy nad rozszerzeniem tej listy i w przyszłych wersjach wprowadzimy obsługę większej liczby funkcji.
- Nowe parametry SessionConfig: ta klasa, która służy do rozpoczynania sesji aparatu, akceptuje teraz 2 nowe parametry:
requiredFeatureGroup: używaj tego parametru w przypadku funkcji, które muszą być obsługiwane, aby konfiguracja się powiodła. Jest to idealne rozwiązanie w przypadku funkcji, które użytkownik włącza bezpośrednio, np. przełączając przełącznik „HDR”. Aby zapewnić deterministyczne i spójne działanie, wywołaniebindToLifecyclezgłosi wyjątekIllegalArgumentException, jeśli żądana kombinacja nie jest obsługiwana, zamiast ignorować żądanie funkcji. Aby wcześniej sprawdzić ten wynik, użyj interfejsuCameraInfo#isFeatureGroupSupportedAPI (szczegóły poniżej).preferredFeatureGroup: używaj tego parametru w przypadku funkcji, które są pożądane, ale opcjonalne, np. gdy chcesz wdrożyć domyślny tryb „Wysoka jakość”. Podajesz listę pożądanych funkcji uporządkowaną według priorytetów, a CameraX automatycznie włącza kombinację o najwyższym priorytecie, którą obsługuje urządzenie.
- CameraInfo#isFeatureGroupSupported(): jest to podstawowa metoda sprawdzania, czy grupa funkcji jest obsługiwana. Jest ona odpowiednia do udostępniania użytkownikom w interfejsie aplikacji tylko obsługiwanych opcji funkcji. Przekazujesz do niej
SessionConfig, a ona zwraca wartość logiczną wskazującą, czy kombinacja jest obsługiwana. Jeśli zamierzasz powiązaćSessionConfigz wymaganymi funkcjami, najpierw użyj tego interfejsu API, aby upewnić się, że jest on obsługiwany.
Implementacja w praktyce
Zobaczmy, jak używać tych komponentów do tworzenia lepszych funkcji aparatu.
Scenariusz 1. Tryb „Wysoka jakość”
Jeśli chcesz domyślnie włączyć najlepsze możliwe funkcje, możesz podać listę priorytetów w preferredFeatureGroup. W tym przykładzie informujemy CameraX, aby priorytetowo traktował HDR, następnie 60 kl./s, a na końcu stabilizację podglądu. CameraX zajmuje się złożonością sprawdzania wszystkich możliwych kombinacji i wybierania najlepszej, którą obsługuje urządzenie.
Jeśli na przykład urządzenie może obsługiwać HDR i 60 kl./s razem, ale nie ze stabilizacją podglądu, CameraX włączy pierwsze 2 funkcje i odrzuci trzecią. Dzięki temu możesz uzyskać najlepsze możliwe wrażenia bez pisania złożonych, specyficznych dla urządzenia sprawdzeń.
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
SessionConfig(
useCases = listOf(preview, videoCapture),
// The order of features in this list determines their priority.
// CameraX will enable the best-supported combination based on these
// priorities: HDR_HLG10 > FPS_60 > Preview Stabilization.
preferredFeatureGroup =
listOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION),
).apply {
// (Optional) Get a callback with the enabled features
// to update your UI.
setFeatureSelectionListener { selectedFeatures ->
updateUiIndicators(selectedFeatures)
}
}
)W przypadku tego fragmentu kodu CameraX będzie próbować włączyć kombinacje funkcji w tej kolejności priorytetów, wybierając pierwszą, którą urządzenie w pełni obsługuje:
- HDR + 60 kl./s + stabilizacja podglądu
- HDR + 60 kl./s
- HDR + stabilizacja podglądu
- HDR
- 60 kl./s + stabilizacja podglądu
- 60 kl./s
- Stabilizacja podglądu
- Żadna z powyższych funkcji
Scenariusz 2. Tworzenie reaktywnego interfejsu
Aby utworzyć interfejs, który reaguje na wybory użytkownika i uniemożliwia mu wybranie nieobsługiwanej kombinacji funkcji, możesz bezpośrednio sprawdzić obsługę. Poniższa funkcja sprawdza, które funkcje są niezgodne z bieżącymi wyborami użytkownika, co pozwala wyłączyć odpowiednie elementy interfejsu.
/**
* Returns a list of features that are NOT supported in combination
* with the currently selected features.
*/
fun getUnsupportedFeatures(
currentFeatures: Set<GroupableFeature>
): Set<GroupableFeature> {
val unsupportedFeatures = mutableSetOf<GroupableFeature>()
val appFeatureOptions = setOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION)
// Iterate over every available feature option in your app.
appFeatureOptions.forEach { featureOption ->
// Skip features the user has already selected.
if (currentFeatures.contains(featureOption)) return@forEach
// Check if adding this new feature is supported.
val isSupported = cameraInfo.isFeatureGroupSupported(
SessionConfig(
useCases = useCases,
// Check the new feature on top of existing ones.
requiredFeatureGroup = currentFeatures + featureOption
)
)
if (!isSupported) {
unsupportedFeatures.add(featureOption)
}
}
return unsupportedFeatures
}Następnie możesz połączyć tę logikę z ViewModel lub kontrolerem interfejsu, aby reagować na dane wejściowe użytkownika i ponownie powiązać aparat z konfiguracją, która na pewno będzie działać.
// Invoked when user turns some feature on/off.
fun onFeatureChange(currentFeatures: Set<GroupableFeature>) {
// Identify features that are unsupported with the current selection.
val unsupportedFeatures = getUnsupportedFeatures(currentFeatures)
// Update app UI so that users can't enable them.
updateDisabledFeatures(unsupportedFeatures)
// Since the UI now only allows selecting supported feature combinations,
// `currentFeatures` is always valid. This allows setting
// `requiredFeatureGroup` directly, without needing to re-check for
// support or set a feature selection listener.
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
SessionConfig(
useCases = listOf(preview, videoCapture),
requiredFeatureGroup = currentFeatures,
)
)
}Aby zobaczyć te koncepcje w działającej aplikacji, możesz zapoznać się z naszą wewnętrzną aplikacją testową. Zawiera ona pełną implementację obu opisanych powyżej scenariuszy: „Wysoka jakość” i „Reaktywny interfejs”.
Uwaga: jest to aplikacja testowa, a nie oficjalnie obsługiwany przykład. Chociaż jest to świetny punkt odniesienia dla interfejsu Feature Group API, nie został on dopracowany do użytku produkcyjnego.
Rozpocznij już dziś
Interfejs Feature Group API eliminuje niejasności związane z zaawansowanymi funkcjami aparatu. Dzięki deterministycznemu sposobowi sprawdzania obsługi funkcji możesz z pewnością tworzyć wydajniejsze i bardziej niezawodne aplikacje aparatu.
Interfejs API jest dostępny w wersji eksperymentalnej w CameraX 1.5, a w wersji 1.6 ma stać się w pełni stabilny. Wkrótce wprowadzimy też więcej obsługi i ulepszeń.
Więcej informacji znajdziesz w oficjalnej dokumentacji. Chętnie zobaczymy, co stworzysz, i czekamy na Twoje opinie. Podziel się z nami wrażeniami i zgłoś wszelkie problemy, korzystając z tych kanałów:
-
Wiadomości o usługachZapewnianie bezpiecznego korzystania z internetu i ochrona użytkowników przed szkodliwymi treściami to dla nas w Google Play priorytet.
Paul Feng • Czas czytania: 2 minuty -
Wiadomości o usługachDziś oficjalnie obchodzimy 5. rocznicę wydania Jetpack Compose 1.0. Od wersji 1.0, ogłoszonej 28 lipca 2021 r., do najnowszej wersji 1.11 interfejsy API znacznie się rozwinęły, dlatego chcemy to uczcić.
Rebecca Franks, Nick Butcher, Loryn Hairston • Czas czytania: 5 minut -
Wiadomości o usługachAndroid Studio Quail 2 jest już stabilny i gotowy do użycia w środowisku produkcyjnym. Wprowadza on zmiany w IDE dzięki równoczesnym przepływom pracy agenta, natywnie zintegrowanemu profilowaniu wycieków pamięci i świadomemu kontekstu usuwaniu awarii.
Amman Asfaw • Czas czytania: 3 minuty
Otrzymuj co tydzień najnowsze informacje o tworzeniu aplikacji na Androida na swoją skrzynkę odbiorczą.