Interfejsy API Androida 4.2

Poziom API: 17

Android 4.2 (JELLY_BEAN_MR1) to aktualizacja wersji Jelly Bean, która oferuje nowe funkcje dla użytkowników i aplikacji dla programistów. Dokument ten przedstawia najważniejsze i najważniejsze nowych, przydatnych interfejsach API dla programistów.

Jako deweloper aplikacji możesz pobrać obraz systemu Android 4.2 i platformę SDK Menedżera SDK. Jeśli Nie masz urządzenia z Androidem 4.2, na którym chcesz przetestować aplikację, użyj systemu Android 4.2. aby przetestować aplikację przy użyciu emulatora Androida. Następnie twórz aplikacje na platformie Androida 4.2 i zacznij korzystać z najnowszych interfejsów API.

Aby lepiej zoptymalizować aplikację na urządzeniach z Androidem 4.2, ustaw targetSdkVersion na "17", zainstaluj ją w obrazie systemu Android 4.2 przetestować ją, a następnie opublikować aktualizację z tą zmianą.

Ty można używać interfejsów API w Androidzie 4.2, a także obsługiwać starsze wersje przez dodanie w kodzie, które sprawdzają poziom interfejsu API systemu przed jego wykonaniem minSdkVersion nie obsługuje interfejsów API. Aby dowiedzieć się więcej o: zachowywania zgodności wstecznej można znaleźć w artykule Tworzenie zgodności wstecznej Interfejsy użytkownika.

Więcej informacji o sposobie działania poziomów interfejsu API znajdziesz w artykule Co to jest interfejs API Poziom?

Ważne zmiany w działaniu

Jeśli masz już opublikowaną aplikację na Androida, pamiętaj o tych kwestiach: zmiany, które mogą wpływać na działanie aplikacji:

  • Dane dostawców treści nie są już domyślnie eksportowane. Oznacza to, że domyślna wartość dla atrybutu android:exported ma teraz wartość “false". Jeśli ważne jest, aby inne aplikacje masz dostęp do dostawcy treści, musisz teraz skonfigurować android:exported="true".

    Ta zmiana zostanie wprowadzona tylko wtedy, gdy ustawisz w parametrze android:targetSdkVersion lub android:minSdkVersion wartość 17 lub większą. W przeciwnym razie domyślną wartością jest “true". nawet w Androidzie 4.2 lub nowszym.

  • W porównaniu z poprzednimi wersjami Androida wyniki dotyczące lokalizacji użytkownika mogą być mniej dokładne jeśli aplikacja prosi o uprawnienie ACCESS_COARSE_LOCATION, ale nie prosi o uprawnienie ACCESS_FINE_LOCATION.

    Aby spełnić oczekiwania użytkowników w zakresie prywatności, gdy Twoja aplikacja prosi o zgodę na przybliżoną (a nie dokładną) lokalizacją, system nie podaje szacunkowej lokalizacji użytkownika. w porównaniu z przecznicą.

  • Niektóre ustawienia urządzenia zdefiniowane przez użytkownika Settings.System są teraz tylko do odczytu. Jeśli Twoja aplikacja próbuje zapisać zmiany w ustawieniach zdefiniowanych w usłudze Settings.System, które zostały przeniesione do: Settings.Global, w przypadku Androida 4.2 i nowszych operacja zapisu będzie dyskretna.

    Nawet jeśli wartości parametrów android:targetSdkVersion i android:minSdkVersion są mniejsze niż 17, aplikacja nie może modyfikować ustawień, które została przeniesiona do Settings.Global w przypadku Androida 4.2 lub nowszego.

  • Jeśli Twoja aplikacja używa WebView, Android 4.2 ma dodatkową warstwę aby bezpieczniej powiązywać JavaScript ze Kod na Androida. Jeśli ustawisz parametr targetSdkVersion co najmniej 17, musisz teraz dodać adnotację @JavascriptInterface do dowolnej metody które mają być dostępne dla JavaScriptu (metoda musi też być publiczna). Jeśli nie podasz atrybutu adnotacja, metoda nie jest dostępna dla strony internetowej na Twoim koncie WebView z Androidem 4.2 lub nowszym. Jeśli ustawisz parametr targetSdkVersion do 16 lub niższej, adnotacja nie jest wymagana, ale zalecamy zaktualizowanie wersji docelowej i dodać adnotację, aby jeszcze bardziej zwiększyć bezpieczeństwo.

    Więcej informacji o wiązaniu z kodu JavaScript do kodu na Androidzie.

