App-Sicherheit verbessern

Wenn Sie Ihre App sicherer machen, tragen Sie dazu bei, das Vertrauen der Nutzer und die Geräteintegrität zu wahren.

Auf dieser Seite werden mehrere Best Practices vorgestellt, die sich positiv auf die Sicherheit Ihrer App auswirken.

Sichere Kommunikation erzwingen

Wenn Sie die Daten schützen, die Sie zwischen Ihrer App und anderen Apps oder zwischen Ihrer App und einer Website austauschen, verbessern Sie die Stabilität Ihrer App und schützen die Daten, die Sie senden und empfangen.

Kommunikation zwischen Apps absichern

Wenn Sie sicherer zwischen Anwendungen kommunizieren möchten, verwenden Sie implizite Intents mit einer App-Auswahl, signaturbasierten Berechtigungen und nicht exportierten Inhaltsanbietern.

App-Auswahl anzeigen

Wenn mit einer impliziten Intent-Anfrage mindestens zwei Apps auf dem Gerät eines Nutzers gestartet werden können, zeigen Sie explizit eine App-Auswahl an. Mit dieser Interaktionsstrategie können Nutzer vertrauliche Daten an eine vertrauenswürdige App übertragen.

Kotlin

val intent = Intent(Intent.ACTION_SEND)
val possibleActivitiesList: List<ResolveInfo> =
        packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL)

// Verify that an activity in at least two apps on the user's device
// can handle the intent. Otherwise, start the intent only if an app
// on the user's device can handle the intent.
if (possibleActivitiesList.size > 1) {

    // Create intent to show chooser.
    // Title is something similar to "Share this photo with."

    val chooser = resources.getString(R.string.chooser_title).let { title ->
        Intent.createChooser(intent, title)
    }
    startActivity(chooser)
} else if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
List<ResolveInfo> possibleActivitiesList = getPackageManager()
        .queryIntentActivities(intent, PackageManager.MATCH_ALL);

// Verify that an activity in at least two apps on the user's device
// can handle the intent. Otherwise, start the intent only if an app
// on the user's device can handle the intent.
if (possibleActivitiesList.size() > 1) {

    // Create intent to show chooser.
    // Title is something similar to "Share this photo with."

    String title = getResources().getString(R.string.chooser_title);
    Intent chooser = Intent.createChooser(intent, title);
    startActivity(chooser);
} else if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
}

Weitere Informationen:

Signaturbasierte Berechtigungen anwenden

Wenn Sie Daten zwischen zwei Apps teilen, die Sie verwalten oder besitzen, verwenden Sie signaturbasierte Berechtigungen. Für diese Berechtigungen ist keine Nutzerbestätigung erforderlich. Stattdessen wird geprüft, ob die Apps, die auf die Daten zugreifen, mit demselben Signaturschlüssel signiert sind. Diese Berechtigungen bieten daher eine optimierte und sicherere Nutzererfahrung.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <permission android:name="my_custom_permission_name"
                android:protectionLevel="signature" />

Weitere Informationen :

Zugriff auf die Contentanbieter Ihrer App nicht zulassen

Sofern Sie nicht beabsichtigen, Daten aus Ihrer App an eine andere App zu senden, deren Eigentümer Sie nicht sind, sollten Sie Apps anderer Entwickler explizit den Zugriff auf die ContentProvider-Objekte Ihrer App verweigern. Diese Einstellung ist besonders wichtig, wenn deine App auf Geräten mit Android 4.1.1 (API-Level 16) oder niedriger installiert werden kann, da das Attribut android:exported des Elements <provider> bei diesen Android-Versionen standardmäßig den Wert true hat.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application ... >
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.myapp.fileprovider"
            ...
            android:exported="false">
            <!-- Place child elements of <provider> here. -->
        </provider>
        ...
    </application>
</manifest>

Vor dem Anzeigen vertraulicher Informationen um Anmeldedaten bitten

Wenn Sie von Nutzern Anmeldedaten anfordern, damit sie auf vertrauliche Informationen oder Premiuminhalte in Ihrer App zugreifen können, fordern Sie entweder eine PIN, ein Passwort oder ein Muster oder biometrische Anmeldedaten wie die Gesichts- oder Fingerabdruckerkennung an.

