Damit in Ihrer Anwendung Netzwerkvorgänge ausgeführt werden können, muss das Manifest Folgendes enthalten: die folgenden Berechtigungen:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Best Practices für eine sichere Netzwerkkommunikation
Bevor Sie Ihrer App Netzwerkfunktionen hinzufügen, müssen Sie sicherstellen, Daten und Informationen in Ihrer App auch dann sicher sind, wenn Sie Daten Netzwerk. Befolgen Sie dazu die folgenden Best Practices für die Netzwerksicherheit:
- Minimieren Sie die Menge an sensiblen oder personenbezogenen Nutzerdaten, die Sie über das Netzwerk übertragen.
- Gesamten Netzwerkverkehr von Ihrer App senden über SSL.
- Erwägen Sie die Erstellung einer Netzwerksicherheit Konfiguration, mit der Ihre App benutzerdefinierten Zertifizierungsstellen (CAs) vertrauen oder die Gruppe von System-CAs einschränken für eine sichere Kommunikation.
Weitere Informationen zur Anwendung von Prinzipien für sichere Netzwerke finden Sie in den Tipps zur Netzwerksicherheit.
HTTP-Client auswählen
Die meisten netzwerkverbundenen Apps verwenden HTTP zum Senden und Empfangen von Daten. Das Android-
umfasst die
HttpsURLConnection
-Client,
unterstützt TLS, Streaming-Uploads und -Downloads, konfigurierbare Zeitüberschreitungen,
IPv6 und Verbindungs-Pooling.
Es sind auch Bibliotheken von Drittanbietern verfügbar, die APIs auf höherer Ebene für Netzwerkfunktionen bieten. Diese unterstützen verschiedene praktische Funktionen, z. B. die Serialisierung von Anfragetexten und Deserialisierung von Antworttexten
- Retrofit: ein typsicheres HTTP für die JVM von Square, die auf OkHttp basiert. Mit Retrofit können Sie erstellt eine Client-Schnittstelle deklarativ und bietet Unterstützung für Serialisierungsbibliotheken.
- Ktor: ein HTTP-Client von JetBrains, erstellt für Kotlin und unterstützt Koroutinen. Ktor unterstützt verschiedene Motoren, Serialisatoren und Plattformen.
DNS-Abfragen auflösen
Geräte mit Android 10 (API-Level 29) und höher unterstützen
für spezielle DNS-Lookups sowohl im Klartextmodus als auch im DNS-over-TLS-Modus.
Die DnsResolver
API bietet generische,
asynchrone Auflösung, bei der Sie SRV
, NAPTR
und andere
Eintragstypen. Das Parsen der Antwort bleibt der Anwendung überlassen.
Auf Geräten mit Android 9 (API-Level 28) und niedriger unterstützt der DNS-Resolver der Plattform nur A
- und AAAA
-Einträge. So können Sie die IP-Adresse ermitteln,
Adressen, die einem Namen zugeordnet sind, unterstützt jedoch keine anderen Eintragstypen.
Informationen zu NDK-basierten Anwendungen finden Sie unter
android_res_nsend
Netzwerkvorgänge mit einem Repository kapseln
Mit dem Repository-Designmuster können Sie Netzwerkvorgänge vereinfachen und die Codeduplizierung in verschiedenen Teilen Ihrer App reduzieren. Ein Repository ist eine Klasse, die Datenvorgänge abwickelt und eine eine saubere API-Abstraktion über bestimmte Daten oder Ressourcen.
Sie können mit Retrofit eine Schnittstelle deklarieren, in der die HTTP-Methode, URL, Argumente und Antworttyp für Netzwerkvorgänge wie im folgenden Beispiel: Beispiel:
Kotlin
interface UserService { @GET("/users/{id}") suspend fun getUser(@Path("id") id: String): User }
Java
public interface UserService { @GET("/user/{id}") Call<User> getUserById(@Path("id") String id); }
Innerhalb einer Repository-Klasse können Funktionen Netzwerkvorgänge kapseln und ihre Ergebnisse offenzulegen. Durch diese Kapselung müssen die Komponenten, die das Repository aufrufen, nicht wissen, wie die Daten gespeichert werden. Alle zukünftigen Änderungen an wie die Daten gespeichert werden, unabhängig von der Repository-Klasse. Für z. B. eine Remote-Änderung wie eine Aktualisierung der API-Endpunkte oder können Sie lokales Caching implementieren.
Kotlin
class UserRepository constructor( private val userService: UserService ) { suspend fun getUserById(id: String): User { return userService.getUser(id) } }
Java
class UserRepository { private UserService userService; public UserRepository( UserService userService ) { this.userService = userService; } public Call<User> getUserById(String id) { return userService.getUser(id); } }
Um zu vermeiden, dass die Benutzeroberfläche reagiert, aber keine Netzwerkvorgänge auf dem
im Hauptthread. Standardmäßig müssen Sie Netzwerkvorgänge unter Android in einem anderen Thread als dem Haupt-UI-Thread ausführen. Bei Netzwerkvorgängen
im Hauptthread
NetworkOnMainThreadException
geworfen wird.
Im vorherigen Codebeispiel wird der Netzwerkvorgang nicht ausgelöst. Der Aufrufer von UserRepository
muss das Threading entweder mithilfe von Koroutinen oder mithilfe der enqueue()
implementieren.
. Weitere Informationen finden Sie im Codelab Daten aus dem
Internet,
zeigt, wie Threading mit Kotlin-Koroutinen implementiert wird.
Konfigurationsänderungen beibehalten
Bei einer Konfigurationsänderung, z. B. einer Bildschirmdrehung, Ihres Fragments oder Aktivitäten gelöscht und neu erstellt werden. Alle Daten, die nicht in der Instanz gespeichert sind für die Fragmentaktivität, die nur kleine Datenmengen enthalten kann, geht verloren. In diesem Fall müssen Sie Ihre Netzwerkanfragen möglicherweise noch einmal senden.
Mit einem ViewModel
können Sie
Ihre Daten auch nach
Konfigurationsänderungen bleiben. Die ViewModel
-Komponente wurde entwickelt, um UI-bezogene Daten auf nutzungsorientierte Weise zu speichern und zu verwalten. Mithilfe der vorangehenden UserRepository
kann der ViewModel
notwendige Netzwerkanfragen und liefern das Ergebnis zu Ihrem Fragment oder Ihrer Aktivität
mit LiveData
:
Kotlin
class MainViewModel constructor( savedStateHandle: SavedStateHandle, userRepository: UserRepository ) : ViewModel() { private val userId: String = savedStateHandle["uid"] ?: throw IllegalArgumentException("Missing user ID") private val _user = MutableLiveData<User>() val user = _user as LiveData<User> init { viewModelScope.launch { try { // Calling the repository is safe as it moves execution off // the main thread val user = userRepository.getUserById(userId) _user.value = user } catch (error: Exception) { // Show error message to user } } } }
Java
class MainViewModel extends ViewModel { private final MutableLiveData<User> _user = new MutableLiveData<>(); LiveData<User> user = (LiveData<User>) _user; public MainViewModel( SavedStateHandle savedStateHandle, UserRepository userRepository ) { String userId = savedStateHandle.get("uid"); Call<User> userCall = userRepository.getUserById(userId); userCall.enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if (response.isSuccessful()) { _user.setValue(response.body()); } } @Override public void onFailure(Call<User> call, Throwable t) { // Show error message to user } }); } }
Ähnliche Leitfäden lesen
Weitere Informationen zu diesem Thema finden Sie in den folgenden verwandten Leitfäden:
- Schnelle Akkuentladung im Netzwerk reduzieren: Übersicht
- Auswirkungen regelmäßiger Updates minimieren
- Webbasierte Inhalte
- Anwendungsgrundlagen
- Leitfaden zur Anwendungsarchitektur