Daydream

Daydream to nowy interaktywny tryb wygaszacza ekranu na urządzenia z Androidem. Aktywuje się automatycznie gdy urządzenie znajduje się w stacji dokującej lub gdy jest nieaktywne po podłączeniu do ładowarki (zamiast wyłączać ekran). Daydream wyświetla jeden sen w danym momencie, co może być czysto wizualnym, pasywnym ekranem, który zamyka się po dotknięciu, lub może być interaktywny i responsywny. do pełnego zestawu zdarzeń wejściowych. Twoje sny są w procesie działania aplikacji i mają pełny dostęp do zestaw narzędzi interfejsu Androida, w tym widoki, układy i animacje, dzięki czemu są one bardziej elastyczne niż animowane tapety czy widżety aplikacji.

Aby utworzyć wymarzony sen dla Daydream, zaimplementuj podklasę DreamService. Interfejsy API usługi DreamService są zaprojektowane tak, aby były podobne do komponentów Activity. Aby określić interfejs użytkownika Dream, przekaż identyfikator zasobu układu lub View do setContentView() w dowolnym momencie po okno, np. z onAttachedToWindow() oddzwanianie.

Klasa DreamService udostępnia inne ważne wywołanie zwrotne cyklu życia. w podstawowych interfejsach API Service, takich jak onDreamingStarted(), onDreamingStopped() i onDetachedFromWindow(). Nie możesz zainicjować zadania DreamService na swoim jest uruchamiana automatycznie przez system.

Jeśli Twoje marzenie jest interaktywne, możesz uruchomić z niego aktywność, aby wysłać do niego użytkownika do interfejsu aplikacji, gdzie znajdziesz więcej szczegółów lub większą kontrolę. Możesz użyć finish(), aby zakończyć sen i wyświetlić użytkownikowi nowa aktywność.

Aby udostępnić systemowi wygaszacz ekranu, zadeklaruj DreamService za pomocą elementu <service> w pliku manifestu. Potem musisz uwzględnić filtr intencji z działaniem "android.service.dreams.DreamService". Na przykład:

<service android:name=".MyDream" android:exported="true"
    android:icon="@drawable/dream_icon" android:label="@string/dream_label" >
    <intent-filter>
        <action android:name="android.service.dreams.DreamService" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

Inne przydatne metody to DreamService warto wiedzieć:

  • setInteractive(boolean) określa, czy sen otrzymuje zdarzenia wejściowe lub znika natychmiast po wprowadzeniu przez użytkownika danych wejściowych. Jeśli marzenie to użytkownik może nacisnąć przycisk Wstecz lub Ekran główny, by wyjść ze snu, albo zadzwonić finish(), aby zatrzymać marzenie.
  • Jeśli chcesz uzyskać w pełni pełny wyświetlacz, wywołaj setFullscreen(), by ukryć pasek stanu.
  • Przed uruchomieniem wygaszacza ekranu ekran przyciemnia się, by zasygnalizować użytkownikowi, że upłynął limit czasu bezczynności zbliża się wielkimi krokami. Gdy zadzwonisz pod setScreenBright(true), możesz ustawić standardową jasność wyświetlacza.

Więcej informacji znajdziesz w dokumentacji DreamService.

Wyświetlacze dodatkowe

