APK-Erweiterungsdateien

<ph type="x-smartling-placeholder">

Bei Google Play darf das komprimierte APK, das Nutzer herunterladen, nicht größer als 100 MB sein. Bei den meisten Apps bietet dies viel Platz für den gesamten Code und die Assets der App. Einige Apps benötigen jedoch mehr Speicherplatz für High-Fidelity-Grafiken, Mediendateien oder andere große Assets. Bisher mussten bei komprimierten Dateien über 100 MB die Dateien zusätzliche Ressourcen, wenn der Nutzer die App öffnet. Das Hosten und Bereitstellen der zusätzlichen Dateien und die Nutzererfahrung ist oft nicht ideal. Um Ihnen diesen Vorgang zu erleichtern, und angenehmer für die Nutzer ist, können Sie bei Google Play zwei große Erweiterungsdateien anhängen, Ihr APK ergänzen.

Google Play hostet die Erweiterungsdateien für Ihre App und stellt sie dem Gerät unter für Sie kostenlos. Die Erweiterungsdateien werden im freigegebenen Speicher des Geräts (der SD-Karte oder USB-Partition auch als „externe“ Speicher), auf die Ihre App zugreifen kann . Auf den meisten Geräten lädt Google Play die Erweiterungsdatei(en) gleichzeitig herunter. lädt das APK herunter, sodass Ihre App alles hat, was sie braucht, wenn der Nutzer sie für die beim ersten Mal. In einigen Fällen muss Ihre App die Dateien jedoch von Google Play herunterladen. wenn deine App gestartet wird.

Wenn du auf Erweiterungsdateien verzichten möchtest und die komprimierte Downloadgröße deiner App größer ist als 100 MB, laden Sie Ihre App stattdessen mit einer Android-App Bundles mit einer komprimierten Downloadgröße von bis zu 200 MB. Da die Verwendung von App Bundles verschieben die APK-Erstellung und -Signatur bei Google Play, Nutzer laden optimierte APKs mit nur den Code und die Ressourcen, die sie zum Ausführen Ihrer Anwendung benötigen. Sie müssen nicht selbst erstellen, mehrere APKs oder Erweiterungsdateien verwalten und Nutzer erhalten kleinere, optimierte Downloads.

Übersicht

Jedes Mal, wenn Sie ein APK über die Google Play Console hochladen, können Sie Fügen Sie der APK eine oder zwei Erweiterungsdateien hinzu. Jede Datei kann bis zu 2 GB groß sein und in einem beliebigen auswählen. Wir empfehlen jedoch die Verwendung einer komprimierten Datei, um Bandbreite während des Downloads zu sparen. Konzeptionell spielt jede Erweiterungsdatei eine andere Rolle:

  • Die Haupt-Erweiterungsdatei primäre Erweiterungsdatei für zusätzliche Ressourcen, die für Ihre App erforderlich sind.
  • Die Erweiterungsdatei patch ist optional und für kleine Aktualisierungen des Haupt-Erweiterungsdatei.

Sie können die beiden Erweiterungsdateien beliebig verwenden. Wir empfehlen jedoch, die Hauptdatei Erweiterungsdatei liefert die primären Assets und sollte nur selten aktualisiert werden. die Patcherweiterung sollte kleiner sein und als „Patch-Anbieter“ dienen, der mit jedem größeren oder nach Bedarf veröffentlicht werden.

Selbst wenn für Ihr App-Update nur eine neue Patch-Erweiterungsdatei erforderlich ist, müssen Sie ein neues APK mit einem aktualisierten versionCode im Manifest hochladen. Der Parameter In der Play Console ist es nicht möglich, eine Erweiterungsdatei in ein vorhandenes APK hochzuladen.)

Hinweis: Die Patch-Erweiterungsdatei ist semantisch identisch mit dem Haupterweiterungsdatei – Sie können jede Datei beliebig verwenden.

Format des Dateinamens

Jede Erweiterungsdatei, die Sie hochladen, kann ein beliebiges Format haben (ZIP, PDF, MP4 usw.). Sie können auch das Tool JOBB zum Kapseln und Verschlüsseln eines Satzes verwenden von Ressourcendateien und nachfolgenden Patches für diesen Satz. Unabhängig vom Dateityp betrachtet sie als undurchsichtige binäre Blobs und benennt die Dateien nach dem folgenden Schema um:

[main|patch].<expansion-version>.<package-name>.obb

Dieses Schema besteht aus drei Komponenten:

main oder patch
Gibt an, ob die Datei die Haupt- oder Patch-Erweiterungsdatei ist. Es kann sein, nur eine Hauptdatei und eine Patchdatei für jedes APK.
<expansion-version>
Dies ist eine Ganzzahl, die dem Versionscode des APK entspricht, mit dem die Erweiterung beginnt zuerst verknüpft (sie stimmt mit den android:versionCode der App überein) -Wert).

"Erste" betont, weil ihr mit der Play Console eine hochgeladene Erweiterungsdatei mit einem neuen APK wiederverwenden, ändert sich der Name der Erweiterungsdatei nicht, sondern Die Version, die beim ersten Hochladen der Datei angewendet wurde, wird beibehalten.

<package-name>
Der Name des App-Pakets im Java-Stil.

Angenommen, Ihre APK-Version lautet 314159 und Ihr Paketname ist com.beispiel.app. Wenn Sie eine Haupt-Erweiterungsdatei hochladen, wird die Datei umbenannt in:

main.314159.com.example.app.obb

Speicherort

Wenn Google Play Ihre Erweiterungsdateien auf ein Gerät herunterlädt, speichert es sie im System freigegebener Speicher. Um einwandfreies Verhalten sicherzustellen, dürfen Sie die Elemente nicht löschen, verschieben oder umbenennen Erweiterungsdateien. Falls Ihre App den Download von Google Play ausführen muss müssen Sie die Dateien am selben Speicherort speichern.

Die Methode getObbDir() gibt den spezifischen Standort zurück. für Ihre Erweiterungsdateien im folgenden Format:

<shared-storage>/Android/obb/<package-name>/

In diesem Verzeichnis befinden sich für jede Anwendung nie mehr als zwei Erweiterungsdateien. Das eine ist die Haupterweiterungsdatei und das andere ist die Patch-Erweiterungsdatei (falls erforderlich). Zurück Versionen werden überschrieben, wenn du deine App mit neuen Erweiterungsdateien aktualisierst. Seit Android 4.4 (API-Level 19): Apps können Erweiterungsdateien von OBB ohne externen Speicher lesen Berechtigung. Für einige Implementierungen von Android 6.0 (API-Level 23) und höher ist jedoch Berechtigungen erteilen, also müssen Sie READ_EXTERNAL_STORAGE im App-Manifest und fordern Sie die Berechtigung unter an Laufzeit so:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Unter Android 6 und höher muss die Berechtigung für den externen Speicher zur Laufzeit angefordert werden. Einige Implementierungen von Android benötigen jedoch keine Berechtigung zum Lesen von OBB-Dateien. Die Das folgende Code-Snippet zeigt, wie Sie den Lesezugriff prüfen, bevor Sie externen Speicher anfordern Berechtigung:

Kotlin

val obb = File(obb_filename)
var open_failed = false

try {
    BufferedReader(FileReader(obb)).also { br ->
        ReadObbFile(br)
    }
} catch (e: IOException) {
    open_failed = true
}

if (open_failed) {
    // request READ_EXTERNAL_STORAGE permission before reading OBB file
    ReadObbFileWithPermission()
}

Java

File obb = new File(obb_filename);
 boolean open_failed = false;

 try {
     BufferedReader br = new BufferedReader(new FileReader(obb));
     open_failed = false;
     ReadObbFile(br);
 } catch (IOException e) {
     open_failed = true;
 }

 if (open_failed) {
     // request READ_EXTERNAL_STORAGE permission before reading OBB file
     ReadObbFileWithPermission();
 }

Wenn Sie den Inhalt der Erweiterungsdateien entpacken müssen, löschen Sie die Datei OBB anschließend Erweiterungsdateien und speichern Sie die entpackten Daten nicht. im selben Verzeichnis. Speichern Sie die entpackten Dateien im Verzeichnis, angegeben durch getExternalFilesDir(). Sie können jedoch Verwenden Sie nach Möglichkeit ein Erweiterungsdateiformat, mit dem Sie direkt aus anstatt sie entpacken zu müssen. Wir stellen z. B. eine Bibliothek mit Projekt namens APK Expansion Zip Library, das Ihre Daten direkt liest aus der ZIP-Datei.