Weitere Informationen zum Anfordern biometrischer Anmeldedaten finden Sie im Leitfaden zur biometrischen Authentifizierung.

Netzwerksicherheitsmaßnahmen anwenden

In den folgenden Abschnitten wird beschrieben, wie Sie die Netzwerksicherheit Ihrer App verbessern können.

TLS-Traffic verwenden

Wenn Ihre Anwendung mit einem Webserver kommuniziert, dessen Zertifikat von einer bekannten, vertrauenswürdigen Zertifizierungsstelle ausgestellt wurde, verwenden Sie eine HTTPS-Anfrage wie die folgende:

Kotlin

val url = URL("https://www.google.com")
val urlConnection = url.openConnection() as HttpsURLConnection
urlConnection.connect()
urlConnection.inputStream.use {
    ...
}

Java

URL url = new URL("https://www.google.com");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.connect();
InputStream in = urlConnection.getInputStream();

Netzwerksicherheitskonfiguration hinzufügen

Wenn Ihre App neue oder benutzerdefinierte Zertifizierungsstellen verwendet, können Sie die Sicherheitseinstellungen Ihres Netzwerks in einer Konfigurationsdatei angeben. So können Sie die Konfiguration erstellen, ohne den App-Code zu ändern.

So fügen Sie Ihrer App eine Konfigurationsdatei für die Netzwerksicherheit hinzu:

  1. Deklarieren Sie die Konfiguration im Manifest Ihrer App:
  2. <manifest ... >
        <application
            android:networkSecurityConfig="@xml/network_security_config"
            ... >
            <!-- Place child elements of <application> element here. -->
        </application>
    </manifest>
  3. Fügen Sie eine XML-Ressourcendatei unter res/xml/network_security_config.xml hinzu.

    Legen Sie fest, dass für den gesamten Traffic zu bestimmten Domains HTTPS verwendet werden muss, indem Sie den Klartext deaktivieren:

    <network-security-config>
        <domain-config cleartextTrafficPermitted="false">
            <domain includeSubdomains="true">secure.example.com</domain>
            ...
        </domain-config>
    </network-security-config>

    Während des Entwicklungsprozesses können Sie das Element <debug-overrides> verwenden, um vom Nutzer installierte Zertifikate explizit zuzulassen. Mit diesem Element werden die sicherheitskritischen Optionen Ihrer App während des Debuggens und Testens überschrieben, ohne dass sich dies auf die Release-Konfiguration der App auswirkt. Das folgende Snippet zeigt, wie dieses Element in der XML-Datei zur Konfiguration der Netzwerksicherheit deiner App definiert wird:

    <network-security-config>
        <debug-overrides>
            <trust-anchors>
                <certificates src="user" />
            </trust-anchors>
        </debug-overrides>
    </network-security-config>

Weitere Informationen: Netzwerksicherheitskonfiguration

Eigenen Trust Manager erstellen

Ihr TLS-Prüftool sollte nicht jedes Zertifikat akzeptieren. Möglicherweise müssen Sie einen Trust Manager einrichten und alle TLS-Warnungen behandeln, die auftreten, wenn eine der folgenden Bedingungen für Ihren Anwendungsfall zutrifft:

  • Sie kommunizieren mit einem Webserver, dessen Zertifikat von einer neuen oder benutzerdefinierten Zertifizierungsstelle signiert wurde.
  • Diese Zertifizierungsstelle wird von dem verwendeten Gerät als nicht vertrauenswürdig eingestuft.
  • Sie können keine Netzwerksicherheitskonfiguration verwenden.

Weitere Informationen dazu, wie Sie diese Schritte ausführen, finden Sie im Abschnitt zum Umgang mit einer unbekannten Zertifizierungsstelle.

Weitere Informationen:

WebView-Objekte mit Bedacht verwenden

WebView Über Objekte in Ihrer App dürfen Nutzer nicht auf Websites zugreifen, die nicht in Ihrer Kontrolle stehen. Verwenden Sie nach Möglichkeit eine Zulassungsliste, um die Inhalte einzuschränken, die von den WebView-Objekten Ihrer App geladen werden.

Außerdem sollten Sie die Unterstützung der JavaScript-Schnittstelle nur aktivieren, wenn Sie die Inhalte in den WebView-Objekten Ihrer App vollständig kontrollieren und vertrauen.