Android pozwala teraz aplikacji wyświetlać unikalne treści na dodatkowych, połączonych ekranach z urządzenia użytkownika, korzystając z połączenia przewodowego lub Wi-Fi. Aby utworzyć unikalną treść na potrzeby dodatkowego wyświetlacza, rozwiń Presentation i zaimplementuj wywołanie zwrotne onCreate(). W ciągu onCreate(), określ interfejs dla wyświetlacza dodatkowego , dzwoniąc pod numer setContentView(). Jako rozszerzenie klasy Dialog klasa Presentation określa region, w którym aplikacja może wyświetlać unikalny interfejs użytkownika dodatkowy wyświetlacz.

Aby wykrywać ekrany dodatkowe, na których można wyświetlić Presentation, użyj komponentu DisplayManager lub MediaRouter API. Interfejsy API DisplayManager umożliwiają natomiast wielu wyświetlaczy, które można podłączyć jednocześnie, zwykle lepiej jest używać interfejsu MediaRouter, aby szybko uzyskać dostęp do domyślnego wyświetlacza systemu prezentacje.

Aby uzyskać domyślny sposób wyświetlania prezentacji, wywołaj MediaRouter.getSelectedRoute() i przekaż go ROUTE_TYPE_LIVE_VIDEO Zwraca obiekt MediaRouter.RouteInfo, który opisuje aktualnie wybraną trasę przez system w prezentacjach wideo. Jeśli MediaRouter.RouteInfo nie ma wartości null, wywołaj getPresentationDisplay(), aby wyświetlić Display reprezentujący połączony wyświetlacz.

Następnie możesz wyświetlić prezentację, przekazując obiekt Display do konstruktora klasy Presentation. Prezentacja będzie teraz na wyświetlaczu dodatkowym.

Aby wykrywać w czasie działania podłączenie nowego wyświetlacza, utwórz instancję MediaRouter.SimpleCallback z zaimplementowaną metodą wywołania zwrotnego onRoutePresentationDisplayChanged(), którą system będzie wywoływał po Podłączono wyświetlacz prezentacji. Następnie zarejestruj MediaRouter.SimpleCallback, przekazując go do usługi MediaRouter.addCallback() wraz z typem trasy ROUTE_TYPE_LIVE_VIDEO. Gdy ktoś do Ciebie zadzwoni onRoutePresentationDisplayChanged(), po prostu zadzwoń pod MediaRouter.getSelectedRoute() zgodnie z opisem powyżej.

Aby jeszcze bardziej zoptymalizować interfejs użytkownika Presentation dla ekranów dodatkowych, możesz zastosować inny motyw, określając atrybut android:presentationTheme w <style>, który został przez Ciebie do aplikacji lub aktywności.

Pamiętaj, że ekrany podłączone do urządzeń często mają większy rozmiar, i innej gęstości ekranu. Charakterystyka ekranu może się różnić, dlatego które są zoptymalizowane pod kątem takich dużych ekranów. Jeśli potrzebujesz , aby zażądać dodatkowych zasobów z Presentation, wywołaj getContext().getResources() w celu pobrania obiektu Resources odpowiadającego wyświetlaczowi. Dzięki temu odpowiednie zasoby aplikacji najlepiej dopasowane do do rozmiaru i gęstości ekranu dodatkowego.

Więcej informacji i przykładowe fragmenty kodu znajdziesz tutaj: Presentation dokumentacji zajęć.

Widżety ekranu blokady

Android pozwala teraz użytkownikom dodawać widżety aplikacji do ekranu blokady. Aby udostępnić widżet aplikacji w ekranu blokady, dodaj do pliku XML atrybut android:widgetCategory, który określa AppWidgetProviderInfo. Ten atrybut obsługuje 2 wartości: home_screen i keyguard. Domyślny atrybut to home_screen, więc użytkownicy mogą dodawać Twoje na ekranie głównym. Jeśli chcesz, aby widżet aplikacji był też dostępny na ekranie blokady , dodaj wartość keyguard:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:widgetCategory="keyguard|home_screen">
</appwidget-provider>

Musisz też określić początkowy układ widżetu aplikacji na ekranie blokady atrybut android:initialKeyguardLayout. Działa tak samo jak android:initialLayout, ponieważ zapewnia układ, który może pojawiać się od razu do momentu zainicjowania widżetu aplikacji i możliwości aktualizowania układ.

