Untuk menjalankan operasi jaringan di aplikasi Anda, manifes Anda harus menyertakan izin berikut:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Praktik terbaik untuk komunikasi jaringan yang aman
Sebelum menambahkan fungsi jaringan ke aplikasi, Anda perlu memastikan bahwa data dan informasi dalam aplikasi tetap aman saat Anda melakukan transmisi melalui jaringan. Untuk melakukannya, ikuti praktik terbaik keamanan jaringan ini:
- Minimalkan jumlah data pengguna yang bersifat sensitif atau pribadi yang Anda kirimkan melalui jaringan.
- Kirim semua traffic jaringan dari aplikasi Anda melalui SSL.
- Pertimbangkan untuk membuat konfigurasi keamanan jaringan, yang memungkinkan aplikasi Anda memercayai otoritas sertifikat khusus (CA) atau membatasi kumpulan CA sistem yang dipercaya untuk komunikasi aman.
Untuk mengetahui informasi selengkapnya tentang cara menerapkan prinsip jaringan aman, lihat tips keamanan jaringan.
Memilih klien HTTP
Sebagian besar aplikasi yang terhubung ke jaringan menggunakan HTTP untuk mengirim dan menerima data. Platform
Android mencakup
klien HttpsURLConnection
,
yang mendukung TLS, upload dan download streaming, waktu tunggu yang dapat dikonfigurasi,
IPv6, serta penggabungan koneksi.
Library pihak ketiga yang menawarkan API tingkat lebih tinggi untuk operasi jaringan juga tersedia. Fungsi ini mendukung berbagai fitur praktis, seperti serialisasi isi permintaan dan deserialisasi isi respons.
- Retrofit: klien HTTP yang aman jenisnya untuk JVM dari Square, dan dibuat di atas OkHttp. Retrofit memungkinkan Anda membuat antarmuka klien secara deklaratif dan memiliki dukungan untuk beberapa library serialisasi.
- Ktor: klien HTTP dari JetBrains yang dibuat sepenuhnya untuk Kotlin dan didukung oleh coroutine. Ktor mendukung berbagai komputer, serializer, dan platform.
Menyelesaikan kueri DNS
Perangkat yang menjalankan Android 10 (API level 29) dan yang lebih tinggi memiliki dukungan bawaan untuk
pencarian DNS khusus melalui pencarian cleartext dan mode DNS-over-TLS.
API DnsResolver
menyediakan resolusi
asinkron dan generik, yang memungkinkan Anda mencari SRV
, NAPTR
, dan jenis data
lainnya. Penguraian respons akan diserahkan ke aplikasi.
Pada perangkat yang menjalankan Android 9 (API level 28) dan yang lebih rendah, DNS
resolver platform hanya mendukung data A
dan AAAA
. Hal ini memungkinkan Anda mencari alamat IP
yang berkaitan dengan nama, namun tidak mendukung jenis data lain.
Untuk aplikasi berbasis NDK, lihat android_res_nsend
.
Mengenkapsulasi operasi jaringan dengan repositori
Untuk memudahkan proses penerapan operasi jaringan dan mengurangi duplikasi kode di berbagai bagian aplikasi, Anda dapat menggunakan pola desain repositori. Repositori adalah class yang menangani operasi data dan menyediakan abstraksi API yang bersih atas beberapa data atau resource tertentu.
Anda dapat menggunakan Retrofit untuk mendeklarasikan antarmuka yang menentukan metode HTTP, URL, argumen, dan jenis respons untuk operasi jaringan, seperti contoh berikut:
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); }
Dalam class repositori, fungsi dapat mengenkapsulasi operasi jaringan dan menampilkan hasilnya. Enkapsulasi ini memastikan bahwa komponen yang memanggil repositori tidak perlu mengetahui cara data disimpan. Setiap perubahan mendatang pada cara data disimpan juga dipisahkan ke class repositori. Misalnya, Anda mungkin memiliki perubahan jarak jauh seperti update pada endpoint API, atau Anda mungkin ingin mengimplementasikan cache lokal.
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); } }
Untuk menghindari pembuatan UI yang tidak responsif, jangan menjalankan operasi jaringan pada
thread utama. Secara default, Android mengharuskan Anda melakukan operasi jaringan pada
thread selain UI thread utama. Jika Anda mencoba menjalankan operasi jaringan
di thread utama,
NetworkOnMainThreadException
akan ditampilkan.
Dalam contoh kode sebelumnya,
operasi jaringan tidak benar-benar dipicu. Pemanggil UserRepository
harus mengimplementasikan thread menggunakan coroutine atau fungsi
enqueue()
. Untuk mengetahui informasi selengkapnya, lihat codelab Mendapatkan data dari
internet,
yang menunjukkan cara menerapkan thread menggunakan coroutine Kotlin.
Mempertahankan perubahan konfigurasi
Saat terjadi perubahan konfigurasi, seperti rotasi layar, fragmen atau aktivitas Anda akan dihancurkan dan dibuat ulang. Setiap data yang tidak disimpan dalam status instance untuk aktivitas fragmen Anda, yang hanya dapat menyimpan sedikit data, akan hilang. Jika hal ini terjadi, Anda mungkin perlu mengajukan permintaan jaringan lagi.
Anda dapat menggunakan ViewModel
agar
data Anda dapat bertahan saat terjadi perubahan konfigurasi. Komponen ViewModel
didesain untuk menyimpan dan mengelola data terkait UI dengan cara yang berbasis
siklus proses. Menggunakan UserRepository
sebelumnya, ViewModel
dapat membuat
permintaan jaringan yang penting dan memberikan hasil untuk fragmen atau aktivitas Anda
menggunakan 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 } }); } }
Membaca panduan terkait
Untuk mempelajari topik ini lebih lanjut, lihat panduan terkait berikut:
- Mengurangi konsumsi baterai jaringan: Ringkasan
- Meminimalkan efek update reguler
- Konten berbasis web
- Dasar-dasar aplikasi
- Panduan untuk arsitektur aplikasi