HTML-Nachrichtenkanäle verwenden

Wenn Ihre App die JavaScript-Benutzeroberfläche auf Geräten mit Android 6.0 (API-Ebene 23) und höher unterstützen muss, verwenden Sie HTML-Nachrichtenkanäle, anstatt zwischen einer Website und Ihrer App zu kommunizieren, wie im folgenden Code-Snippet gezeigt:

Kotlin

val myWebView: WebView = findViewById(R.id.webview)

// channel[0] and channel[1] represent the two ports.
// They are already entangled with each other and have been started.
val channel: Array<out WebMessagePort> = myWebView.createWebMessageChannel()

// Create handler for channel[0] to receive messages.
channel[0].setWebMessageCallback(object : WebMessagePort.WebMessageCallback() {

    override fun onMessage(port: WebMessagePort, message: WebMessage) {
        Log.d(TAG, "On port $port, received this message: $message")
    }
})

// Send a message from channel[1] to channel[0].
channel[1].postMessage(WebMessage("My secure message"))

Java

WebView myWebView = (WebView) findViewById(R.id.webview);

// channel[0] and channel[1] represent the two ports.
// They are already entangled with each other and have been started.
WebMessagePort[] channel = myWebView.createWebMessageChannel();

// Create handler for channel[0] to receive messages.
channel[0].setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
    @Override
    public void onMessage(WebMessagePort port, WebMessage message) {
         Log.d(TAG, "On port " + port + ", received this message: " + message);
    }
});

// Send a message from channel[1] to channel[0].
channel[1].postMessage(new WebMessage("My secure message"));

Weitere Informationen:

Die richtigen Berechtigungen bereitstellen

Fordern Sie nur die Mindestanzahl an Berechtigungen an, die für die ordnungsgemäße Funktion Ihrer App erforderlich sind. Legen Sie Berechtigungen nach Möglichkeit zurück, wenn Ihre App sie nicht mehr benötigt.

Berechtigungen mit Intents verschieben

Fügen Sie Ihrer App nach Möglichkeit keine Berechtigung hinzu, um eine Aktion auszuführen, die in einer anderen App ausgeführt werden kann. Verwenden Sie stattdessen einen Intent, um die Anfrage an eine andere App weiterzuleiten, die bereits die erforderliche Berechtigung hat.

Im folgenden Beispiel wird gezeigt, wie Sie Nutzer mithilfe einer Intent-Anfrage zu einer Kontakt-App weiterleiten, anstatt die Berechtigungen READ_CONTACTS und WRITE_CONTACTS anzufordern:

Kotlin

// Delegates the responsibility of creating the contact to a contacts app,
// which has already been granted the appropriate WRITE_CONTACTS permission.
Intent(Intent.ACTION_INSERT).apply {
    type = ContactsContract.Contacts.CONTENT_TYPE
}.also { intent ->
    // Make sure that the user has a contacts app installed on their device.
    intent.resolveActivity(packageManager)?.run {
        startActivity(intent)
    }
}

Java

// Delegates the responsibility of creating the contact to a contacts app,
// which has already been granted the appropriate WRITE_CONTACTS permission.
Intent insertContactIntent = new Intent(Intent.ACTION_INSERT);
insertContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);

// Make sure that the user has a contacts app installed on their device.
if (insertContactIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(insertContactIntent);
}

Wenn Ihre Anwendung außerdem dateibasierte E/A-Vorgänge ausführen muss, z. B. auf Speicher zugreifen oder eine Datei auswählen, sind keine besonderen Berechtigungen erforderlich, da das System die Vorgänge im Namen Ihrer Anwendung ausführen kann. Noch besser: Wenn ein Nutzer Inhalte unter einem bestimmten URI auswählt, erhält die aufrufende App die Berechtigung für die ausgewählte Ressource.

Weitere Informationen:

Daten sicher zwischen Apps teilen

Beachte die folgenden Best Practices, um die Inhalte deiner App sicherer mit anderen Apps zu teilen:

Im folgenden Code-Snippet wird gezeigt, wie Sie mithilfe von Flags für die URI-Berechtigungsüberprüfung und Berechtigungen für Inhaltsanbieter die PDF-Datei einer App in einer separaten PDF-Betrachter-App anzeigen:

Kotlin

// Create an Intent to launch a PDF viewer for a file owned by this app.
Intent(Intent.ACTION_VIEW).apply {
    data = Uri.parse("content://com.example/personal-info.pdf")

    // This flag gives the started app read access to the file.
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}.also { intent ->
    // Make sure that the user has a PDF viewer app installed on their device.
    intent.resolveActivity(packageManager)?.run {
        startActivity(intent)
    }
}

Java

// Create an Intent to launch a PDF viewer for a file owned by this app.
Intent viewPdfIntent = new Intent(Intent.ACTION_VIEW);
viewPdfIntent.setData(Uri.parse("content://com.example/personal-info.pdf"));

// This flag gives the started app read access to the file.
viewPdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Make sure that the user has a PDF viewer app installed on their device.
if (viewPdfIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(viewPdfIntent);
}

Hinweis : Das Ausführen von Dateien aus dem beschreibbaren Basisverzeichnis der App ist ein W^X-Verstoß. Aus diesem Grund können nicht vertrauenswürdige Apps, die auf Android 10 (API-Level 29) und höher ausgerichtet sind, exec() nicht auf Dateien im Basisverzeichnis der App aufrufen, sondern nur auf den Binärcode, der in der APK-Datei einer App eingebettet ist. Außerdem können Apps, die auf Android 10 und höher ausgerichtet sind, ausführbaren Code aus Dateien, die mit dlopen() geöffnet wurden, nicht im Arbeitsspeicher ändern. Dies gilt auch für gemeinsam genutzte Objektdateien (.so) mit Textverschiebungen.

Weitere Informationen: android:grantUriPermissions

Daten sicher speichern

Auch wenn Ihre Anwendung möglicherweise Zugriff auf vertrauliche Nutzerinformationen benötigt, gewähren Nutzer Ihrer Anwendung nur dann Zugriff auf ihre Daten, wenn sie darauf vertrauen, dass Sie sie ordnungsgemäß schützen.

Private Daten im internen Speicher speichern

Speichern Sie alle privaten Nutzerdaten im internen Speicher des Geräts, der für jede App in einer Sandbox isoliert ist. Ihre App muss keine Berechtigung zum Ansehen dieser Dateien anfordern und andere Apps können nicht auf die Dateien zugreifen. Als zusätzliche Sicherheitsmaßnahme werden beim Deinstallieren einer App alle Dateien gelöscht, die die App im internen Speicher gespeichert hat.

Das folgende Code-Snippet zeigt eine Möglichkeit, Daten in den internen Speicher zu schreiben:

Kotlin

// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
val FILE_NAME = "sensitive_info.txt"
val fileContents = "This is some top-secret information!"
File(filesDir, FILE_NAME).bufferedWriter().use { writer ->
    writer.write(fileContents)
}

Java

// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
final String FILE_NAME = "sensitive_info.txt";
String fileContents = "This is some top-secret information!";
try (BufferedWriter writer =
             new BufferedWriter(new FileWriter(new File(getFilesDir(), FILE_NAME)))) {
    writer.write(fileContents);
} catch (IOException e) {
    // Handle exception.
}

Das folgende Code-Snippet zeigt den umgekehrten Vorgang, das Lesen von Daten aus dem internen Speicher:

Kotlin

val FILE_NAME = "sensitive_info.txt"
val contents = File(filesDir, FILE_NAME).bufferedReader().useLines { lines ->
    lines.fold("") { working, line ->
        "$working\n$line"
    }
}

Java

final String FILE_NAME = "sensitive_info.txt";
StringBuffer stringBuffer = new StringBuffer();
try (BufferedReader reader =
             new BufferedReader(new FileReader(new File(getFilesDir(), FILE_NAME)))) {

    String line = reader.readLine();
    while (line != null) {
        stringBuffer.append(line).append('\n');
        line = reader.readLine();
    }
} catch (IOException e) {
    // Handle exception.
}

Weitere Informationen:

Daten je nach Anwendungsfall im externen Speicher speichern

Verwenden Sie externen Speicher für große, nicht vertrauliche Dateien, die speziell für Ihre Anwendung gelten, sowie für Dateien, die Ihre Anwendung für andere Anwendungen freigibt. Welche APIs Sie genau verwenden, hängt davon ab, ob Ihre App für den Zugriff auf anwendungsspezifische Dateien oder für den Zugriff auf freigegebene Dateien entwickelt wurde.