Achtung:Im Gegensatz zu APK-Dateien werden alle gespeicherten Dateien im freigegebenen Speicher können vom Nutzer und von anderen Apps gelesen werden.

Tipp:Wenn Sie Mediendateien in eine ZIP-Datei packen, können Sie dafür Mediendateien mit Offset- und Längensteuerelementen (z. B. MediaPlayer.setDataSource() und SoundPool.load()) ohne das Ihre ZIP-Datei entpacken müssen. Damit dies funktioniert, dürfen Sie die Mediendateien beim Erstellen der ZIP-Pakete. Wenn Sie beispielsweise das zip-Tool verwenden, sollten Sie mit der Option -n die Dateisuffixe angeben, die nicht komprimiert:
zip -n .mp4;.ogg main_expansion media_files

Download

Meistens lädt Google Play deine Erweiterungsdateien herunter und speichert sie gleichzeitig lädt das APK auf das Gerät herunter. In einigen Fällen kann Google Play kann die Erweiterungsdateien nicht herunterladen oder der Nutzer hat zuvor heruntergeladene Erweiterungsdateien gelöscht. Dateien. Um diese Situationen zu bewältigen, muss Ihre App in der Lage sein, die Dateien herunterzuladen. sich selbst, wenn die Hauptaktivität beginnt. Verwenden Sie dazu eine von Google Play bereitgestellte URL.

Der Downloadvorgang sieht im Allgemeinen so aus:

  1. Der Nutzer entscheidet, deine App über Google Play zu installieren.
  2. Wenn Google Play die Erweiterungsdateien herunterladen kann (was bei den meisten Geräte), werden sie zusammen mit dem APK heruntergeladen.

    Wenn Google Play die Erweiterungsdateien nicht herunterladen kann, werden die Nur APK.

  3. Wenn der Nutzer Ihre App startet, muss Ihre App prüfen, ob die Erweiterungsdateien die bereits auf dem Gerät gespeichert sind.
    1. Wenn ja, ist Ihre App einsatzbereit.
    2. Falls nicht, muss deine App die Erweiterungsdateien über HTTP von Google Play herunterladen. Ihre App muss über den App-Lizenzierungsdienst von Google Play eine Anfrage an den Google Play-Client senden, die gibt für jede Erweiterungsdatei den Namen, die Dateigröße und die URL zurück. Mit diesen Informationen laden Sie die Dateien herunter und speichern Sie sie am richtigen Speicherort.

Achtung:Sie müssen unbedingt den erforderlichen Code für die Laden Sie die Erweiterungsdateien aus Google Play herunter, falls sich die Dateien nicht bereits im wenn die App gestartet wird. Wie im folgenden Abschnitt zum Herunterladen der Erweiterungsdateien beschrieben, steht Ihnen eine Bibliothek zur Verfügung, die vereinfacht diesen Vorgang erheblich und führt den Download von einem Dienst mit minimaler Code von Ihnen.

Checkliste für die Entwicklung

Im Folgenden finden Sie eine Zusammenfassung der Aufgaben, die Sie ausführen sollten, um Erweiterungsdateien mit Ihrem App:

  1. Ermitteln Sie zuerst, ob die komprimierte Downloadgröße Ihrer App größer als 100 MB sein muss. Speicherplatz ist kostbar und die Downloadgröße sollte so klein wie möglich sein. Wenn Ihre App verwendet mehr als 100 MB, um mehrere Versionen deiner Grafikinhalte für mehrere Bildschirme bereitzustellen sollten Sie stattdessen mehrere APKs veröffentlichen, in denen jedes APK enthält nur die Assets, die für die Bildschirme erforderlich sind, auf die die Anzeige ausgerichtet ist. Um optimale Ergebnisse zu erzielen, bei Google Play veröffentlichen, laden Sie ein Android App Bundle hoch, enthält den gesamten kompilierten Code und die Ressourcen Ihrer App, verschiebt jedoch die APK-Erstellung und -Anmeldung bei Google Spielen.
  2. Bestimmen Sie, welche App-Ressourcen von Ihrem APK getrennt werden sollen, und verpacken Sie sie in einem -Datei, die als Haupterweiterungsdatei verwendet werden soll.

    Normalerweise sollten Sie nur die zweite Patch-Erweiterungsdatei verwenden, wenn Sie Updates für die Haupterweiterungsdatei. Wenn Ihre Ressourcen jedoch die Beschränkung von 2 GB für den Haupt- Erweiterungsdatei verwenden, können Sie die Patchdatei für Ihre restlichen Assets verwenden.

  3. Entwickeln Sie Ihre App so, dass sie die Ressourcen aus Ihren Erweiterungsdateien in der freigegebenen Speicherort des Geräts.

    Sie dürfen die Erweiterungsdateien nicht löschen, verschieben oder umbenennen.

    Wenn Ihre App kein bestimmtes Format erfordert, empfehlen wir Ihnen, ZIP-Dateien für Ihre Erweiterungsdateien und lesen Sie sie mit dem APK Expansion Zip Mediathek.

  4. Fügen Sie der Hauptaktivität Ihrer App eine Logik hinzu, die prüft, ob die Erweiterungsdateien befinden sich beim Start auf dem Gerät. Wenn sich die Dateien nicht auf dem Gerät befinden, verwenden Sie den App-Lizenzierungsdienst von Google Play, um URLs anzufordern. für die Erweiterungsdateien, laden Sie sie herunter und speichern Sie sie.

    Um die Menge an Code, den Sie schreiben müssen, erheblich zu reduzieren und eine gute User Experience zu gewährleisten empfehlen wir dir, den Downloader zu verwenden, Bibliothek zum Implementieren des Downloadverhaltens.

    Wenn Sie statt der Bibliothek einen eigenen Downloaddienst erstellen, Der Name der Erweiterungsdateien darf nicht geändert werden und sie müssen an der richtigen Speicherort.

Nachdem Sie Ihre App-Entwicklung abgeschlossen haben, folgen Sie der Anleitung zum Testen Ihre Erweiterungsdateien.

Regeln und Einschränkungen

Das Hinzufügen von APK-Erweiterungsdateien ist eine Funktion, die verfügbar ist, wenn du deine App über die Play Console Wenn Sie Ihre App zum ersten Mal hochladen oder eine App verwenden, die Erweiterungsdateien verwendet, müssen Sie die folgenden Regeln und Einschränkungen beachten:

  1. Eine Erweiterungsdatei darf nicht größer als 2 GB sein.
  2. Um Ihre Erweiterungsdateien bei Google Play herunterzuladen, muss der Nutzer Ihre App bei Google Play erworben haben. Google Play wird keine die URLs für Ihre Erweiterungsdateien angeben, falls die App auf andere Weise installiert wurde.
  3. Beim Download in Ihrer App wird die URL, die von Google Play stellt für jede Datei bereit, die für jeden Download eindeutig ist, und jeder Download läuft kurz nach seiner Bereitstellung ab. zu Ihrer App hinzufügen.
  4. Wenn Sie Ihre App mit einem neuen APK aktualisieren oder mehrere APKs für dasselbe APK hochladen App können Sie Erweiterungsdateien auswählen, die Sie für eine vorherige APK-Datei hochgeladen haben. Die Der Name der Erweiterungsdatei ändert sich nicht. Die vom APK empfangene Version wird beibehalten, mit der die Datei ursprünglich verknüpft war.
  5. Wenn Sie Erweiterungsdateien in Kombination mit mehreren APKs verwenden, um unterschiedliche Erweiterungsdateien für verschiedene Geräte zur Verfügung stellen, müssen Sie dennoch separate APKs hochladen. für jedes Gerät, um eine eindeutige versionCode und legen Sie verschiedene Filter für für jedes APK.
  6. Du kannst kein Update deiner App durchführen, indem du die Erweiterungsdateien änderst Laden Sie ein neues APK hoch, um Ihre App zu aktualisieren. Wenn Ihre Änderungen nur die Assets in Ihren Erweiterungsdateien betreffen, können Sie Ihr APK aktualisieren, indem Sie versionCode (und vielleicht auch die versionName).

  7. Speichere keine anderen Daten auf deinem obb/ Verzeichnis. Wenn Sie einige Daten entpacken müssen, speichern Sie sie an dem durch getExternalFilesDir() angegebenen Speicherort.
  8. Löschen Sie die Erweiterungsdatei .obb nicht und benennen Sie sie nicht um, es sei denn, Sie der Aktualisierung). Dies führt dazu, dass Google Play (oder Ihre App selbst) wiederholt laden Sie die Erweiterungsdatei herunter.
  9. Wenn Sie eine Erweiterungsdatei manuell aktualisieren, müssen Sie die vorherige Erweiterungsdatei löschen.

