APIs unter Android 4.3

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:

  • Zugriff auf die Konten des Inhabers über ein eingeschränktes Profil erlauben.

    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.

  • Bestimmte Funktionen deaktivieren, wenn Konten nicht geändert werden können

    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.

  • Deaktivieren Sie Ihre App, wenn Sie nicht auf private Konten zugreifen können.

    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 ViewOverlays 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.

    Abbildung 1: Layout mit Clipgrenzen (Standardeinstellung).

    Abbildung 2: Layout mit optischen Grenzen.

    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" ... >
    

    Abbildung 3: Vergrößerte Ansicht der neunteiligen Holo-Schaltfläche mit optischen Grenzen.

    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.