Więcej informacji o tworzeniu widżetów aplikacji na ekran blokady, w tym o do zmiany rozmiaru widżetu aplikacji na ekranie blokady znajdziesz w przewodniku Widżety aplikacji.

Wielu użytkowników

Android pozwala teraz na korzystanie z wielu przestrzeni użytkownika na urządzeniach, które można udostępniać, takich jak tablety. Każdy użytkownik urządzenie ma własny zestaw kont, aplikacji, ustawień systemu, plików i innych powiązane z nimi dane.

Jako deweloper aplikacji nie musisz nic robić, aby aplikacja działała z wieloma użytkownikami na 1 urządzeniu. Niezależnie od tego, ilu użytkowników urządzenia, dane zapisywane przez aplikację dla danego użytkownika są przechowywane oddzielnie od danych zapisywanych przez aplikację dla innych użytkowników. System śledzi, które dane użytkownika należą do procesu użytkownika, w którym aplikacja jest uruchomiona i zapewnia dostęp tylko do danych tego użytkownika dostęp do danych innych użytkowników.

Zapisywanie danych w środowisku obejmującym wielu użytkowników

Za każdym razem, gdy aplikacja zapisuje preferencje użytkownika, tworzy bazę danych lub zapisuje plik w w pamięci wewnętrznej lub zewnętrznej, dane te są dostępne tylko wtedy, gdy użytkownik działa jako ten użytkownik.

Aby mieć pewność, że aplikacja działa prawidłowo w środowisku, w którym jest wielu użytkowników, nie używaj wewnętrzny katalog aplikacji lub lokalizację w pamięci zewnętrznej za pomocą zakodowanych na stałe ścieżek, a zamiast tego zawsze używaj odpowiednich interfejsów API:

Niezależnie od tego, którego z tych interfejsów API użyjesz do zapisania danych konkretnego użytkownika, dane nie zostaną dostępne dla różnych użytkowników. Z perspektywy Twojej aplikacji każdy użytkownik jest uruchomiony. na całkowicie oddzielnym urządzeniu.

Identyfikowanie użytkowników w środowisku, w którym jest wielu użytkowników

Jeśli aplikacja chce identyfikować unikalnych użytkowników, np. zbierać dane analityczne lub tworzyć inne konta postępuj zgodnie z zalecanymi metodami identyfikowania stron unikalne instalacje. Tworząc nowy element UUID, gdy aplikacja uruchamia się dla najprawdopodobniej uzyskasz unikalny identyfikator do śledzenia każdego użytkownika, to użytkownicy instalują Twoją aplikację na jednym urządzeniu. Można też zapisać lokalny token pobrany z swojego serwera lub użyj identyfikatora rejestracji z Google Cloud Messaging.

Jeśli aplikacja prosi o jeden z identyfikatorów sprzętowych (np. MAC sieci Wi-Fi), adresu lub numeru SERIAL), zapewnią one tę samą wartość dla każdego z nich ponieważ są one powiązane ze sprzętem, a nie z użytkownikiem. Nie wspominając o tym drugim związane z tymi identyfikatorami, jak omówiono w sekcji Identyfikacja post na blogu o instalacjach aplikacji.

Nowe ustawienia globalne

Ustawienia systemu zostały zaktualizowane, aby obsługiwać wielu użytkowników dzięki dodaniu interfejsu Settings.Global. Ten zbiór ustawień jest podobny do ustawień Settings.Secure, ponieważ są one tylko do odczytu, ale obowiązują globalnie w całym wszystkie przestrzenie użytkownika na urządzeniu.

