API-Level: 18
Android 4.3 (JELLY_BEAN_MR2
) ist ein Update der Jelly Bean-Version, das neue Funktionen für Nutzer und App-Entwickler bietet. Dieses Dokument bietet eine Einführung in die wichtigsten neuen APIs.
Als App-Entwickler sollten Sie das System-Image und die SDK-Plattform für Android 4.3 so schnell wie möglich aus dem SDK-Manager herunterladen. Wenn Sie zum Testen Ihrer App kein Gerät mit Android 4.3 haben, testen Sie die App mit dem System-Image von Android 4.3 im Android-Emulator. Erstellen Sie dann Ihre Apps auf der Plattform Android 4.3, um die neuesten APIs zu nutzen.
Ziel-API-Level aktualisieren
Wenn du deine App besser für Geräte mit Android 4.3 optimieren möchtest, solltest du targetSdkVersion
auf "18"
setzen, sie auf einem Android 4.3-System-Image installieren, testen und dann ein Update mit dieser Änderung veröffentlichen.
Sie können APIs in Android 4.3 verwenden und gleichzeitig ältere Versionen unterstützen. Fügen Sie Ihrem Code dazu Bedingungen hinzu, die das System-API-Level prüfen, bevor APIs ausgeführt werden, die von Ihrem minSdkVersion
nicht unterstützt werden.
Weitere Informationen zur Aufrechterhaltung der Abwärtskompatibilität findest du unter Unterstützung verschiedener Plattformversionen.
In der Supportbibliothek von Android sind verschiedene APIs verfügbar, mit denen Sie neue Funktionen in älteren Versionen der Plattform implementieren können.
Weitere Informationen zur Funktionsweise von API-Levels finden Sie unter Was ist ein API-Level?
Wichtige Verhaltensänderungen
Wenn du bereits eine App für Android veröffentlicht hast, solltest du beachten, dass deine App von Änderungen in Android 4.3 betroffen sein kann.
Wenn deine App implizite Intents verwendet...
Ihre App kann in einer Umgebung mit eingeschränktem Profil möglicherweise unerwünschtes Verhalten aufweisen.
Nutzer in einer Umgebung mit eingeschränkten Profilen haben möglicherweise nicht alle verfügbaren Android-Standardanwendungen. Bei einem eingeschränkten Profil können beispielsweise der Webbrowser und die Kamera-App deaktiviert sein. Ihre Anwendung sollte daher keine Annahmen darüber treffen, welche Anwendungen verfügbar sind. Wenn Sie startActivity()
aufrufen, ohne zu prüfen, ob eine Anwendung für die Verarbeitung von Intent
verfügbar ist, kann die Anwendung in einem eingeschränkten Profil abstürzen.
Wenn Sie einen impliziten Intent verwenden, sollten Sie immer dafür sorgen, dass eine App zur Verarbeitung des Intents verfügbar ist, indem Sie resolveActivity()
oder queryIntentActivities()
aufrufen. Beispiele:
Kotlin
val intent = Intent(Intent.ACTION_SEND) ... if (intent.resolveActivity(packageManager) != null) { startActivity(intent) } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show() }
Java
Intent intent = new Intent(Intent.ACTION_SEND); ... if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); } else { Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show(); }
Wenn Ihre Anwendung von Konten abhängig ist:
Ihre App kann in einer Umgebung mit eingeschränktem Profil möglicherweise unerwünschtes Verhalten aufweisen.
Nutzer in einer Umgebung mit eingeschränkten Profilen haben standardmäßig keinen Zugriff auf Nutzerkonten.
Wenn Ihre Anwendung von einem Account
abhängig ist, kann sie abstürzen oder sich unerwartet verhalten, wenn sie in einem eingeschränkten Profil verwendet wird.
Wenn Sie verhindern möchten, dass eingeschränkte Profile Ihre Anwendung vollständig nutzen, da Ihre Anwendung von vertraulichen Kontoinformationen abhängt, geben Sie das Attribut android:requiredAccountType
im <application>
-Element Ihres Manifests an.
Wenn Sie zulassen möchten, dass eingeschränkte Profile Ihre Anwendung weiterhin verwenden, obwohl diese keine eigenen Konten erstellen können, können Sie entweder die Funktionen Ihrer Anwendung deaktivieren, für die ein Konto erforderlich ist, oder eingeschränkten Profilen den Zugriff auf Konten gewähren, die vom Hauptnutzer erstellt wurden. Weitere Informationen finden Sie unten im Abschnitt Konten in einem eingeschränkten Profil unterstützen.
Wenn Ihre App VideoView verwendet...
Unter Android 4.3 wird das Video möglicherweise kleiner dargestellt.
In früheren Android-Versionen hat das VideoView
-Widget den "wrap_content"
-Wert für layout_height
und layout_width
fälschlicherweise so berechnet, dass er mit "match_parent"
übereinstimmt. Wenn du "wrap_content"
für die Höhe oder Breite verwendest, ist das Videolayout unter Android 4.3 und höher möglicherweise deutlich kleiner. Um das Problem zu beheben, ersetze "wrap_content"
durch "match_parent"
und überprüfe, ob dein Video unter Android 4.3 sowie in älteren Versionen wie erwartet angezeigt wird.
Eingeschränkte Profile
Auf Android-Tablets können Nutzer jetzt eingeschränkte Profile auf Grundlage des Hauptnutzers erstellen. Wenn Nutzer ein eingeschränktes Profil erstellen, können sie Einschränkungen aktivieren, z. B. welche Anwendungen für das Profil verfügbar sind. Dank neuer APIs in Android 4.3 können Sie auch detailliertere Einstellungen für die von Ihnen entwickelten Apps festlegen. Mit den neuen APIs können Sie Nutzern beispielsweise erlauben, zu steuern, welche Art von Inhalten innerhalb Ihrer Anwendung verfügbar ist, wenn sie in einer Umgebung mit eingeschränkten Profilen ausgeführt wird.
Die Benutzeroberfläche, über die Nutzer die von Ihnen erstellten Einschränkungen steuern können, wird von der Anwendung „Einstellungen“ des Systems verwaltet. Damit die Einschränkungseinstellungen Ihrer App dem Nutzer angezeigt werden, müssen Sie die von Ihrer App bereitgestellten Einschränkungen deklarieren. Erstellen Sie dazu eine BroadcastReceiver
, die den Intent ACTION_GET_RESTRICTION_ENTRIES
empfängt. Das System ruft diesen Intent auf, um alle Apps auf verfügbare Einschränkungen abzufragen. Anschließend erstellt das System die UI, damit der primäre Nutzer die Einschränkungen für jedes eingeschränkte Profil verwalten kann.
In der Methode onReceive()
der BroadcastReceiver
müssen Sie eine RestrictionEntry
für jede Einschränkung erstellen, die Ihre App bereitstellt. Jedes RestrictionEntry
definiert einen Einschränkungstitel, eine Beschreibung und einen der folgenden Datentypen:
TYPE_BOOLEAN
für die Einschränkung, die entweder „wahr“ oder „falsch“ ist.TYPE_CHOICE
für eine Einschränkung mit mehreren Optionen, die sich gegenseitig ausschließen (Optionsoptionen).TYPE_MULTI_SELECT
für eine Einschränkung mit mehreren Optionen, die sich nicht gegenseitig ausschließen (Kästchenauswahl).
Anschließend fügen Sie alle RestrictionEntry
-Objekte in ein ArrayList
ein und fügen es als Wert für das zusätzliche EXTRA_RESTRICTIONS_LIST
im Ergebnis des Broadcast-Empfängers ein.
Das System erstellt die UI für die Einschränkungen Ihrer App in der App „Einstellungen“ und speichert jede Einschränkung mit dem eindeutigen Schlüssel, den Sie für jedes RestrictionEntry
-Objekt angegeben haben. Wenn der Nutzer Ihre App öffnet, können Sie durch Aufrufen von getApplicationRestrictions()
aktuelle Einschränkungen abfragen.
Es wird ein Bundle
zurückgegeben, das die Schlüssel/Wert-Paare für jede Einschränkung enthält, die Sie mit den RestrictionEntry
-Objekten definiert haben.
Wenn Sie spezifischere Einschränkungen festlegen möchten, die nicht mit booleschen Werten, Single-Choice- und Multi-Choice-Werten gehandhabt werden können, können Sie eine Aktivität erstellen, in der der Nutzer die Einschränkungen festlegen und Nutzern erlauben kann, diese Aktivität über die Einschränkungseinstellungen zu öffnen. Fügen Sie bei Ihrem Broadcast-Empfänger das EXTRA_RESTRICTIONS_INTENT
-Extra in das Ergebnis-Bundle
ein. Dieses Extra muss ein Intent
angeben, das die Activity
-Klasse angibt, die gestartet werden soll. Verwenden Sie die Methode putParcelable()
, um EXTRA_RESTRICTIONS_INTENT
mit dem Intent zu übergeben.
Wenn der primäre Nutzer Ihre Aktivität eingibt, um benutzerdefinierte Einschränkungen festzulegen, muss die Aktivität ein Ergebnis zurückgeben, das die Einschränkungswerte in einem Extra mit dem Schlüssel EXTRA_RESTRICTIONS_LIST
oder EXTRA_RESTRICTIONS_BUNDLE
enthält, je nachdem, ob Sie RestrictionEntry
-Objekte oder Schlüssel/Wert-Paare angeben.
Unterstützung von Konten in einem eingeschränkten Profil
Alle Konten, die dem primären Nutzer hinzugefügt wurden, sind für ein eingeschränktes Profil verfügbar. Sie sind jedoch standardmäßig über die AccountManager
APIs nicht zugänglich.
Wenn Sie versuchen, ein Konto mit AccountManager
in einem eingeschränkten Profil hinzuzufügen, erhalten Sie eine Fehlermeldung. Aufgrund dieser Einschränkungen haben Sie die folgenden drei Optionen:
Um von einem eingeschränkten Profil auf ein Konto zugreifen zu können, müssen Sie dem <application>-Tag das Attribut android:restrictedAccountType
hinzufügen:
<application ... android:restrictedAccountType="com.example.account.type" >
Achtung:Wenn Sie dieses Attribut aktivieren, erhält Ihre Anwendung über eingeschränkte Profile Zugriff auf die Konten des Hauptnutzers. Sie sollten dies also nur zulassen, wenn die von Ihrer App angezeigten Informationen keine personenidentifizierbaren Informationen enthalten, die als vertraulich gelten. In den Systemeinstellungen wird der primäre Nutzer darüber informiert, dass die Anwendung den Konten eingeschränkte Profile zuweist. Daher sollte ihm klar sein, dass der Kontozugriff für die Funktionalität der Anwendung wichtig ist. Wenn möglich, sollten Sie auch angemessene Einschränkungen für den Hauptnutzer bereitstellen, mit denen Sie festlegen, wie viel Kontozugriff in Ihrer App gewährt wird.
Wenn Sie Konten verwenden möchten, diese aber nicht für die Hauptfunktionen Ihrer App erforderlich sind, können Sie die Kontoverfügbarkeit prüfen und Funktionen deaktivieren, wenn sie nicht verfügbar sind.
Prüfen Sie zuerst, ob bereits ein Konto verfügbar ist. Falls nicht, fragen Sie ab, ob es möglich ist, ein neues Konto zu erstellen. Rufen Sie dazu getUserRestrictions()
auf und prüfen Sie im Ergebnis das zusätzliche DISALLOW_MODIFY_ACCOUNTS
. Wenn true
festgelegt ist, sollten Sie die Funktionen Ihrer Anwendung deaktivieren, die Zugriff auf Konten erfordert.
Beispiele:
Kotlin
val um = context.getSystemService(Context.USER_SERVICE) as UserManager val restrictions: Bundle = um.userRestrictions if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality }
Java
UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); Bundle restrictions = um.getUserRestrictions(); if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { // cannot add accounts, disable some functionality }
Hinweis: In diesem Szenario sollten Sie in Ihrer Manifestdatei keine neuen Attribute deklarieren.
Wenn es stattdessen wichtig ist, dass Ihre Anwendung nicht für eingeschränkte Profile verfügbar ist, weil Ihre Anwendung von vertraulichen personenbezogenen Daten in einem Konto abhängt (und weil mit eingeschränkten Profilen derzeit keine neuen Konten hinzugefügt werden können), fügen Sie dem Tag <application> das Attribut android:requiredAccountType
hinzu:
<application ... android:requiredAccountType="com.example.account.type" >
In der Gmail-Anwendung wird dieses Attribut beispielsweise verwendet, um sich selbst für eingeschränkte Profile zu deaktivieren, da die private E-Mail-Adresse des Inhabers für eingeschränkte Profile nicht verfügbar sein soll.
WLAN und Konnektivität
Bluetooth Low Energy (Smart Ready)
Android unterstützt jetzt Bluetooth Low Energy (LE) mit neuen APIs in android.bluetooth
.
Mit den neuen APIs können Sie Android-Apps entwickeln, die mit Bluetooth Low Energy-Peripheriegeräten wie Herzfrequenzmessern und Schrittzählern kommunizieren.
Da Bluetooth LE eine Hardwarefunktion ist, die nicht auf allen Android-Mobilgeräten verfügbar ist, müssen Sie in Ihrer Manifestdatei ein <uses-feature>
-Element für "android.hardware.bluetooth_le"
deklarieren:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
Wenn Sie bereits mit den klassischen Bluetooth APIs von Android vertraut sind, beachten Sie, dass es bei der Verwendung der Bluetooth LE APIs einige Unterschiede gibt. Am wichtigsten ist, dass es jetzt eine BluetoothManager
-Klasse gibt, die Sie für einige übergeordnete Vorgänge verwenden sollten, z. B. für das Abrufen eines BluetoothAdapter
, das Abrufen einer Liste verbundener Geräte und das Prüfen des Gerätestatus. So sollten Sie jetzt BluetoothAdapter
erhalten:
Kotlin
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothAdapter = bluetoothManager.adapter
Java
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter();
Um Bluetooth LE-Peripheriegeräte zu erkennen, rufen Sie startLeScan()
im BluetoothAdapter
auf und übergeben Sie eine Implementierung der BluetoothAdapter.LeScanCallback
-Schnittstelle. Wenn der Bluetooth-Adapter ein Bluetooth LE-Peripheriegerät erkennt, empfängt Ihre BluetoothAdapter.LeScanCallback
-Implementierung einen Aufruf an die Methode onLeScan()
. Bei dieser Methode erhalten Sie ein BluetoothDevice
-Objekt, das das erkannte Gerät darstellt, den RSSI-Wert für das Gerät und ein Bytearray, das den Advertising-Eintrag des Geräts enthält.
Wenn Sie nur nach bestimmten Peripheriegeräten suchen möchten, können Sie stattdessen startLeScan()
aufrufen und ein Array mit UUID
-Objekten einfügen, die die GATT-Dienste angeben, die Ihre App unterstützt.
Hinweis: Sie können nur mit früheren APIs nach Bluetooth LE-Geräten oder nach klassischen Bluetooth-Geräten suchen. Es ist nicht möglich, gleichzeitig nach LE- und Classic-Bluetooth-Geräten zu suchen.
Wenn Sie dann eine Verbindung zu einem Bluetooth LE-Peripheriegerät herstellen möchten, rufen Sie connectGatt()
für das entsprechende BluetoothDevice
-Objekt auf und übergeben Sie eine Implementierung von BluetoothGattCallback
. Ihre Implementierung von BluetoothGattCallback
empfängt Callbacks für den Verbindungsstatus mit dem Gerät und andere Ereignisse. Während des onConnectionStateChange()
-Callbacks können Sie die Kommunikation mit dem Gerät beginnen, wenn die Methode STATE_CONNECTED
als neuen Status übergibt.
Für den Zugriff auf Bluetooth-Funktionen auf einem Gerät muss die App außerdem bestimmte Bluetooth-Nutzerberechtigungen anfordern. Weitere Informationen finden Sie im Leitfaden zur Bluetooth Low Energy API.
Modus „Nur WLAN-Suche“
Bei dem Versuch, den Standort eines Nutzers zu ermitteln, kann Android WLAN verwenden, um den Standort zu bestimmen, indem Zugangspunkte in der Nähe gescannt werden. Häufig deaktivieren Nutzer jedoch das WLAN, um den Akku zu schonen, was die Genauigkeit der Standortdaten zur Folge hat. Android verfügt jetzt über einen Modus „Nur Scannen“, mit dem das WLAN des Geräts Zugangspunkte scannen kann, um den Standort zu ermitteln, ohne sich mit einem Zugangspunkt verbinden zu müssen. Dadurch wird der Akkuverbrauch erheblich reduziert.
Wenn Sie den Standort des Nutzers ermitteln möchten, aber WLAN derzeit deaktiviert ist, können Sie den Nutzer auffordern, den Modus „Nur WLAN-Scan“ zu aktivieren. Rufen Sie dazu startActivity()
mit der Aktion ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
auf.
WLAN-Konfiguration
Mit den neuen WifiEnterpriseConfig
APIs können unternehmensorientierte Dienste die WLAN-Konfiguration für verwaltete Geräte automatisieren.
Schnellantwort für eingehende Anrufe
Seit Android 4.0 können Nutzer dank einer Funktion namens „Kurzantwort“ auf eingehende Anrufe sofort mit einer SMS antworten, ohne den Anruf annehmen oder das Gerät entsperren zu müssen.
Bisher wurden diese Kurznachrichten immer von der Standard-Messaging-App verarbeitet. Jetzt kann jede App ihre Fähigkeit zur Verarbeitung dieser Nachrichten erklären, indem sie ein Service
mit einem Intent-Filter für ACTION_RESPOND_VIA_MESSAGE
erstellt.
Wenn der Nutzer mit einer kurzen Antwort auf einen eingehenden Anruf antwortet, sendet die Telefon App den Intent ACTION_RESPOND_VIA_MESSAGE
mit einem URI, der den Empfänger (den Anrufer) beschreibt, und das zusätzliche EXTRA_TEXT
mit der Nachricht, die der Nutzer senden möchte. Wenn Ihr Dienst den Intent empfängt, sollte er die Nachricht senden und sich sofort selbst beenden (Ihre App sollte keine Aktivität anzeigen).
Sie müssen die Berechtigung SEND_RESPOND_VIA_MESSAGE
deklarieren, um diesen Intent zu erhalten.
Multimedia
MediaExtractor- und MediaCodec-Verbesserungen
Mit Android ist es jetzt einfacher, mithilfe vorhandener APIs in MediaCodec
und MediaExtractor
eigene DASH-Player (Dynamic Adaptive Streaming over HTTP) gemäß dem Standard ISO/IEC 23009-1 zu schreiben. Das Framework, das diesen APIs zugrunde liegt, wurde aktualisiert, um das Parsen fragmentierter MP4-Dateien zu unterstützen. Ihre Anwendung ist jedoch weiterhin für das Parsen der MPD-Metadaten und die Übergabe der einzelnen Streams an MediaExtractor
verantwortlich.
Wenn Sie DASH mit verschlüsselten Inhalten verwenden möchten, gibt die Methode getSampleCryptoInfo()
die MediaCodec.CryptoInfo
-Metadaten zurück, die die Struktur der einzelnen verschlüsselten Medienbeispiele beschreiben. Außerdem wurde MediaExtractor
die Methode getPsshInfo()
hinzugefügt, damit du auf die PSSH-Metadaten für deine DASH-Medien zugreifen kannst.
Diese Methode gibt eine Zuordnung von UUID
-Objekten zu Byte zurück, wobei UUID
das Kryptoschema und die Byte die Daten sind, die für dieses Schema spezifisch sind.
Medien-DRM
Die neue MediaDrm
-Klasse bietet eine modulare Lösung für die digitale Rechteverwaltung (Digital Rights Management, DRM) mit Ihren Medieninhalten. Dabei trennt sie DRM von der Medienwiedergabe. Durch diese API-Trennung können Sie beispielsweise Widevine-verschlüsselte Inhalte wiedergeben, ohne das Widevine-Medienformat verwenden zu müssen. Diese DRM-Lösung unterstützt auch die allgemeine DASH-Verschlüsselung, sodass Sie eine Vielzahl von DRM-Schemata für Ihre Streaminginhalte verwenden können.
Mit MediaDrm
können Sie intransparente Schlüsselanfragenachrichten abrufen und Schlüsselantwortnachrichten vom Server zum Erwerb und Bereitstellen von Lizenzen verarbeiten. Ihre Anwendung ist für die Netzwerkkommunikation mit den Servern zuständig. Die Klasse MediaDrm
bietet nur die Möglichkeit, die Nachrichten zu generieren und zu verarbeiten.
Die MediaDrm
APIs sind für die Verwendung in Verbindung mit den MediaCodec
APIs vorgesehen, die in Android 4.1 (API-Level 16) eingeführt wurden. Dazu gehören MediaCodec
für die Codierung und Decodierung von Inhalten, MediaCrypto
für die Verarbeitung verschlüsselter Inhalte und MediaExtractor
für das Extrahieren und Trennen von Inhalten.
Sie müssen zuerst die Objekte MediaExtractor
und MediaCodec
erstellen. Anschließend können Sie auf das DRM-Schema UUID
zugreifen, das normalerweise über Metadaten im Inhalt identifiziert wird, und es verwenden, um eine Instanz eines MediaDrm
-Objekts mit seinem Konstruktor zu erstellen.
Videocodierung über eine Oberfläche
Android 4.1 (API-Level 16) hat die Klasse MediaCodec
für die Low-Level-Codierung und Decodierung von Medieninhalten hinzugefügt. Bei der Codierung von Videos musste in Android 4.1 ein ByteBuffer
-Array für die Medien bereitgestellt werden. In Android 4.3 kannst du jetzt jedoch ein Surface
als Eingabe für einen Encoder verwenden. So kannst du beispielsweise die Eingabe aus einer vorhandenen Videodatei oder mit OpenGL ES generierte Frames codieren.
Wenn du ein Surface
als Eingabe für deinen Encoder verwenden möchtest, musst du zuerst configure()
für dein MediaCodec
aufrufen.
Rufen Sie dann createInputSurface()
auf, um die Surface
zu erhalten, über die Sie Ihre Medien streamen können.
Sie können beispielsweise den angegebenen Surface
als Fenster für einen OpenGL-Kontext verwenden, indem Sie ihn an eglCreateWindowSurface()
übergeben. Rufen Sie dann beim Rendern der Oberfläche eglSwapBuffers()
auf, um den Frame an MediaCodec
zu übergeben.
Um mit der Codierung zu beginnen, rufen Sie start()
für MediaCodec
auf. Rufen Sie danach signalEndOfInputStream()
auf, um die Codierung zu beenden, und rufen Sie release()
für die Surface
auf.
Media-Muxing
Die neue MediaMuxer
-Klasse ermöglicht Multiplexing zwischen einem Audiostream und einem Videostream. Diese APIs dienen als Gegenstück zur MediaExtractor
-Klasse, die in Android 4.2 zum Demultiplexing (Demuxing) von Medien hinzugefügt wurde.
Unterstützte Ausgabeformate sind in MediaMuxer.OutputFormat
definiert. Derzeit ist MP4 das einzige unterstützte Ausgabeformat und MediaMuxer
unterstützt derzeit nur jeweils einen Audiostream und/oder einen Videostream.
MediaMuxer
wurde hauptsächlich für die Zusammenarbeit mit MediaCodec
entwickelt, sodass Sie ein Video mit MediaCodec
verarbeiten und die Ausgabe dann über MediaMuxer
in einer MP4-Datei speichern können. Sie können MediaMuxer
auch in Kombination mit MediaExtractor
verwenden, um Medien zu bearbeiten, ohne sie codieren oder decodieren zu müssen.
Wiedergabefortschritt und Scrubbing für RemoteControlClient
In Android 4.0 (API-Level 14) wurde RemoteControlClient
hinzugefügt, um die Steuerung der Medienwiedergabe über Fernbedienungsclients zu aktivieren, z. B. die auf dem Sperrbildschirm verfügbaren Steuerelemente. Android 4.3 bietet jetzt die Möglichkeit für solche Controller, die Wiedergabeposition und Steuerelemente für das Scrubbing der Wiedergabe anzuzeigen. Wenn du die Fernbedienung für deine Medien-App mit den RemoteControlClient
APIs aktiviert hast, kannst du das Scrubbing für die Wiedergabe zulassen, indem du zwei neue Schnittstellen implementierst.
Zuerst müssen Sie das Flag FLAG_KEY_MEDIA_POSITION_UPDATE
aktivieren. Dazu übergeben Sie es an setTransportControlsFlags()
.
Implementieren Sie anschließend die folgenden beiden neuen Schnittstellen:
RemoteControlClient.OnGetPlaybackPositionListener
- Hierzu gehört der Callback
onGetPlaybackPosition()
, der die aktuelle Position deiner Medien anfordert, wenn die Fernbedienung den Fortschritt auf der Benutzeroberfläche aktualisieren muss. RemoteControlClient.OnPlaybackPositionUpdateListener
- Hierzu gehört auch der Callback
onPlaybackPositionUpdate()
, der der App den neuen Timecode für die Medien mitteilt, wenn der Nutzer mit dem Scrubbing der Wiedergabe über die Benutzeroberfläche der Fernbedienung navigiert.Nachdem du die Wiedergabe mit der neuen Position aktualisiert hast, ruf
setPlaybackState()
auf, um den neuen Wiedergabestatus, die Position und die Geschwindigkeit anzugeben.
Mit diesen definierten Oberflächen können Sie sie für die RemoteControlClient
festlegen, indem Sie setOnGetPlaybackPositionListener()
bzw. setPlaybackPositionUpdateListener()
aufrufen.
Grafik
Unterstützung für OpenGL ES 3.0
Android 4.3 bietet zusätzlich Java-Schnittstellen und native Unterstützung für OpenGL ES 3.0. Zu den wichtigsten neuen Funktionen in OpenGL ES 3.0 gehören:
- Beschleunigung erweiterter visueller Effekte
- Hochwertige ETC2/EAC-Texturkomprimierung als Standardfunktion
- Eine neue Version der GLSL ES-Shading-Sprache mit Unterstützung für Ganzzahlen und 32-Bit-Gleitkommazahlen
- Erweitertes Textur-Rendering
- Breitere Standardisierung der Texturgröße und Rendering-Zwischenspeicherformate
Die Java-Schnittstelle für OpenGL ES 3.0 unter Android wird mit GLES30
bereitgestellt.
Wenn du OpenGL ES 3.0 verwendest, musst du es in deiner Manifestdatei mit dem Tag <uses-feature> und dem Attribut android:glEsVersion
deklarieren. Beispiele:
<manifest> <uses-feature android:glEsVersion="0x00030000" /> ... </manifest>
Denken Sie daran, den OpenGL ES-Kontext anzugeben, indem Sie setEGLContextClientVersion()
aufrufen und 3
als Version übergeben.
Weitere Informationen zur Verwendung von OpenGL ES und zum Prüfen der unterstützten OpenGL ES-Version des Geräts zur Laufzeit finden Sie in der OpenGL ES-API-Anleitung.
Mipmapping für Drawables
Die Verwendung einer Mipmap als Quelle für Ihre Bitmap oder Drawable ist eine einfache Möglichkeit, ein Qualitätsbild und verschiedene Bildmaßstäbe zu liefern. Das ist besonders nützlich, wenn Sie erwarten, dass Ihr Bild während einer Animation skaliert wird.
In Android 4.2 (API-Level 17) werden Mipmaps in der Bitmap
-Klasse unterstützt. Android tauscht die Mip-Bilder in Ihrer Bitmap
aus, wenn Sie eine Mipmap-Quelle angegeben und setHasMipMap()
aktiviert haben. In Android 4.3 können Sie Mipmaps jetzt auch für ein BitmapDrawable
-Objekt aktivieren. Dazu stellen Sie ein Mipmap-Asset bereit und legen das Attribut android:mipMap
in einer Bitmap-Ressourcendatei fest oder rufen hasMipMap()
auf.
Benutzeroberfläche
Overlays anzeigen
Die neue ViewOverlay
-Klasse stellt eine transparente Ebene über einer View
bereit, auf der Sie visuelle Inhalte hinzufügen können. Die Layouthierarchie hat dadurch keinen Einfluss. Du kannst eine ViewOverlay
für jede View
erhalten, indem du getOverlay()
aufrufst. Das Overlay hat immer dieselbe Größe und Position wie seine Hostansicht (die Ansicht, von der aus es erstellt wurde). So können Sie Inhalte hinzufügen, die vor der Hostansicht angezeigt werden, die aber die Grenzen dieser Hostansicht nicht erweitern können.
Die Verwendung eines ViewOverlay
s ist besonders nützlich, wenn Sie Animationen erstellen möchten und beispielsweise eine Ansicht außerhalb des Containers verschieben oder Elemente auf dem Bildschirm verschieben möchten, ohne die Ansichtshierarchie zu beeinflussen. Da der nutzbare Bereich eines Overlays jedoch auf denselben Bereich wie die Hostansicht beschränkt ist, müssen Sie zum Animieren einer Ansicht, die sich außerhalb ihrer Position im Layout bewegt, ein Overlay aus einer übergeordneten Ansicht mit den gewünschten Layoutgrenzen verwenden.
Wenn Sie ein Overlay für eine Widget-Ansicht wie Button
erstellen, können Sie ihm Drawable
-Objekte hinzufügen, indem Sie add(Drawable)
aufrufen. Wenn Sie getOverlay()
für eine Layoutansicht wie RelativeLayout
aufrufen, wird ein ViewGroupOverlay
-Objekt zurückgegeben. Die Klasse ViewGroupOverlay
ist eine abgeleitete Klasse von ViewOverlay
, mit der Sie durch Aufrufen von add(View)
auch View
-Objekte hinzufügen können.
Hinweis:Alle Drawables und Ansichten, die Sie einem Overlay hinzufügen, sind nur visuell. Sie können keine Fokus- oder Eingabeereignisse empfangen.
Mit dem folgenden Code wird beispielsweise eine Ansicht animiert, die nach rechts geschoben wird. Dazu wird die Ansicht im Overlay der übergeordneten Ansicht platziert und anschließend wird eine Übersetzungsanimation für diese Ansicht ausgeführt:
Kotlin
val view: View? = findViewById(R.id.view_to_remove) val container: ViewGroup? = view?.parent as ViewGroup container?.apply { overlay.add(view) ObjectAnimator.ofFloat(view, "translationX", right.toFloat()) .start() }
Java
View view = findViewById(R.id.view_to_remove); ViewGroup container = (ViewGroup) view.getParent(); container.getOverlay().add(view); ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight()); anim.start();
Optisches Begrenzungslayout
Für Ansichten, die Hintergrundbilder mit neun Patches enthalten, können Sie jetzt festlegen, dass sie an den benachbarten Ansichten basierend auf den „optischen“ Begrenzungen des Hintergrundbilds ausgerichtet werden sollen und nicht anhand der „clip“-Begrenzung der Ansicht.
Die Abbildungen 1 und 2 zeigen beispielsweise jeweils das gleiche Layout, aber in Abbildung 1 werden Clipgrenzen verwendet (Standardverhalten), während in Abbildung 2 optische Grenzen verwendet werden. Da die für die Schaltfläche und den Bilderrahmen verwendeten Bilder mit neun Patches an den Rändern einen Innenrand enthalten, scheinen sie bei Verwendung von Clip-Begrenzungen nicht zueinander oder zum Text auszurichten.
Hinweis:In den Screenshots 1 und 2 ist die Entwicklereinstellung „Layoutgrenzen anzeigen“ aktiviert. Für jede Ansicht geben rote Linien die optischen Grenzen, blaue Linien die Clipgrenzen und rosa die Ränder an.
Um die Ansichten basierend auf ihren optischen Grenzen auszurichten, setzen Sie in einem der übergeordneten Layouts das Attribut android:layoutMode
auf "opticalBounds"
. Beispiele:
<LinearLayout android:layoutMode="opticalBounds" ... >
Dazu müssen die Neun-Patch-Bilder, die auf den Hintergrund der Ansichten angewendet werden, die optischen Grenzen mithilfe von roten Linien entlang der unteren und rechten Seite der Neun-Patch-Datei angeben (siehe Abbildung 3). Die roten Linien geben den Bereich an, der von den Clip-Grenzen subtrahiert werden soll, sodass die optischen Begrenzungen des Bilds beibehalten werden.
Wenn Sie die optischen Grenzen für eine ViewGroup
in Ihrem Layout aktivieren, übernehmen alle untergeordneten Ansichten den Layoutmodus für die optischen Grenzen, sofern Sie ihn für eine Gruppe nicht überschreiben, indem Sie android:layoutMode
auf "clipBounds"
setzen. Alle Layoutelemente berücksichtigen auch die optischen Grenzen der untergeordneten Ansichten und passen ihre eigenen Grenzen basierend auf den optischen Grenzen der darin enthaltenen Ansichten an. Layoutelemente (untergeordnete Klassen von ViewGroup
) unterstützen derzeit jedoch keine optischen Grenzen für Bilder mit neun Patches, die auf ihren eigenen Hintergrund angewendet werden.
Wenn Sie eine benutzerdefinierte Ansicht erstellen, indem Sie View
, ViewGroup
oder eine davon abgeleitete Klasse erstellen, übernimmt die Ansicht das optische Bindungsverhalten.
Hinweis:Alle vom Holo-Design unterstützten Widgets wurden mit optischen Grenzen aktualisiert, darunter Button
, Spinner
und EditText
. Du kannst also sofort davon profitieren, wenn du das Attribut android:layoutMode
auf "opticalBounds"
setzt, wenn deine App ein Holo-Design (Theme.Holo
, Theme.Holo.Light
usw.) anwendet.
Wenn Sie die optischen Grenzen für Ihre eigenen Bilder aus neun Patches mit dem Tool Draw 9-Patch festlegen möchten, halten Sie beim Klicken auf die Rahmenpixel die Strg-Taste gedrückt.
Animation für Rechteckwerte
Mit dem neuen RectEvaluator
können jetzt zwei Rect
-Werte animiert werden. Diese neue Klasse ist eine Implementierung von TypeEvaluator
, die du an ValueAnimator.setEvaluator()
übergeben kannst.
Listener zum Anhängen und Fokussieren von Fenstern
Wenn Sie darauf warten möchten, wann die Ansicht an das Fenster angehängt bzw. davon getrennt wurde, oder wenn sich ihr Fokus änderte, mussten Sie bisher die View
-Klasse überschreiben, um onAttachedToWindow()
bzw. onDetachedFromWindow()
bzw. onWindowFocusChanged()
zu implementieren.
Um jetzt Ereignisse zum Anhängen und Trennen zu empfangen, können Sie stattdessen ViewTreeObserver.OnWindowAttachListener
implementieren und mit addOnWindowAttachListener()
in einer Ansicht festlegen.
Um Fokusereignisse zu erhalten, können Sie ViewTreeObserver.OnWindowFocusChangeListener
implementieren und mit addOnWindowFocusChangeListener()
für eine Ansicht festlegen.
TV-Overscan-Unterstützung
Damit Ihre App auf jedem Fernseher den gesamten Bildschirm ausfüllt, können Sie jetzt Overscan für Ihr App-Layout aktivieren. Der Overscan-Modus wird durch das Flag FLAG_LAYOUT_IN_OVERSCAN
bestimmt, das Sie mit Plattformthemen wie Theme_DeviceDefault_NoActionBar_Overscan
oder durch Aktivieren des Stils windowOverscan
in einem benutzerdefinierten Design aktivieren können.
Bildschirmausrichtung
Für das Attribut screenOrientation
des <activity>
-Tags werden jetzt zusätzliche Werte unterstützt, um die Einstellungen des Nutzers für die automatische Rotation zu berücksichtigen:
"userLandscape"
- Verhält sich wie
"sensorLandscape"
, es sei denn, der Nutzer deaktiviert die automatische Drehung, wird im normalen Querformat gesperrt und nicht gespiegelt. "userPortrait"
- Verhält sich wie
"sensorPortrait"
, es sei denn, der Nutzer deaktiviert das automatische Drehen, wird im normalen Hochformat gesperrt und nicht gespiegelt. "fullUser"
- Verhält sich wie
"fullSensor"
und lässt eine Drehung in alle vier Richtungen zu, es sei denn, der Nutzer deaktiviert das automatische Drehen, wird in der bevorzugten Ausrichtung des Nutzers gesperrt.
Außerdem kannst du jetzt auch "locked"
deklarieren, um die Ausrichtung deiner App an die aktuelle Bildschirmausrichtung zu sperren.
Rotationsanimationen
Mit dem neuen Feld rotationAnimation
in WindowManager
können Sie eine von drei Animationen auswählen, die verwendet werden sollen, wenn das System die Bildschirmausrichtung ändert. Die drei Animationen sind:
Hinweis:Diese Animationen sind nur verfügbar, wenn Sie für Ihre Aktivität den Vollbildmodus aktiviert haben, der mit Designs wie Theme.Holo.NoActionBar.Fullscreen
aktiviert werden kann.
So aktivieren Sie beispielsweise die Überblendungsanimation:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val params: WindowManager.LayoutParams = window.attributes params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE window.attributes = params ... }
Java
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WindowManager.LayoutParams params = getWindow().getAttributes(); params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; getWindow().setAttributes(params); ... }
Nutzereingabe
Neue Sensortypen
Mit dem neuen TYPE_GAME_ROTATION_VECTOR
-Sensor kannst du die Gerätedrehungen erkennen, ohne dir Gedanken über magnetische Störungen machen zu müssen. Im Gegensatz zum TYPE_ROTATION_VECTOR
-Sensor basiert TYPE_GAME_ROTATION_VECTOR
nicht auf der magnetischen Norden.
Die neuen TYPE_GYROSCOPE_UNCALIBRATED
- und TYPE_MAGNETIC_FIELD_UNCALIBRATED
-Sensoren liefern Sensorrohdaten ohne Berücksichtigung von Verzerrungsschätzungen. Das heißt, die vorhandenen TYPE_GYROSCOPE
- und TYPE_MAGNETIC_FIELD
-Sensoren liefern Sensordaten, die die geschätzte Verzerrung durch Gyrosendrift bzw. Harteisen im Gerät berücksichtigen. Während die neuen "nicht kalibrierten" Versionen dieser Sensoren stattdessen die Sensorrohdaten bereitstellen und die geschätzten Verzerrungswerte separat bereitstellen. Mit diesen Sensoren können Sie die Sensordaten selbst kalibrieren, indem Sie die geschätzte Verzerrung mit externen Daten optimieren.
Benachrichtigungs-Listener
In Android 4.3 wird die neue Dienstklasse NotificationListenerService
hinzugefügt, mit der deine App Informationen zu neuen Benachrichtigungen erhalten kann, sobald diese vom System gepostet werden.
Wenn Ihre App derzeit die Accessibility Service APIs für den Zugriff auf Systembenachrichtigungen verwendet, sollten Sie Ihre App aktualisieren, um stattdessen diese APIs zu verwenden.
Contacts Provider
Abfrage nach „contactables“
Die neue Kontaktanbieter-Abfrage Contactables.CONTENT_URI
bietet eine effiziente Möglichkeit, um eine Cursor
abzurufen, die alle E-Mail-Adressen und Telefonnummern enthält, die zu allen Kontakten gehören, die der angegebenen Abfrage entsprechen.
Abfrage von Kontaktdeltas
Dem Contact Provider wurden neue APIs hinzugefügt, mit denen Sie kürzlich vorgenommene Änderungen an den Kontaktdaten effizient abfragen können. Bisher wurde Ihre App möglicherweise benachrichtigt, wenn sich etwas in den Kontaktdaten geändert hat. Sie wissen aber nicht genau, was sich geändert hat, und müssten alle Kontakte abrufen und diese dann durchlaufen, um die Änderung zu erkennen.
Um Änderungen an Einfügungen und Aktualisierungen nachzuverfolgen, können Sie jetzt den Parameter CONTACT_LAST_UPDATED_TIMESTAMP
in Ihre Auswahl aufnehmen, um nur die Kontakte abzufragen, die sich seit Ihrer letzten Abfrage an den Anbieter geändert haben.
Die neue Tabelle ContactsContract.DeletedContacts
enthält ein Protokoll der gelöschten Kontakte, um nachzuverfolgen, welche Kontakte gelöscht wurden. Jeder gelöschte Kontakt ist in dieser Tabelle für eine begrenzte Zeit gespeichert. Ähnlich wie bei CONTACT_LAST_UPDATED_TIMESTAMP
können Sie den neuen Auswahlparameter CONTACT_DELETED_TIMESTAMP
verwenden, um zu prüfen, welche Kontakte seit Ihrer letzten Anfrage an den Anbieter gelöscht wurden. Die Tabelle enthält auch die Konstante DAYS_KEPT_MILLISECONDS
mit der Anzahl der Tage (in Millisekunden), die das Protokoll gespeichert wird.
Außerdem überträgt der Contacts Provider jetzt die Aktion CONTACTS_DATABASE_CREATED
, wenn der Nutzer den Kontaktspeicher über das Menü für Systemeinstellungen löscht. Dadurch wird die Contact Provider-Datenbank neu erstellt. Sie soll Apps signalisieren, dass sie alle gespeicherten Kontaktinformationen löschen und mit einer neuen Abfrage neu laden müssen.
Beispielcode, mit dem diese APIs auf Änderungen an den Kontakten geprüft werden, finden Sie im ApiDemos-Beispiel, das Sie über SDK-Beispiele herunterladen können.
Lokalisierung
Verbesserte Unterstützung für bidirektionalen Text
Frühere Versionen von Android unterstützen von rechts nach links gesprochene Sprachen und das entsprechende Layout, verarbeiten aber manchmal Text in gemischten Richtungen nicht richtig. Deshalb werden unter Android 4.3 die BidiFormatter
-APIs hinzugefügt, mit denen du Text richtig mit Inhalten in entgegengesetzten Richtungen formatieren kannst, ohne Teile davon zu verstören.
Wenn Sie beispielsweise einen Satz mit einer Stringvariablen wie „Meinten Sie 15 Bay Street, Laurel, CA?“ erstellen möchten, übergeben Sie normalerweise eine lokalisierte String-Ressource und die Variable an String.format()
:
Kotlin
val suggestion = String.format(resources.getString(R.string.did_you_mean), address)
Java
Resources res = getResources(); String suggestion = String.format(res.getString(R.string.did_you_mean), address);
Ist die Sprache jedoch Hebräisch, wird der formatierte String so ausgegeben:
💗{/7} 인כルSTEKT {9} 15 Bay Street, Laurel, CA
Das ist falsch, denn die "15" sollte links von der "Bay Street" sein. Die Lösung besteht darin, BidiFormatter
und die zugehörige Methode unicodeWrap()
zu verwenden. Der obige Code sieht beispielsweise so aus:
Kotlin
val bidiFormatter = BidiFormatter.getInstance() val suggestion = String.format( resources.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address) )
Java
Resources res = getResources(); BidiFormatter bidiFormatter = BidiFormatter.getInstance(); String suggestion = String.format(res.getString(R.string.did_you_mean), bidiFormatter.unicodeWrap(address));
Standardmäßig verwendet unicodeWrap()
die Heuristik der ersten starken Richtungsschätzung, die Fehler verursachen kann, wenn das erste Signal für die Textrichtung nicht die richtige Richtung für den gesamten Inhalt darstellt.
Bei Bedarf können Sie eine andere Heuristik angeben, indem Sie eine der TextDirectionHeuristic
-Konstanten von TextDirectionHeuristics
an unicodeWrap()
übergeben.
Hinweis:Diese neuen APIs sind auch für frühere Android-Versionen über die Android Support Library mit der Klasse BidiFormatter
und zugehörigen APIs verfügbar.
Bedienungshilfen
Schlüsselereignisse verarbeiten
Ein AccessibilityService
kann jetzt mit der Callback-Methode onKeyEvent()
einen Callback für Schlüsseleingabeereignisse empfangen. Dadurch kann die Bedienungshilfe Eingaben für tastenbasierte Eingabegeräte wie eine Tastatur verarbeiten und diese Ereignisse in spezielle Aktionen übersetzen, die zuvor möglicherweise nur über die Eingabe per Berührung oder die Richtungstasten des Geräts möglich waren.
Text auswählen und kopieren/einfügen
Das AccessibilityNodeInfo
bietet jetzt APIs, mit denen ein AccessibilityService
Text in einem Knoten auswählen, ausschneiden, kopieren und einfügen kann.
Um die Auswahl des ausgeschnittenen oder zu kopierenden Textes anzugeben, kann die Bedienungshilfe die neue Aktion ACTION_SET_SELECTION
verwenden und dabei die Start- und Endposition der Auswahl mit ACTION_ARGUMENT_SELECTION_START_INT
und ACTION_ARGUMENT_SELECTION_END_INT
übergeben.
Alternativ können Sie Text auswählen, indem Sie die Cursorposition mit der vorhandenen Aktion ACTION_NEXT_AT_MOVEMENT_GRANULARITY
(bisher nur zum Verschieben der Cursorposition) bearbeiten und das Argument ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
hinzufügen.
Sie können sie dann mit ACTION_CUT
und ACTION_COPY
ausschneiden oder kopieren und später mit ACTION_PASTE
einfügen.
Hinweis:Diese neuen APIs sind auch für frühere Android-Versionen über die Android-Supportbibliothek mit der Klasse AccessibilityNodeInfoCompat
verfügbar.
Bedienungshilfen deklarieren
Ab Android 4.3 müssen Bedienungshilfen für bestimmte Bedienungshilfen in der Metadatendatei deklariert werden, um bestimmte Bedienungshilfen nutzen zu können. Wenn die Capability nicht in der Metadatendatei angefordert wird, ist die Funktion ein managementfrei. Um die Barrierefreiheitsfunktionen Ihres Dienstes zu deklarieren, müssen Sie XML-Attribute verwenden, die den verschiedenen „capability“-Konstanten in der AccessibilityServiceInfo
-Klasse entsprechen.
Wenn ein Dienst beispielsweise die Funktion flagRequestFilterKeyEvents
nicht anfordert, empfängt er keine Schlüsselereignisse.
Tests und Fehlerbehebung
Automatisierte UI-Tests
Die neue UiAutomation
-Klasse stellt APIs bereit, mit denen Sie Nutzeraktionen für die Testautomatisierung simulieren können. Wenn du die AccessibilityService
APIs der Plattform verwendest, kannst du mit den UiAutomation
-APIs den Bildschirminhalt prüfen und beliebige Tastatur- und Touch-Ereignisse einfügen.
Rufen Sie Instrumentation.getUiAutomation()
auf, um eine Instanz von UiAutomation
abzurufen. Damit dies funktioniert, müssen Sie die Option -w
mit dem Befehl instrument
angeben, wenn Sie InstrumentationTestCase
über adb shell
ausführen.
Mit der Instanz UiAutomation
können Sie beliebige Ereignisse zum Testen Ihrer Anwendung ausführen. Dazu rufen Sie executeAndWaitForEvent()
auf, übergeben einen Runnable
-Wert für die Ausführung, ein Zeitlimit für den Vorgang und eine Implementierung der UiAutomation.AccessibilityEventFilter
-Schnittstelle. Innerhalb der UiAutomation.AccessibilityEventFilter
-Implementierung erhältst du einen Aufruf, mit dem du die für dich interessanten Ereignisse filtern und den Erfolg oder Misserfolg eines bestimmten Testlaufs bestimmen kannst.
Um alle Ereignisse während eines Tests zu beobachten, erstellen Sie eine Implementierung von UiAutomation.OnAccessibilityEventListener
und übergeben Sie sie an setOnAccessibilityEventListener()
.
Die Listener-Schnittstelle empfängt dann jedes Mal, wenn ein Ereignis auftritt, einen Aufruf an onAccessibilityEvent()
und empfängt ein AccessibilityEvent
-Objekt, das das Ereignis beschreibt.
Die UiAutomation
APIs bieten eine Vielzahl weiterer Vorgänge auf sehr niedriger Ebene an, um die Entwicklung von UI-Testtools wie uiautomator zu fördern. Beispielsweise kann UiAutomation
auch Folgendes tun:
- Eingabeereignisse einfügen
- Ausrichtung des Bildschirms ändern
- Screenshots erstellen
Für UI-Testtools ist besonders wichtig: Die UiAutomation
APIs funktionieren über Anwendungsgrenzen hinweg, im Gegensatz zu den APIs in Instrumentation
.
Systrace-Ereignisse für Apps
Unter Android 4.3 wird die Trace
-Klasse mit den beiden statischen Methoden beginSection()
und endSection()
hinzugefügt. Damit können Sie Codeblöcke definieren, die in den Systrace-Bericht aufgenommen werden sollen. Durch das Erstellen von Abschnitten mit nachverfolgbarem Code in Ihrer Anwendung bieten Ihnen die Systrace-Logs eine viel detailliertere Analyse, wo in Ihrer Anwendung Verlangsamung auftritt.
Informationen zur Verwendung des Systrace-Tools finden Sie unter Anzeige und Leistung mit Systrace analysieren.
Sicherheit
Android-Schlüsselspeicher für private App-Schlüssel
Android bietet in der KeyStore
-Funktion jetzt einen benutzerdefinierten Java-Sicherheitsanbieter namens Android Key Store an, mit dem du private Schlüssel generieren und speichern kannst, die nur von deiner App gesehen und verwendet werden können. Übergib "AndroidKeyStore"
an KeyStore.getInstance()
, um den Android Key Store zu laden.
Generieren Sie einen neuen Schlüssel mit KeyPairGenerator
und KeyPairGeneratorSpec
, um die privaten Anmeldedaten Ihrer App im Android Key Store zu verwalten. Rufen Sie zuerst eine Instanz von KeyPairGenerator
ab, indem Sie getInstance()
aufrufen. Rufen Sie dann initialize()
auf und übergeben Sie eine Instanz von KeyPairGeneratorSpec
, die Sie mit KeyPairGeneratorSpec.Builder
abrufen können.
Hol dir deine KeyPair
, indem du generateKeyPair()
anrufst.
Hardware-Anmeldedatenspeicher
Android unterstützt jetzt auch hardwaregestützten Speicher für Ihre KeyChain
-Anmeldedaten. Dadurch erhöht sich die Sicherheit, da die Schlüssel nicht extrahiert werden können. Sobald sich Schlüssel in einem hardwaregestützten Schlüsselspeicher (Secure Element, TPM oder TrustZone) befinden, können sie für kryptografische Vorgänge verwendet werden, das Material des privaten Schlüssels jedoch nicht. Selbst der Kernel des Betriebssystems kann nicht auf dieses Schlüsselmaterial zugreifen. Nicht alle Android-Geräte unterstützen Speicher auf Hardware. Sie können aber zur Laufzeit prüfen, ob hardwaregestützter Speicher verfügbar ist, indem Sie KeyChain.IsBoundKeyAlgorithm()
aufrufen.
Manifestdeklarationen
Deklarierbare erforderliche Funktionen
Die folgenden Werte werden jetzt im Element <uses-feature>
unterstützt, damit deine App nur auf Geräten installiert wird, die die Funktionen bieten, die für deine App erforderlich sind.
FEATURE_APP_WIDGETS
- Deklariert, dass Ihre App ein App-Widget zur Verfügung stellt und nur auf Geräten mit einem Startbildschirm oder einer ähnlichen Stelle installiert werden sollte, auf der Nutzer App-Widgets einbetten können.
Beispiel:
<uses-feature android:name="android.software.app_widgets" android:required="true" />
FEATURE_HOME_SCREEN
- Deklariert, dass sich deine App als Ersatz für den Startbildschirm verhält und nur auf Geräten installiert werden sollte, die Startbildschirm-Apps von Drittanbietern unterstützen.
Beispiel:
<uses-feature android:name="android.software.home_screen" android:required="true" />
FEATURE_INPUT_METHODS
- Deklariert, dass deine App eine benutzerdefinierte Eingabemethode (eine mit
InputMethodService
erstellte Tastatur) bietet und nur auf Geräten installiert werden sollte, die Eingabemethoden von Drittanbietern unterstützen. Beispiel:<uses-feature android:name="android.software.input_methods" android:required="true" />
FEATURE_BLUETOOTH_LE
- Erklärt, dass deine App Bluetooth Low Energy APIs verwendet und nur auf Geräten installiert werden sollte, die über Bluetooth Low Energy mit anderen Geräten kommunizieren können
Beispiel:
<uses-feature android:name="android.software.bluetooth_le" android:required="true" />
Nutzerberechtigungen
Die folgenden Werte werden jetzt in <uses-permission>
unterstützt, um die Berechtigungen zu deklarieren, die Ihre Anwendung für den Zugriff auf bestimmte APIs benötigt.
BIND_NOTIFICATION_LISTENER_SERVICE
- Erforderlich zur Verwendung der neuen
NotificationListenerService
APIs. SEND_RESPOND_VIA_MESSAGE
- Erforderlich, um den
ACTION_RESPOND_VIA_MESSAGE
-Intent zu empfangen.
Eine detaillierte Ansicht aller API-Änderungen in Android 4.3 finden Sie im Bericht zu API-Unterschieden.