Erweiterungsdateien herunterladen

In den meisten Fällen lädt Google Play Ihre Erweiterungsdateien herunter und speichert sie gleichzeitig auf dem Gerät. Zeitpunkt der Installation oder Aktualisierung des APK. So sind die Erweiterungsdateien verfügbar, wenn Ihre wenn die App zum ersten Mal veröffentlicht wird. In einigen Fällen muss Ihre App jedoch die Datei Erweiterungsdateien selbst, indem sie von einer URL angefordert werden, die Sie in einer Antwort erhalten. über den App-Lizenzierungsservice von Google Play.

Zum Herunterladen Ihrer Erweiterungsdateien benötigen Sie folgende grundlegende Logik:

  1. Suchen Sie beim Start der App im freigegebenen Speicher (in der Android/obb/<package-name>/-Verzeichnis).
    1. Wenn die Erweiterungsdateien vorhanden sind, müssen Sie nichts weiter tun und Ihre App kann fortfahren.
    2. Wenn die Erweiterungsdateien nicht vorhanden sind: <ph type="x-smartling-placeholder">
        </ph>
      1. Stellen Sie eine Anfrage über die App-Lizenzierung von Google Play, um Ihre die Namen, Größen und URLs von Erweiterungsdateien der App.
      2. Lade die Erweiterungsdateien über die von Google Play bereitgestellten URLs herunter und speichere sie die Erweiterungsdateien. Sie müssen die Dateien am freigegebenen Speicherort speichern. (Android/obb/<package-name>/) und verwenden Sie exakt den angegebenen Dateinamen. der Reaktion von Google Play.

        Hinweis:Die URL, die Google Play für Ihre Erweiterungsdateien sind für jeden Download eindeutig und laufen kurz nach der Übergabe an für Ihre App.

Wenn Ihre App kostenlos und keine kostenpflichtige App ist, haben Sie den App-Lizenzierungsdienst wahrscheinlich noch nicht genutzt. Hauptsächlich die Sie durchsetzen, Lizenzierungsrichtlinien für Ihre App und stellen Sie sicher, dass der Nutzer das Recht hat, Ihre App verwenden (er oder sie hat sie rechtmäßig bei Google Play bezahlt). Um die Erweiterungsdatei-Funktionalität wurde der Lizenzierungsservice erweitert, um eine Antwort zu Ihrer App hinzufügen, die die URL der Erweiterungsdateien enthält, die in Ihrer App gehostet werden bei Google Play. Auch wenn deine App für Nutzer kostenlos ist, musst du also die License Verification Library (LVL) zur Verwendung von APK-Erweiterungsdateien Wenn Ihre App ist kostenlos. Sie müssen keine Lizenzüberprüfung durchsetzen, sondern nur die um die Anfrage auszuführen, die die URL Ihrer Erweiterungsdateien zurückgibt.

Hinweis:Unabhängig davon, ob Ihre App kostenlos ist oder nicht, gibt die URLs der Erweiterungsdateien nur dann zurück, wenn der Nutzer Ihre App über Google Play erworben hat.

Neben der LVL benötigen Sie einen Codesatz, mit dem die Erweiterungsdateien heruntergeladen werden. über eine HTTP-Verbindung und speichert sie am richtigen Speicherort im freigegebenen Speicher des Geräts. Beim Einbinden dieses Verfahrens in Ihre App gibt es einige Probleme, die Sie berücksichtigen sollten. Kaufbereitschaft:

  • Möglicherweise ist auf dem Gerät nicht genügend Speicherplatz für die Erweiterungsdateien vorhanden, daher sollten Sie prüfen, bevor Sie den Download starten und den Nutzer warnen, wenn nicht genügend Speicherplatz vorhanden ist.
  • Dateidownloads sollten im Hintergrunddienst erfolgen, um den Nutzer nicht zu blockieren Interaktion und ermöglichen es dem Nutzer, die App während des Downloads zu verlassen.
  • Während der Anforderung und des Downloads können verschiedene Fehler auftreten, die Sie an die Arbeit denken.
  • Die Netzwerkverbindung kann sich während des Downloads ändern. Falls der Download unterbrochen wird, setzen Sie den Download nach Möglichkeit fort.
  • Während der Download im Hintergrund erfolgt, sollten Sie eine Benachrichtigung bereitstellen, zeigt den Downloadfortschritt an, benachrichtigt den Nutzer, wenn er abgeschlossen ist, und leitet ihn zurück zu Ihre App auswählen.

Um Ihnen diese Arbeit zu erleichtern, haben wir die Downloader-Bibliothek entwickelt. das die Erweiterungsdateien an den Lizenzierungsservice anfordert, die Erweiterungsdateien herunterlädt, alle oben aufgeführten Aufgaben ausgeführt und ermöglicht sogar das Pausieren und Fortsetzen herunterladen. Durch das Hinzufügen der Downloader-Bibliothek und einiger Code-Hooks zu Ihrer App können fast alle dass die Erweiterungsdateien bereits für Sie codiert sind. Um die bestmögliche Leistung mit minimalem Aufwand für dich nutzerfreundlich ist, empfehlen wir dir, die Downloader Library zu verwenden, Ihre Erweiterungsdateien herunterladen. In den Informationen in den folgenden Abschnitten wird die Integration von Bibliothek in Ihre App einbinden.

Falls Sie lieber eine eigene Lösung zum Herunterladen der Erweiterungsdateien mithilfe der Google Google Play-URLs aufrufen, müssen Sie der App Dokumentation zur Lizenzierung, um eine Lizenzanfrage durchzuführen. Anschließend können Sie die Namen der Erweiterungsdateien abrufen. Größen und URLs aus den Antwortextras. Sie sollten die Klasse APKExpansionPolicy (in der Library zur Lizenzüberprüfung) als Lizenzierung verwenden , die die Namen, Größen und URLs der Erweiterungsdateien des Lizenzierungsdienstes erfasst.

Downloader-Bibliothek

Um APK-Erweiterungsdateien mit Ihrer App zu verwenden und eine optimale Nutzererfahrung mit für dich mit minimalem Aufwand. Wir empfehlen dir, die Downloader Library zu verwenden, die in der Paket der APK-Erweiterungsbibliothek für Google Play Diese Bibliothek lädt Ihre Erweiterungsdateien Hintergrunddienst, zeigt eine Nutzerbenachrichtigung mit dem Downloadstatus an, verarbeitet die Netzwerkverbindung und den Download nach Möglichkeit fortsetzen.

So implementieren Sie Downloads von Erweiterungsdateien mithilfe der Downloader-Bibliothek:

  • Erweitern Sie eine spezielle Service- und eine BroadcastReceiver-Unterklasse, die jeweils nur wenige Codezeilen von Ihnen.
  • Fügen Sie Ihrer Hauptaktivität Logik hinzu, die prüft, ob die Erweiterungsdateien bereits heruntergeladen wurde. Falls nicht, wird der Download-Prozess aufgerufen und eine Meldung mit einem Fortschritts-UI.
  • Implementieren Sie eine Callback-Oberfläche mit einigen Methoden in Ihrer Hauptaktivität, erhält Updates zum Downloadfortschritt.

In den folgenden Abschnitten wird erläutert, wie Sie Ihre App mithilfe der Downloader-Bibliothek einrichten.

Verwendung der Downloader-Bibliothek vorbereiten

Um die Downloader-Bibliothek zu verwenden, musst du zwei Pakete aus dem SDK Manager herunterladen und die entsprechenden Bibliotheken

Öffnen Sie zuerst den Android SDK Manager (Tools > SDK-Manager) und unter Darstellung und Verhalten > Systemeinstellungen > Android SDK, wählen Sie Tab SDK-Tools, um Folgendes auszuwählen und herunterzuladen:

  • Paket mit der Google Play-Lizenzierungsbibliothek
  • Paket der APK-Erweiterungsbibliothek für Google Play

Neues Bibliotheksmodul für die Lizenzüberprüfungsbibliothek und den Downloader erstellen Mediathek. Für jede Bibliothek:

  1. Wählen Sie Datei > Neu > Neues Modul.
  2. Wähle im Fenster Create New Module (Neues Modul erstellen) die Option Android Library (Android-Bibliothek) aus. und wähle dann Weiter aus.
  3. Geben Sie einen Namen für die App oder Bibliothek an, z. B. „Google Play-Lizenzbibliothek“. und „Google Play Downloader Library“, wählen Sie Minimum SDK Level (Mindest-SDK-Level) und dann Fertigstellen.
  4. Wählen Sie Datei > Projektstruktur.
  5. Wählen Sie den Tab Eigenschaften und dann in der Bibliothek Repository: Geben Sie die Bibliothek aus dem Verzeichnis <sdk>/extras/google/ ein. (play_licensing/ für die License Verification Library oder play_apk_expansion/downloader_library/ für die Downloader Library).
  6. Wählen Sie OK aus, um das neue Modul zu erstellen.

Hinweis:Die Downloader-Bibliothek hängt von der Lizenz ab. Verifizierungsbibliothek. Fügen Sie unbedingt die Lizenz hinzu „Überprüfungsbibliothek“ auf die Projekteigenschaften der Downloader-Bibliothek.

Alternativ können Sie über eine Befehlszeile Ihr Projekt so aktualisieren, dass es die Bibliotheken enthält:

  1. Wechseln Sie in das Verzeichnis <sdk>/tools/.
  2. Führen Sie android update project mit der Option --library aus, um LVL und die Downloader-Bibliothek in Ihr Projekt. Hier einige Beispiele:
    android update project --path ~/Android/MyApp \
    --library ~/android_sdk/extras/google/market_licensing \
    --library ~/android_sdk/extras/google/market_apk_expansion/downloader_library
    

Wenn Sie die Bibliothek für die Lizenzüberprüfung und die Downloader Library App haben, können Sie die Möglichkeit zum Herunterladen von Erweiterungsdateien aus Google Play Das Format, das Sie für die Erweiterungsdateien auswählen, und die Art und Weise, wie sie gelesen werden vom freigegebenen Speicher ist eine separate Implementierung, die Sie aufgrund Ihres App-Anforderungen.

Tipp:Das APK-Erweiterungspaket enthält ein Beispiel App in dem erklärt wird, wie die Downloader-Bibliothek in einer App verwendet wird. Im Beispiel wird eine dritte Bibliothek verwendet. die im APK-Erweiterungspaket namens "APK Expansion Zip Library" verfügbar ist. Wenn Sie planen, für Ihre Erweiterungsdateien verwenden, sollten Sie auch die APK Expansion Zip Library zu für Ihre App. Weitere Informationen finden Sie im folgenden Abschnitt. zur Verwendung der APK Expansion Zip Library

Nutzerberechtigungen deklarieren

Zum Herunterladen der Erweiterungsdateien enthält die Downloader Library erfordert mehrere Berechtigungen, die Sie in der Manifestdatei Ihrer App deklarieren müssen. Sie sind:

<manifest ...>
    <!-- Required to access Google Play Licensing -->
    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />

    <!-- Required to download files from Google Play -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- Required to keep CPU alive while downloading files
        (NOT to keep screen awake) -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <!-- Required to poll the state of the network connection
        and respond to changes -->
    <uses-permission
        android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!-- Required to check whether Wi-Fi is enabled -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

    <!-- Required to read and write the expansion files on shared storage -->
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>

Hinweis:Standardmäßig erfordert die Downloader Library eine API. Ebene 4, aber die APK Expansion Zip Library erfordert API-Level 5.

Downloader-Dienst implementieren

Um Downloads im Hintergrund ausführen zu können, stellt die Downloader Library ihre eigene abgeleitete Service-Klasse namens DownloaderService, die Sie erweitern sollten. In hat der DownloaderService nicht nur die Erweiterungsdateien für Sie heruntergeladen, sondern auch Folgendes:

  • Registriert einen BroadcastReceiver, der auf Änderungen am die Netzwerkverbindung des Geräts (CONNECTIVITY_ACTION Übertragung) verwenden, um den Download bei Bedarf (z. B. bei Verbindungsverlust) zu unterbrechen, und Setzen Sie den Download nach Möglichkeit fort (Verbindung wird hergestellt).
  • Plant einen RTC_WAKEUP-Wecker, um den Download zu wiederholen für in denen der Dienst beendet wird.
  • Erstellt eine benutzerdefinierte Notification, die den Downloadfortschritt anzeigt und Fehler oder Statusänderungen zu erkennen.
  • Ermöglicht Ihrer App, den Download manuell anzuhalten und fortzusetzen.
  • Überprüft, ob der freigegebene Speicher bereitgestellt und verfügbar ist bzw. dass die Dateien noch nicht vorhanden sind. und dass genügend Speicherplatz vorhanden ist, bevor Sie die Erweiterungsdateien herunterladen. Der Nutzer wird dann wenn einer dieser Punkte nicht zutrifft.

Sie müssen lediglich eine Klasse in Ihrer App erstellen, die die DownloaderService-Klasse erweitert, und drei Methoden überschreiben, um bestimmte App-Details anzugeben:

getPublicKey()
Es muss ein String zurückgegeben werden, der der Base64-codierte öffentliche RSA-Schlüssel für Ihren Publisher ist. -Konto, verfügbar über die Profilseite in der Play Console (siehe Einrichtung der Lizenzierung).
getSALT()
Es muss ein Array von zufälligen Byte zurückgegeben werden, die die Lizenzierung Policy verwendet, um erstellen Sie ein Obfuscator. Das Salz sorgt dafür, dass deine verschleierten SharedPreferences Datei, in der Ihre Lizenzierungsdaten gespeichert sind, sind eindeutig und nicht auffindbar.
getAlarmReceiverClassName()
Hierbei muss der Klassenname der BroadcastReceiver in die den Alarm empfangen soll, der besagt, dass der Download neu gestartet. Dies kann passieren, wenn der Downloader-Dienst unerwartet beendet wird.

Hier ein Beispiel einer vollständigen Implementierung von DownloaderService:

Kotlin

// You must use the public key belonging to your publisher account
const val BASE64_PUBLIC_KEY = "YourLVLKey"
// You should also modify this salt
val SALT = byteArrayOf(
        1, 42, -12, -1, 54, 98, -100, -12, 43, 2,
        -8, -4, 9, 5, -106, -107, -33, 45, -1, 84
)

class SampleDownloaderService : DownloaderService() {

    override fun getPublicKey(): String = BASE64_PUBLIC_KEY

    override fun getSALT(): ByteArray = SALT

    override fun getAlarmReceiverClassName(): String = SampleAlarmReceiver::class.java.name
}

Java

public class SampleDownloaderService extends DownloaderService {
    // You must use the public key belonging to your publisher account
    public static final String BASE64_PUBLIC_KEY = "YourLVLKey";
    // You should also modify this salt
    public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98,
            -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84
    };

    @Override
    public String getPublicKey() {
        return BASE64_PUBLIC_KEY;
    }

    @Override
    public byte[] getSALT() {
        return SALT;
    }

    @Override
    public String getAlarmReceiverClassName() {
        return SampleAlarmReceiver.class.getName();
    }
}

Hinweis: Sie müssen den Wert BASE64_PUBLIC_KEY aktualisieren. ist der öffentliche Schlüssel, der zu Ihrem Publisher-Konto gehört. Den Schlüssel finden Sie in der Console unter Ihren Profilinformationen. Dies ist auch beim Testen Ihre Downloads.

Denken Sie daran, den Dienst in Ihrer Manifestdatei zu deklarieren:

<app ...>
    <service android:name=".SampleDownloaderService" />
    ...
</app>

Alarmempfänger implementieren

Um den Fortschritt des Dateidownloads zu beobachten und den Download bei Bedarf neu zu starten, DownloaderService richtet einen RTC_WAKEUP-Wecker ein, der liefert Intent für BroadcastReceiver in Ihrem Sie müssen die BroadcastReceiver definieren, um eine API aufzurufen aus der Downloader Library, die den Status des Downloads prüft und neu startet wenn nötig.

Sie müssen lediglich die Methode onReceive() überschreiben, um DownloaderClientMarshaller.startDownloadServiceIfRequired() aufzurufen.

Beispiel:

Kotlin

class SampleAlarmReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        try {
            DownloaderClientMarshaller.startDownloadServiceIfRequired(
                    context,
                    intent,
                    SampleDownloaderService::class.java
            )
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
        }
    }
}

Java

public class SampleAlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            DownloaderClientMarshaller.startDownloadServiceIfRequired(context,
                intent, SampleDownloaderService.class);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Beachten Sie, dass dies die Klasse ist, für die Sie den Namen zurückgeben müssen. in der getAlarmReceiverClassName()-Methode Ihres Dienstes ein (siehe vorherigen Abschnitt).

Denk daran, den Empfänger in deiner Manifestdatei zu deklarieren:

<app ...>
    <receiver android:name=".SampleAlarmReceiver" />
    ...
</app>

Download wird gestartet

Die Hauptaktivität in Ihrer App (die durch das Launcher-Symbol gestartet wird) ist ist für die Überprüfung, ob die Erweiterungsdateien bereits auf dem Gerät vorhanden sind, und die Initiierung falls dies nicht der Fall ist.

Um den Download über die Downloader-Bibliothek zu starten, ist Folgendes erforderlich: Verfahren:

  1. Prüfen Sie, ob die Dateien heruntergeladen wurden.

    Die Downloader-Bibliothek enthält einige APIs in der Klasse Helper, um Hilfe bei diesem Prozess:

    • getExpansionAPKFileName(Context, c, boolean mainFile, int versionCode)
    • doesFileExist(Context c, String fileName, long fileSize)

    Beispiel: Die im APK-Erweiterungspaket enthaltene Beispiel-App ruft die die folgende Methode in der onCreate()-Methode der Aktivität, Gibt an, ob die Erweiterungsdateien bereits auf dem Gerät vorhanden sind:

    Kotlin

    fun expansionFilesDelivered(): Boolean {
        xAPKS.forEach { xf ->
            Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion).also { fileName ->
                if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false))
                    return false
            }
        }
        return true
    }
    

    Java

    boolean expansionFilesDelivered() {
        for (XAPKFile xf : xAPKS) {
            String fileName = Helpers.getExpansionAPKFileName(this, xf.isBase,
                xf.fileVersion);
            if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false))
                return false;
        }
        return true;
    }
    

    In diesem Fall enthält jedes XAPKFile-Objekt die Versionsnummer und Dateigröße einer bekannten Erweiterungsdatei und einem booleschen Wert, der angibt, ob es sich um die Haupterweiterungsdatei handelt. (Siehe Beispiel SampleDownloaderActivity der App.)

    Wenn diese Methode „false“ zurückgibt, muss der Download der Anwendung beginnen.

  2. Starten Sie den Download durch Aufrufen der statischen Methode DownloaderClientMarshaller.startDownloadServiceIfRequired(Context c, PendingIntent notificationClient, Class<?> serviceClass).

    Die Methode nimmt folgende Parameter an:

    • context: Die Context deiner App.
    • notificationClient: Ein PendingIntent zum Starten deines Haupt- Aktivitäten. Dieser wird in der Notification verwendet, die vom DownloaderService erstellt, um den Downloadfortschritt anzuzeigen. Wenn der Nutzer die Benachrichtigung auswählt, Ruft die PendingIntent auf, die Sie hier angeben, und sollte die Aktivität öffnen der den Downloadfortschritt anzeigt (normalerweise die Aktivität, mit der der Download gestartet wurde).
    • serviceClass: Das Class-Objekt für die Implementierung von DownloaderService, um den Dienst zu starten und gegebenenfalls den Download zu starten.

    Die Methode gibt eine Ganzzahl zurück, ob der Download erforderlich ist. Mögliche Werte sind:

    • NO_DOWNLOAD_REQUIRED: Wird zurückgegeben, wenn die Dateien bereits existieren oder ein Download läuft.
    • LVL_CHECK_REQUIRED: Wird zurückgegeben, wenn eine Lizenzüberprüfung erfolgt ist. erforderlich, um die URLs der Erweiterungsdateien zu erhalten.
    • DOWNLOAD_REQUIRED: Wird zurückgegeben, wenn die URLs der Erweiterungsdateien bereits bekannt sind. aber nicht heruntergeladen wurden.

    Das Verhalten für LVL_CHECK_REQUIRED und DOWNLOAD_REQUIRED entspricht im Wesentlichen und Sie müssen sich darüber keine Gedanken machen. In deiner Hauptaktivität, die startDownloadServiceIfRequired() aufruft, kannst du einfach prüfen, ob die Antwort NO_DOWNLOAD_REQUIRED ist. Wenn die Antwort nicht NO_DOWNLOAD_REQUIRED ist, der Downloader-Bibliothek beginnt und Sie sollten Ihre Aktivitäts-UI so aktualisieren: Downloadfortschritt anzeigen (siehe nächster Schritt). Wenn die Antwort ist NO_DOWNLOAD_REQUIRED, sind die Dateien verfügbar und Ihre Anwendung kann gestartet werden.

    Beispiel:

    Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        // Check if expansion files are available before going any further
        if (!expansionFilesDelivered()) {
            val pendingIntent =
                    // Build an Intent to start this activity from the Notification
                    Intent(this, MainActivity::class.java).apply {
                        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
                    }.let { notifierIntent ->
                        PendingIntent.getActivity(
                                this,
                                0,
                                notifierIntent,
                                PendingIntent.FLAG_UPDATE_CURRENT
                        )
                    }
    
    
            // Start the download service (if required)
            val startResult: Int = DownloaderClientMarshaller.startDownloadServiceIfRequired(
                    this,
                    pendingIntent,
                    SampleDownloaderService::class.java
            )
            // If download has started, initialize this activity to show
            // download progress
            if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
                // This is where you do set up to display the download
                // progress (next step)
                ...
                return
            } // If the download wasn't necessary, fall through to start the app
        }
        startApp() // Expansion files are available, start the app
    }
    

    Java

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // Check if expansion files are available before going any further
        if (!expansionFilesDelivered()) {
            // Build an Intent to start this activity from the Notification
            Intent notifierIntent = new Intent(this, MainActivity.getClass());
            notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                                    Intent.FLAG_ACTIVITY_CLEAR_TOP);
            ...
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                    notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    
            // Start the download service (if required)
            int startResult =
                DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
                            pendingIntent, SampleDownloaderService.class);
            // If download has started, initialize this activity to show
            // download progress
            if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
                // This is where you do set up to display the download
                // progress (next step)
                ...
                return;
            } // If the download wasn't necessary, fall through to start the app
        }
        startApp(); // Expansion files are available, start the app
    }
    
  3. Wenn die Methode startDownloadServiceIfRequired() etwas anderes als NO_DOWNLOAD_REQUIRED, erstellen Sie eine Instanz von IStub, indem Sie DownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class<?> downloaderService) aufrufen. IStub stellt eine Bindung zwischen deiner Aktivität und dem Downloader her. -Dienst, sodass Ihre Aktivität Rückrufe über den Download-Fortschritt empfängt.

    Um IStub durch Aufrufen von CreateStub() zu instanziieren, müssen Sie sie übergeben eine Implementierung der IDownloaderClient-Schnittstelle und Ihres DownloaderService Implementierung. Im nächsten Abschnitt Downloadfortschritt erhalten wird dies Die IDownloaderClient-Schnittstelle, die du normalerweise in deiner Activity-Klasse implementieren solltest, damit du die Aktivitäts-UI aktualisieren kannst, wenn sich der Downloadstatus ändert.

    Wir empfehlen, CreateStub() aufzurufen, um die IStub während der onCreate()-Methode deiner Aktivität nach dem startDownloadServiceIfRequired() zu instanziieren startet den Download.

    Im vorherigen Codebeispiel für onCreate() können Sie auf das startDownloadServiceIfRequired()-Ergebnis beispielsweise so antworten:

    Kotlin

            // Start the download service (if required)
            val startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(
                    this@MainActivity,
                    pendingIntent,
                    SampleDownloaderService::class.java
            )
            // If download has started, initialize activity to show progress
            if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
                // Instantiate a member instance of IStub
                downloaderClientStub =
                        DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService::class.java)
                // Inflate layout that shows download progress
                setContentView(R.layout.downloader_ui)
                return
            }
    

    Java

            // Start the download service (if required)
            int startResult =
                DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
                            pendingIntent, SampleDownloaderService.class);
            // If download has started, initialize activity to show progress
            if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
                // Instantiate a member instance of IStub
                downloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
                        SampleDownloaderService.class);
                // Inflate layout that shows download progress
                setContentView(R.layout.downloader_ui);
                return;
            }
    

    Nachdem die Methode onCreate() zurückgegeben wurde, wird Ihre Aktivität erhält einen Anruf an onResume(). Anschließend sollten Sie Rufen Sie connect() auf der IStub auf und übergeben Sie die Context Ihrer App. Umgekehrt sollten Sie disconnect() im onStop()-Callback deiner Aktivität.

    Kotlin

    override fun onResume() {
        downloaderClientStub?.connect(this)
        super.onResume()
    }
    
    override fun onStop() {
        downloaderClientStub?.disconnect(this)
        super.onStop()
    }
    

    Java

    @Override
    protected void onResume() {
        if (null != downloaderClientStub) {
            downloaderClientStub.connect(this);
        }
        super.onResume();
    }
    
    @Override
    protected void onStop() {
        if (null != downloaderClientStub) {
            downloaderClientStub.disconnect(this);
        }
        super.onStop();
    }
    

    Durch den Aufruf von connect() am IStub wird Ihre Aktivität an die DownloaderService gebunden, sodass Ihre Aktivität Callbacks bezüglich Änderungen am Download erhält. über die IDownloaderClient-Schnittstelle.

Downloadfortschritt wird empfangen

Um Updates zum Downloadfortschritt zu erhalten und mit der DownloaderService zu interagieren, musst du die IDownloaderClient-Schnittstelle der Downloader-Bibliothek implementieren. Die Aktivität, mit der Sie den Download starten, sollte diese Schnittstelle in der Regel implementieren, um den Downloadfortschritt anzuzeigen und Anfragen an den Dienst zu senden.

Die erforderlichen Schnittstellenmethoden für IDownloaderClient sind:

onServiceConnected(Messenger m)
Nachdem Sie die IStub in Ihrer Aktivität instanziiert haben, erhalten Sie einen Aufruf an diese , die ein Messenger-Objekt übergibt, das mit der Instanz verbunden ist. von DownloaderService. Zum Senden von Anfragen an den Dienst, z. B. zum Pausieren und Fortsetzen heruntergeladen wird, musst du DownloaderServiceMarshaller.CreateProxy() aufrufen, um die IDownloaderService-Schnittstelle zu empfangen, die mit dem Dienst verbunden ist.

Eine empfohlene Implementierung sieht so aus:

Kotlin

private var remoteService: IDownloaderService? = null
...

override fun onServiceConnected(m: Messenger) {
    remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply {
        downloaderClientStub?.messenger?.also { messenger ->
            onClientUpdated(messenger)
        }
    }
}

Java

private IDownloaderService remoteService;
...

@Override
public void onServiceConnected(Messenger m) {
    remoteService = DownloaderServiceMarshaller.CreateProxy(m);
    remoteService.onClientUpdated(downloaderClientStub.getMessenger());
}

Wenn das IDownloaderService-Objekt initialisiert ist, können Sie Befehle an die Downloaddienst, beispielsweise zum Pausieren und Fortsetzen des Downloads (requestPauseDownload() und requestContinueDownload()).

onDownloadStateChanged(int newState)
Der Downloaddienst ruft dies auf, wenn sich der Downloadstatus ändert, z. B. die der Download beginnt oder vollständig abgeschlossen ist.

Der Wert newState ist einer von mehreren möglichen Werten, die in durch eine der STATE_*-Konstanten der IDownloaderClient-Klasse.

Sie können einen entsprechenden String anfordern, um Ihren Nutzern eine hilfreiche Nachricht zur Verfügung zu stellen für jeden Bundesstaat durch Aufrufen von Helpers.getDownloaderStringResourceIDFromState(). Dieses gibt die Ressourcen-ID für einen der mit dem Downloader gebündelten Strings zurück. Mediathek. Beispiel: Der String „Download aufgrund von Roaming pausiert“ entspricht STATE_PAUSED_ROAMING.

onDownloadProgress(DownloadProgressInfo progress)
Der Downloaddienst ruft dies auf, um ein DownloadProgressInfo-Objekt bereitzustellen. Sie enthält verschiedene Informationen zum Downloadfortschritt, darunter die geschätzte verbleibende Zeit, die aktuelle Geschwindigkeit, den Gesamtfortschritt und den Gesamtwert, sodass Sie die Benutzeroberfläche für den Downloadfortschritt aktualisieren können.

Tipp:Beispiele für diese Callbacks, die den Download aktualisieren siehe SampleDownloaderActivity in der Beispiel-App, die mit dem APK-Erweiterungspaket.

Einige öffentliche Methoden für die IDownloaderService-Schnittstelle, die Sie möglicherweise nützlich finden, sind:

requestPauseDownload()
Haltt den Download an.
requestContinueDownload()
Setzt einen pausierten Download fort.
setDownloadFlags(int flags)
Hiermit werden die Nutzereinstellungen für Netzwerktypen festgelegt, von denen das Herunterladen der Dateien erlaubt wird. Die Die aktuelle Implementierung unterstützt nur das Flag FLAGS_DOWNLOAD_OVER_CELLULAR. Sie können jedoch andere. Standardmäßig ist dieses Flag nicht aktiviert, d. h., der Nutzer muss zum Herunterladen eine WLAN-Verbindung haben. Erweiterungsdateien. Sie können festlegen, dass Downloads über mit dem Mobilfunknetz verbunden. Rufen Sie in diesem Fall folgende Nummer an:

Kotlin

remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply {
    ...
    setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR)
}

Java

remoteService
    .setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);

APKExpansionPolicy verwenden

Wenn Sie sich dafür entscheiden, einen eigenen Downloader-Dienst zu entwickeln, anstatt Google Play zu verwenden Downloader Library, solltest du weiterhin die APKExpansionPolicy aus der Bibliothek für die Lizenzüberprüfung verwenden. Die Klasse APKExpansionPolicy ist fast identisch mit ServerManagedPolicy (verfügbar in der Google Play License Verification Library, enthält aber zusätzliche Abläufe für die APK-Erweiterung Extras für Dateiantworten.

Hinweis:Wenn Sie die Downloader-Bibliothek wie im vorherigen Abschnitt beschrieben verwenden, alle Interaktionen mit der APKExpansionPolicy-Bibliothek vornehmen. Sie müssen direkt in diesen Kurs.

Die Klasse enthält Methoden, mit denen Sie die erforderlichen Informationen Erweiterungsdateien:

  • getExpansionURLCount()
  • getExpansionURL(int index)
  • getExpansionFileName(int index)
  • getExpansionFileSize(int index)

Weitere Informationen zur Verwendung von APKExpansionPolicy, wenn nicht über die Downloader-Bibliothek finden Sie in der Dokumentation zum Hinzufügen der Lizenzierung zu Ihrer App. in dem erklärt wird, wie eine Lizenzrichtlinie wie diese implementiert wird.

Erweiterungsdatei lesen

Wenn deine APK-Erweiterungsdateien auf dem Gerät gespeichert sind, hängt davon ab, welchen Dateityp Sie verwenden. Wie in der Übersicht erläutert, Erweiterungsdateien können jede Art von Datei sein, aber mit einem bestimmten Dateinamenformat umbenannt und unter folgendem Pfad gespeichert: <shared-storage>/Android/obb/<package-name>/

Unabhängig davon, wie Sie Ihre Dateien lesen, sollten Sie immer zuerst prüfen, ob die externen Dateien Speicherplatz zum Lesen verfügbar ist. Es kann vorkommen, dass der Speicherplatz Computer über USB angeschlossen oder die SD-Karte entfernt hat.

Hinweis:Beim Starten Ihrer App sollten Sie immer prüfen, Der externe Speicherplatz ist verfügbar und kann durch Aufrufen von getExternalStorageState() gelesen werden. Dadurch wird einer von mehreren möglichen Strings zurückgegeben. die den Status des externen Speichers darstellen. Damit die Daten in Ihrem Konto App verwenden, muss der Rückgabewert MEDIA_MOUNTED sein.

Dateinamen abrufen

Wie in der Übersicht beschrieben, werden Ihre APK-Erweiterungsdateien gespeichert mit einem bestimmten Dateinamensformat:

[main|patch].<expansion-version>.<package-name>.obb

Verwenden Sie zum Abrufen des Speicherorts und der Namen Ihrer Erweiterungsdateien die Methode getExternalStorageDirectory() und getPackageName(), um den Pfad zu Ihren Dateien zu erstellen.

Mit dieser Methode können Sie in Ihrer App ein Array abrufen, das den vollständigen Pfad enthält. auf beide Erweiterungsdateien:

Kotlin

fun getAPKExpansionFiles(ctx: Context, mainVersion: Int, patchVersion: Int): Array<String> {
    val packageName = ctx.packageName
    val ret = mutableListOf<String>()
    if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
        // Build the full path to the app's expansion files
        val root = Environment.getExternalStorageDirectory()
        val expPath = File(root.toString() + EXP_PATH + packageName)

        // Check that expansion file path exists
        if (expPath.exists()) {
            if (mainVersion > 0) {
                val strMainPath = "$expPath${File.separator}main.$mainVersion.$packageName.obb"
                val main = File(strMainPath)
                if (main.isFile) {
                    ret += strMainPath
                }
            }
            if (patchVersion > 0) {
                val strPatchPath = "$expPath${File.separator}patch.$mainVersion.$packageName.obb"
                val main = File(strPatchPath)
                if (main.isFile) {
                    ret += strPatchPath
                }
            }
        }
    }
    return ret.toTypedArray()
}

Java

// The shared path to all app expansion files
private final static String EXP_PATH = "/Android/obb/";

static String[] getAPKExpansionFiles(Context ctx, int mainVersion,
      int patchVersion) {
    String packageName = ctx.getPackageName();
    Vector<String> ret = new Vector<String>();
    if (Environment.getExternalStorageState()
          .equals(Environment.MEDIA_MOUNTED)) {
        // Build the full path to the app's expansion files
        File root = Environment.getExternalStorageDirectory();
        File expPath = new File(root.toString() + EXP_PATH + packageName);

        // Check that expansion file path exists
        if (expPath.exists()) {
            if ( mainVersion > 0 ) {
                String strMainPath = expPath + File.separator + "main." +
                        mainVersion + "." + packageName + ".obb";
                File main = new File(strMainPath);
                if ( main.isFile() ) {
                        ret.add(strMainPath);
                }
            }
            if ( patchVersion > 0 ) {
                String strPatchPath = expPath + File.separator + "patch." +
                        mainVersion + "." + packageName + ".obb";
                File main = new File(strPatchPath);
                if ( main.isFile() ) {
                        ret.add(strPatchPath);
                }
            }
        }
    }
    String[] retArray = new String[ret.size()];
    ret.toArray(retArray);
    return retArray;
}

Sie können diese Methode aufrufen, indem Sie sie an Ihre App Context übergeben. und die Version der gewünschten Erweiterungsdatei.

Es gibt viele Möglichkeiten, die Versionsnummer der Erweiterungsdatei zu ermitteln. Eine einfache Möglichkeit besteht darin, die Version zu Beginn des Downloads in einer SharedPreferences-Datei speichern, indem Sie Abfrage des Namens der Erweiterungsdatei mit der Methode getExpansionFileName(int index) der Klasse APKExpansionPolicy. Sie können dann den Versionscode abrufen, indem Sie die Datei SharedPreferences lesen, wenn Sie auf die Erweiterung zugreifen möchten -Datei.

Weitere Informationen zum Auslesen aus dem freigegebenen Speicher finden Sie im Abschnitt zur Datenspeicherung. Dokumentation.

Verwenden der APK Expansion Zip-Bibliothek

Das APK-Erweiterungspaket für Google Market enthält eine APK-Bibliothek. Erweiterungs-Zip-Bibliothek (in <sdk>/extras/google/google_market_apk_expansion/zip_file/). Dies ist eine optionale Bibliothek, können Sie die Erweiterung wenn sie als ZIP-Dateien gespeichert werden. Mit dieser Bibliothek können Sie ganz einfach Ressourcen aus ZIP-Erweiterungsdateien als virtuelles Dateisystem.

Die APK Expansion Zip-Bibliothek enthält die folgenden Klassen und APIs:

APKExpansionSupport
Bietet einige Methoden für den Zugriff auf Namen von Erweiterungsdateien und ZIP-Dateien: <ph type="x-smartling-placeholder">
</ph>
getAPKExpansionFiles()
Dieselbe Methode wie oben, bei der der vollständige Dateipfad sowohl an die Erweiterung Dateien.
getAPKExpansionZipFile(Context ctx, int mainVersion, int patchVersion)
Gibt eine ZipResourceFile zurück, die die Summe aus Hauptdatei und Patch-Datei. Wenn Sie also sowohl das mainVersion als auch das patchVersion, wird ein ZipResourceFile zurückgegeben, das Lesezugriff auf alle Daten, wobei die Daten der Patchdatei über der Hauptdatei zusammengeführt wurden.
ZipResourceFile
Repräsentiert eine ZIP-Datei im freigegebenen Speicher und führt alle erforderlichen Schritte für die Bereitstellung einer virtuellen basierend auf Ihren ZIP-Dateien. Sie können eine Instanz mit APKExpansionSupport.getAPKExpansionZipFile() oder mit dem ZipResourceFile abrufen, indem Sie die Pfad zu Ihrer Erweiterungsdatei. Diese Klasse umfasst eine Vielzahl nützlicher Methoden. In der Regel auf die meisten von ihnen nicht zugreifen. Einige wichtige Methoden sind: <ph type="x-smartling-placeholder">
</ph>
getInputStream(String assetPath)
Stellt ein InputStream zum Lesen einer Datei in der ZIP-Datei bereit. Die assetPath muss der Pfad zur gewünschten Datei sein, relativ zu das Stammverzeichnis des Inhalts der ZIP-Datei.
getAssetFileDescriptor(String assetPath)
Stellt ein AssetFileDescriptor für eine Datei im ZIP-Datei. assetPath muss der Pfad zur gewünschten Datei sein, relativ zu das Stammverzeichnis des Inhalts der ZIP-Datei. Dies ist bei bestimmten Android-APIs nützlich, die eine AssetFileDescriptor erfordern, z. B. einige MediaPlayer-APIs.
APEZProvider
Die meisten Apps benötigen diesen Kurs nicht. Diese Klasse definiert ein ContentProvider, das die Daten aus den ZIP-Dateien über einen Inhalt verteilt. Uri, um Dateizugriff für bestimmte Android-APIs bereitzustellen, die Uri-Zugriff auf Mediendateien. Dies ist beispielsweise nützlich, wenn Sie Spiel ein Video mit VideoView.setVideoURI() ab.

ZIP-Komprimierung von Mediendateien überspringen

Auch wenn Sie Ihre Erweiterungsdateien zum Speichern von Mediendateien verwenden, können Sie mit einer ZIP-Datei Android-Anrufe für die Medienwiedergabe verwenden, die Versatz- und Längensteuerung ermöglichen (z. B. MediaPlayer.setDataSource() und SoundPool.load()). Damit Damit dies funktioniert, dürfen die Mediendateien beim Erstellen der ZIP-Datei nicht zusätzlich komprimiert werden. Pakete. Wenn Sie beispielsweise das zip-Tool verwenden, sollten Sie das -n-Tool verwenden. zur Angabe der Dateisuffixe, die nicht komprimiert werden sollen:

zip -n .mp4;.ogg main_expansion media_files

Aus einer ZIP-Datei lesen

Wenn Sie die APK Expansion Zip Library verwenden, benötigen Sie zum Lesen einer Datei aus Ihrer ZIP-Datei in der Regel die Folgendes:

Kotlin

// Get a ZipResourceFile representing a merger of both the main and patch files
val expansionFile =
        APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion)

// Get an input stream for a known file inside the expansion file ZIPs
expansionFile.getInputStream(pathToFileInsideZip).use {
    ...
}

