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
lubandroid: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 uprawnienieACCESS_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łudzeSettings.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
iandroid:minSdkVersion
są mniejsze niż 17, aplikacja nie może modyfikować ustawień, które została przeniesiona doSettings.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 parametrtargetSdkVersion
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 koncieWebView
z Androidem 4.2 lub nowszym. Jeśli ustawisz parametrtargetSdkVersion
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:
- Aby uzyskać dostęp do pamięci wewnętrznej, użyj aplikacji
getFilesDir()
,getCacheDir()
lubopenFileOutput()
. - Aby uzyskać dostęp do pamięci zewnętrznej, użyj
getExternalFilesDir()
lubgetExternalStoragePublicDirectory()
.
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:
- 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 miejsceandroid:layout_marginLeft
iandroid:layout_marginEnd
zamiastandroid: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ąpandroid:layout_alignParentLeft
iandroid:layout_toStartOf
zamiastandroid:layout_toLeftOf
. - 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 aplikacjires/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:
Blends
Blur
Color matrix
3x3 convolve
5x5 convolve
Per-channel lookup table
Converting an Android YUV buffer to RGB
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 numerset()
w ramach poszczególnych skryptów w celu ustawienia niezbędnych danych wejściowych i opcji. Na koniec wywołajforEach()
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 numeraddKernel()
. 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 numercreate()
aby utworzyć grupę skryptów. Przed wykonaniem grupy skryptów określ dane wejścioweAllocation
i początkowy skrypt do uruchomienia zsetInput(Script.KernelID, Allocation)
i podaj dane wyjściowe.Allocation
, w którym zostanie zapisany wynik, a skrypt końcowy na uruchomienia zsetOutput()
. Na koniec wywołajexecute()
, 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 funkcjiroot()
.
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.