Kilka dotychczasowych ustawień zostało przeniesionych tutaj z urządzeń Settings.System lub Settings.Secure. Jeśli Twoja aplikacja jest obecnie wprowadzam zmiany w ustawieniach zdefiniowanych wcześniej na stronie Settings.System (takich jak AIRPLANE_MODE_ON), możesz się spodziewać Przestanie działać na urządzeniach z Androidem 4.2 lub nowszym, jeśli te ustawienia przeniesiono do folderu Settings.Global. Możesz nadal czytać ustawienia w sekcji Settings.Global, ale ponieważ ustawienia nie są już uważane za bezpieczne aplikacje, które mogą ulec zmianie, próba zaktualizowania tego błędu zakończy się po cichu, a system doda ostrzeżenie do dziennika systemowego w przypadku uruchomienia aplikacji na urządzeniu z Androidem 4.2 lub nowszym.

Obsługa układu od prawej do lewej

Android oferuje teraz kilka interfejsów API, które pozwalają tworzyć zmieniać orientację układu, aby zapewnić obsługę języków z interfejsami pisanymi od prawej do lewej oraz z czytaniem takich jak arabski i hebrajski.

Aby zacząć obsługiwać układy RTL w swojej aplikacji, ustaw atrybut android:supportsRtl na element <application> w pliku manifestu i ustaw tę wartość “true". Po włączeniu tej funkcji system włączy różne interfejsy API RTL, aby wyświetlać aplikację w układach od prawej do lewej, Na przykład na pasku działań będą widoczne ikona i tytuł oraz przyciski poleceń i działań po lewej stronie oraz układy utworzone za pomocą Klasy View udostępnione przez platformę również zostaną wycofane.

Jeśli musisz jeszcze bardziej zoptymalizować wygląd aplikacji w układzie od prawej do lewej, wyróżniamy 2 podstawowe poziomy optymalizacji:

  1. Konwertuj właściwości układu zorientowanego na lewą i prawą stronę na układ zorientowany na początek i koniec usług.

    Przykład: android:layout_marginStart w miejsce android:layout_marginLeft i android:layout_marginEnd zamiast android:layout_marginRight.

    Klasa RelativeLayout udostępnia też odpowiedni układ atrybuty umożliwiające zastąpienie pozycji lewa/prawa, np. android:layout_alignParentStart na zastąp android:layout_alignParentLeft i android:layout_toStartOf zamiast android:layout_toLeftOf.

  2. Aby zapewnić pełną optymalizację układów od prawej do lewej, możesz przesłać całkowicie osobne pliki układu z kwalifikatorem zasobów ldrtl (ldrtl oznacza układ-direction-right-to-left}). Pliki układu domyślnego możesz na przykład zapisać w Układy zoptymalizowane pod kątem rozmiaru RTL i od prawej do lewej w aplikacji res/layout/ w języku: res/layout-ldrtl/.

    Kwalifikator ldrtl świetnie sprawdza się w przypadku zasobów, które można przeciągać, dzięki czemu możesz podać grafiki zorientowane w kierunku zgodnym z kierunkiem czytania.

W ramach platformy dostępne są różne inne interfejsy API obsługujące układy RTL, takie jak klasy View, aby móc zaimplementować prawidłowe zachowania w przypadku i w Configuration, aby wysłać zapytanie dotyczące bieżącego kierunku układu.

Uwaga: jeśli używasz SQlite, a nazwy tabel lub kolumn są następujące "tylko liczba", być ostrożnie: użycie String.format(String, Object...) może spowodować błędy, gdzie liczby zostały przekonwertowane na odpowiedniki w języku arabskim, jeśli język urządzenia został ustawiony na arabski. Należy użyć funkcji String.format(Locale,String,Object...), aby zapewnić zachowywany jako ASCII. Możesz też używać atrybutu String.format("%d", int) zamiast String.valueOf(int) za formatowanie liczb.

Zagnieżdżone fragmenty

Teraz możesz umieszczać fragmenty wewnątrz fragmentów. Jest to przydatne w różnych sytuacjach: chcesz umieścić dynamiczne i przeznaczone do wielokrotnego użytku komponenty interfejsu w elemencie interfejsu, który sam w sobie. nadające się do wielokrotnego użytku. Jeśli na przykład używasz ViewPager do tworzy się fragmenty, które przesuwają w lewo i w prawo i zajmują większość miejsca na ekranie, wstaw fragmenty do każdej strony z fragmentami.