Wenn eine Datei keine privaten oder vertraulichen Informationen enthält, aber für den Nutzer nur in Ihrer App von Nutzen ist, speichern Sie sie in einem anwendungsspezifischen Verzeichnis im externen Speicher.

Wenn Ihre App auf eine Datei zugreifen oder eine Datei speichern muss, die für andere Apps von Nutzen ist, verwenden Sie je nach Anwendungsfall eine der folgenden APIs:

  • Mediendateien:Verwenden Sie die MediaStore API, um Bilder, Audiodateien und Videos zu speichern und darauf zuzugreifen, die zwischen Apps freigegeben werden.
  • Andere Dateien:Verwenden Sie das Storage Access Framework, um andere Arten freigegebener Dateien, einschließlich heruntergeladener Dateien, zu speichern und darauf zuzugreifen.

Verfügbarkeit des Speichervolumes prüfen

Wenn Ihre App mit einem externen Wechselspeichergerät interagiert, kann der Nutzer das Speichergerät entfernen, während Ihre App versucht, darauf zuzugreifen. Fügen Sie eine Logik hinzu, um zu prüfen, ob das Speichergerät verfügbar ist.

Gültigkeit von Daten prüfen

Wenn Ihre App Daten aus dem externen Speicher verwendet, achten Sie darauf, dass der Inhalt der Daten nicht beschädigt oder geändert wurde. Fügen Sie Logik zum Umgang mit Dateien hinzu, die sich nicht mehr in einem stabilen Format befinden.

Das folgende Code-Snippet enthält ein Beispiel für einen Hash-Prüfwert:

Kotlin

val hash = calculateHash(stream)
// Store "expectedHash" in a secure location.
if (hash == expectedHash) {
    // Work with the content.
}

// Calculating the hash code can take quite a bit of time, so it shouldn't
// be done on the main thread.
suspend fun calculateHash(stream: InputStream): String {
    return withContext(Dispatchers.IO) {
        val digest = MessageDigest.getInstance("SHA-512")
        val digestStream = DigestInputStream(stream, digest)
        while (digestStream.read() != -1) {
            // The DigestInputStream does the work; nothing for us to do.
        }
        digest.digest().joinToString(":") { "%02x".format(it) }
    }
}

Java

Executor threadPoolExecutor = Executors.newFixedThreadPool(4);
private interface HashCallback {
    void onHashCalculated(@Nullable String hash);
}

boolean hashRunning = calculateHash(inputStream, threadPoolExecutor, hash -> {
    if (Objects.equals(hash, expectedHash)) {
        // Work with the content.
    }
});

if (!hashRunning) {
    // There was an error setting up the hash function.
}

private boolean calculateHash(@NonNull InputStream stream,
                              @NonNull Executor executor,
                              @NonNull HashCallback hashCallback) {
    final MessageDigest digest;
    try {
        digest = MessageDigest.getInstance("SHA-512");
    } catch (NoSuchAlgorithmException nsa) {
        return false;
    }

    // Calculating the hash code can take quite a bit of time, so it shouldn't
    // be done on the main thread.
    executor.execute(() -> {
        String hash;
        try (DigestInputStream digestStream =
                new DigestInputStream(stream, digest)) {
            while (digestStream.read() != -1) {
                // The DigestInputStream does the work; nothing for us to do.
            }
            StringBuilder builder = new StringBuilder();
            for (byte aByte : digest.digest()) {
                builder.append(String.format("%02x", aByte)).append(':');
            }
            hash = builder.substring(0, builder.length() - 1);
        } catch (IOException e) {
            hash = null;
        }

        final String calculatedHash = hash;
        runOnUiThread(() -> hashCallback.onHashCalculated(calculatedHash));
    });
    return true;
}

Speichern Sie nur nicht vertrauliche Daten in Cachedateien.

Speichern Sie nicht sensible App-Daten im Cache des Geräts, um schnelleren Zugriff auf nicht vertrauliche App-Daten zu ermöglichen. Verwenden Sie für Caches, die größer als 1 MB sind, getExternalCacheDir(). Verwenden Sie für Caches mit einer Größe von maximal 1 MB getCacheDir(). Bei beiden Methoden erhalten Sie das File-Objekt, das die im Cache Ihrer App gespeicherten Daten enthält.