Java

// Get a ZipResourceFile representing a merger of both the main and patch files
ZipResourceFile expansionFile =
    APKExpansionSupport.getAPKExpansionZipFile(appContext,
        mainVersion, patchVersion);

// Get an input stream for a known file inside the expansion file ZIPs
InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);

Der obige Code bietet Zugriff auf jede Datei, die entweder in Ihrer Haupt-Erweiterungsdatei oder in Patch-Erweiterungsdatei, indem alle Dateien aus beiden Dateien aus einer zusammengeführten Zuordnung gelesen werden. Alles für dich die getAPKExpansionFile()-Methode deine App-android.content.Context und die Versionsnummer für die Haupterweiterungsdatei und den Patch angeben müssen. Erweiterungsdatei.

Wenn Sie lieber aus einer bestimmten Erweiterungsdatei lesen möchten, können Sie den ZipResourceFile-Konstruktor mit dem Pfad zur gewünschten Erweiterungsdatei verwenden:

Kotlin

// Get a ZipResourceFile representing a specific expansion file
val expansionFile = ZipResourceFile(filePathToMyZip)

// Get an input stream for a known file inside the expansion file ZIPs
expansionFile.getInputStream(pathToFileInsideZip).use {
    ...
}

Java

// Get a ZipResourceFile representing a specific expansion file
ZipResourceFile expansionFile = new ZipResourceFile(filePathToMyZip);

// Get an input stream for a known file inside the expansion file ZIPs
InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);

Weitere Informationen zur Verwendung dieser Bibliothek für Ihre Erweiterungsdateien finden Sie unter Die Klasse SampleDownloaderActivity der Beispiel-App, die zusätzlichen Code zum Überprüfen Sie die heruntergeladenen Dateien mit CRC. Wenn Sie dieses Beispiel als Grundlage für Ihre eigene Implementierung verwenden, müssen Sie die Bytegröße Ihrer Erweiterung Dateien im xAPKS-Array.

Erweiterungsdateien testen

Bevor Sie Ihre App veröffentlichen, sollten Sie zwei Dinge testen: Erweiterungsdateien und Herunterladen der Dateien.

Dateilesevorgänge testen

Bevor Sie Ihre App bei Google Play hochladen, sollte die Fähigkeit Ihrer App testen, Dateien aus dem freigegebenen Speicher zu lesen. Alles, was du tun musst fügen Sie die Dateien am entsprechenden Speicherort im freigegebenen Gerätespeicher hinzu und starten die App:

  1. Erstellen Sie auf Ihrem Gerät das entsprechende Verzeichnis im freigegebenen Speicher, in dem Google Google Play speichert deine Dateien.

    Lautet der Paketname beispielsweise com.example.android, müssen Sie das Verzeichnis Android/obb/com.example.android/ im freigegebenen Speicherplatz. (Anschließen das Testgerät an Ihren Computer an, um den freigegebenen Speicher bereitzustellen, und erstellen Sie Verzeichnis.)

  2. Fügen Sie die Erweiterungsdateien manuell zu diesem Verzeichnis hinzu. Benennen Sie Ihre Dateien in Sie entsprechen dem Format des Dateinamens, das von Google Play verwendet wird.

    Unabhängig vom Dateityp sollte die Haupterweiterungsdatei für die App com.example.android beispielsweise main.0300110.com.example.android.obb sein. Der Versionscode kann ein beliebiger Wert sein. Denken Sie daran:

    • Die Haupterweiterungsdatei beginnt immer mit main und die Patchdatei mit patch.
    • Der Paketname stimmt immer mit dem Namen des APK überein, an das die Datei angehängt ist. Google Play
  3. Da sich nun die Erweiterungsdateien auf dem Gerät befinden, können Sie Ihre App installieren und ausführen, Testen Sie Ihre Erweiterungsdatei(en).

Im Folgenden finden Sie einige Hinweise zum Umgang mit Erweiterungsdateien:

  • .obb-Erweiterungsdateien nicht löschen oder umbenennen (auch nicht beim Entpacken) an einem anderen Ort speichern). Dies führt dazu, dass Google Play (oder Ihre App selbst) die Erweiterungsdatei wiederholt herunterladen.
  • Speichere keine anderen Daten auf deinem obb/ Verzeichnis. Wenn Sie einige Daten entpacken müssen, speichern Sie sie an dem durch getExternalFilesDir() angegebenen Speicherort.

Dateidownloads testen

Weil Ihre App die Erweiterungsdateien manchmal manuell herunterladen muss öffnen, ist es wichtig, dass Sie diesen Prozess testen, um sicherzustellen, dass Ihre App erfolgreich Abfragen für die URLs, laden Sie die Dateien herunter und speichern Sie sie auf dem Gerät.

So testen Sie die Implementierung des manuellen Downloadvorgangs in Ihrer App: können Sie es im internen Test-Track veröffentlichen, damit es nur für Nutzer verfügbar ist, autorisierten Testern. Wenn alles wie erwartet funktioniert, sollte Ihre App die Erweiterungsdateien herunterladen, sobald die Hauptaktivität beginnt.

Hinweis:Bisher konnten Sie Apps testen, indem Sie Hochladen eines unveröffentlichten "Entwurfs" Version. Diese Funktion ist nicht mehr unterstützt. Sie müssen sie stattdessen in einem internen, geschlossenen oder offenen Test veröffentlichen. Titel. Weitere Informationen finden Sie unter App-Entwürfe sind nicht Länger unterstützt.

App aktualisieren

Einer der großen Vorteile von Erweiterungsdateien bei Google Play ist die Möglichkeit, aktualisieren, ohne alle ursprünglichen Assets noch einmal herunterzuladen. Weil Google Play kannst du mit jedem APK zwei Erweiterungsdateien bereitstellen. Die zweite Datei kann als Patch verwendet werden. mit Updates und neuen Assets. Dadurch wird der Fehler die Haupterweiterungsdatei, die für Nutzer sehr groß und teuer sein könnte, erneut herunterladen.

Die Patch-Erweiterungsdatei entspricht technisch der Haupt-Erweiterungsdatei und Das Android-System oder Google Play führen tatsächliche Patches zwischen der Haupt- und der Patcherweiterung aus. Dateien. Alle erforderlichen Patches müssen von Ihrem App-Code selbst ausgeführt werden.

Wenn Sie ZIP-Dateien als Erweiterungsdateien verwenden, gibt die APK Expansion Zip Die im APK-Erweiterungspaket enthaltene Bibliothek enthält die Möglichkeit, Ihr Patchdatei mit der Haupterweiterungsdatei.

Hinweis:Auch wenn Sie nur Änderungen am Patch vornehmen müssen Erweiterungsdatei müssen Sie trotzdem das APK aktualisieren, damit Google Play ein Update durchführen kann. Wenn keine Codeänderungen in der App erforderlich sind, aktualisieren Sie einfach versionCode in der Manifests.

Solange Sie die Haupterweiterungsdatei, die mit dem APK verknüpft ist, nicht ändern in der Play Console angezeigt, können Nutzer, die Ihre App bereits installiert haben, die Haupterweiterungsdatei herunterladen. Bestehende Nutzer erhalten nur das aktualisierte APK und den neuen Patch Erweiterungsdatei (unter Beibehaltung der vorherigen Haupterweiterungsdatei).

Im Zusammenhang mit der Aktualisierung von Erweiterungsdateien sind folgende Punkte zu beachten:

  • Es können immer nur zwei Erweiterungsdateien für Ihre App gleichzeitig vorhanden sein. Eine Haupterweiterung und eine Patch-Erweiterungsdatei. Während der Aktualisierung einer Datei löscht Google Play Folgendes: frühere Version (genauso wie bei manueller Aktualisierung der App).
  • Beim Hinzufügen einer Patch-Erweiterungsdatei wird Ihre Datei vom Android-System nicht gepatcht. App- oder Haupterweiterungsdatei. Sie müssen Ihre App so konzipieren, dass sie die Patchdaten unterstützt. Das APK-Erweiterungspaket enthält jedoch eine Bibliothek zur Verwendung von ZIP-Dateien. als Erweiterungsdateien, wodurch die Daten aus der Patchdatei in der Haupterweiterungsdatei zusammengeführt werden, können Sie alle Daten der Erweiterungsdateien leicht lesen.