Aby zagnieździć fragment, wywołaj po prostu funkcję getChildFragmentManager() Fragment, do którego chcesz dodać fragment. Spowoduje to zwrócenie FragmentManager, którego możesz użyć w zwykły sposób w przypadku aktywności najwyższego poziomu. aby utworzyć transakcje fragment. Oto przykładowy kod, który dodaje fragment z wewnątrz istniejące zajęcia Fragment:

Kotlin

val videoFragment = VideoPlayerFragment()
childFragmentManager.beginTransaction().apply {
    add(R.id.video_fragment, videoFragment)
    commit()
}

Java

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

Z poziomu zagnieżdżonego fragmentu możesz uzyskać odwołanie do fragmentu nadrzędnego, wywołując getParentFragment()

Biblioteka pomocy Androida obsługuje też teraz zagnieżdżone fragmenty, projektowanie fragmentów w systemie Android 1.6 i nowszych.

Uwaga: nie możesz zwiększać zakresu układu, gdy ten układ zawiera element <fragment>. Zagnieżdżone fragmenty są obsługiwane tylko po dodaniu do fragment kodu w wyszukiwarce Google.

Skrypt renderowania

Ulepszyliśmy funkcję obliczeń w języku Renderscript o te funkcje:

Elementy skryptu

Możesz użyć wbudowanych funkcji skryptu Renderscript, typowe operacje, na przykład:

Aby użyć wbudowanego skryptu, wywołaj statyczną metodę create() każdego elementu wewnętrznego aby utworzyć instancję skryptu. Następnie dzwonisz pod dostępny numer set() w ramach poszczególnych skryptów w celu ustawienia niezbędnych danych wejściowych i opcji. Na koniec wywołaj forEach() do wykonania skryptu.

Grupy skryptów

Elementy ScriptGroup umożliwiają łączenie powiązanych ze sobą skryptów renderowania skryptów i wykonywać je za pomocą jednego wywołania.

Aby dodać wszystkie skrypty do grupy, użyj elementu ScriptGroup.Builder , dzwoniąc pod numer addKernel(). Gdy już dodaj wszystkie skrypty, utwórz połączenia między skryptów, wywołując metodę addConnection(). Po dodaniu wszystkich połączeń zadzwoń pod numer create() aby utworzyć grupę skryptów. Przed wykonaniem grupy skryptów określ dane wejściowe Allocation i początkowy skrypt do uruchomienia z setInput(Script.KernelID, Allocation) i podaj dane wyjściowe. Allocation, w którym zostanie zapisany wynik, a skrypt końcowy na uruchomienia z setOutput(). Na koniec wywołaj execute(), aby uruchomić grupę skryptów.

Skrypt filtra

Skrypt filtra definiuje ograniczenia dotyczące istniejących interfejsów API Renderscript, które umożliwiają uruchamianie kodu na większej liczbie procesorów (CPU, GPU i DSP). Aby tworzyć pliki w języku filtra, utwórz .fs plików zamiast .rs i określ #pragma rs_fp_relaxed do powiedz środowisku wykonawczym Renderscript, że Twoje skrypty nie wymagają ścisłej dokładności liczby zmiennoprzecinkowej IEEE 754–2008. Ta precyzja umożliwia przesuwanie do zera w przypadku denormów i zaokrąglanie do zera. Dodatkowo skrypt skrypty nie mogą korzystać z wbudowanych typów 32-bitowych i muszą określać niestandardową funkcję główną za pomocą funkcji __attribute__((kernel)), ponieważ skrypt filtra nie obsługuje wskaźników, które jest zdefiniowany domyślny podpis funkcji root().

Uwaga: chociaż na platformie jest dostępna obsługa skryptów, będzie dostępna w wersji 21.0.1 narzędzi SDK.

Szczegółowy widok wszystkich zmian interfejsu API w Androidzie 4.2 znajdziesz w Raport o różnicach w interfejsie API.