Das folgende Code-Snippet zeigt, wie Sie eine Datei im Cache speichern, die Ihre App vor Kurzem heruntergeladen hat:

Kotlin

val cacheFile = File(myDownloadedFileUri).let { fileToCache ->
    File(cacheDir.path, fileToCache.name)
}

Java

File cacheDir = getCacheDir();
File fileToCache = new File(myDownloadedFileUri);
String fileToCacheName = fileToCache.getName();
File cacheFile = new File(cacheDir.getPath(), fileToCacheName);

Hinweis : Wenn Sie den Cache Ihrer App mit getExternalCacheDir() im freigegebenen Speicher platzieren, kann der Nutzer die Medien, die diesen Speicher enthalten, während Ihrer App auswerfen. Fügen Sie Logik hinzu, um den Cache-Miss, der durch dieses Nutzerverhalten verursacht wird, reibungslos zu verarbeiten.

Achtung : Für diese Dateien wird keine Sicherheit erzwungen. Daher kann jede App, die auf Android 10 (API-Level 29) oder niedriger ausgerichtet ist und die Berechtigung WRITE_EXTERNAL_STORAGE hat, auf den Inhalt dieses Caches zugreifen.

Weitere Informationen: Daten- und Dateispeicher – Übersicht

SharedPreferences im privaten Modus verwenden

Wenn Sie getSharedPreferences() verwenden, um SharedPreferences-Objekte Ihrer App zu erstellen oder darauf zuzugreifen, verwenden Sie MODE_PRIVATE. So kann nur Ihre App auf die Informationen in der freigegebenen Konfigurationsdatei zugreifen.

Wenn Sie Daten zwischen Apps teilen möchten, verwenden Sie keine SharedPreferences-Objekte. Folgen Sie stattdessen der Anleitung, um Daten sicher zwischen Apps zu teilen.

Die Security Library bietet auch die Klasse EncryptedSharedPreferences, die die SharedPreferences-Klasse umschließt und Schlüssel und Werte automatisch verschlüsselt.

Weitere Informationen:

Dienste und Abhängigkeiten auf dem neuesten Stand halten

Die meisten Apps verwenden externe Bibliotheken und Gerätesysteminformationen, um spezielle Aufgaben auszuführen. Wenn Sie die Abhängigkeiten Ihrer Anwendung auf dem neuesten Stand halten, werden diese Kommunikationspunkte sicherer.

Sicherheitsanbieter für Google Play-Dienste prüfen

Hinweis : Dieser Abschnitt gilt nur für Apps, die auf Geräte ausgerichtet sind, auf denen Google Play-Dienste installiert sind.

Wenn Ihre App Google Play-Dienste verwendet, müssen Sie sie auf dem Gerät aktualisieren, auf dem sie installiert ist. Führen Sie die Prüfung asynchron aus dem UI-Thread durch. Wenn das Gerät nicht auf dem neuesten Stand ist, wird ein Autorisierungsfehler ausgelöst.

Wenn Sie wissen möchten, ob die Google Play-Dienste auf dem Gerät, auf dem Ihre App installiert ist, auf dem neuesten Stand sind, folgen Sie der Anleitung unter Sicherheitsanbieter zum Schutz vor SSL-Exploits aktualisieren.

Weitere Informationen :

Alle App-Abhängigkeiten aktualisieren

Prüfen Sie vor der Bereitstellung Ihrer Anwendung, ob alle Bibliotheken, SDKs und anderen Abhängigkeiten auf dem neuesten Stand sind:

  • Verwenden Sie für eigene Abhängigkeiten wie das Android SDK die Aktualisierungstools in Android Studio, z. B. den SDK-Manager.
  • Prüfen Sie die Websites der Bibliotheken, die Ihre App verwendet, auf Abhängigkeiten von Drittanbietern und installieren Sie alle verfügbaren Updates und Sicherheits-Patches.

Weitere Informationen: Build-Abhängigkeiten hinzufügen

Weitere Informationen

Weitere Informationen dazu, wie Sie Ihre App sicherer machen, finden Sie in den folgenden Ressourcen: