Uygulamanızda ağ işlemleri gerçekleştirmek için manifestinizde aşağıdaki izinler bulunmalıdır:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Güvenli ağ iletişimi için en iyi uygulamalar
Uygulamanıza ağ işlevi eklemeden önce, ağ üzerinden iletirken uygulamanızdaki veri ve bilgilerin güvende kalmasını sağlamanız gerekir. Bunun için aşağıdaki ağ güvenliğiyle ilgili en iyi uygulamaları takip edin:
- Ağ üzerinden ilettiğiniz hassas veya kişisel kullanıcı verilerinin miktarını en aza indirin.
- Uygulamanızdaki tüm ağ trafiğini SSL üzerinden gönderin.
- Uygulamanızın özel sertifika yetkililerine (CA'lar) güvenmesine veya güvenli iletişim için güvendiği sistem CA'larının kümesini kısıtlamasına olanak tanıyan bir ağ güvenliği yapılandırması oluşturmayı düşünebilirsiniz.
Güvenli ağ iletişimi ilkelerini uygulama hakkında daha fazla bilgi için Ağ güvenliği ipuçları başlıklı makaleyi inceleyin.
Bir HTTP istemcisi seçin
Ağa bağlı uygulamaların çoğu, veri göndermek ve almak için HTTP'yi kullanır. Android platformu, TLS, akış yüklemeleri ve indirmeleri, yapılandırılabilir zaman aşımları, IPv6 ve bağlantı havuzunu destekleyen HttpsURLConnection
istemcisini içerir.
Ağ işlemleri için daha üst düzey API'ler sunan üçüncü taraf kitaplıklar da mevcuttur. Bunlar, istek gövdelerinin serileştirilmesi ve yanıt gövdelerinin seri durumdan çıkarılması gibi çeşitli kolaylık özelliklerini destekler.
- Retrofit: OkHttp'nin üzerine inşa edilmiş, Square'in JVM için tür güvenli bir HTTP istemcisi. Retrofit, istemci arayüzünü bildirimsel olarak oluşturmanıza olanak tanır ve çeşitli serileştirme kitaplıklarını destekler.
- Ktor: JetBrains'in tamamen Kotlin için oluşturduğu ve eş yordamlar tarafından desteklenen bir HTTP istemcisi. Ktor çeşitli motorları, serileştiricileri ve platformları destekler.
DNS sorgularını çözme
Android 10 (API düzeyi 29) ve sonraki sürümlerin yüklü olduğu cihazlarda hem düz metin aramaları hem de DNS-over-TLS modu aracılığıyla özel DNS aramaları için yerleşik destek bulunur.
DnsResolver
API, SRV
, NAPTR
ve diğer kayıt türlerini aramanıza olanak tanıyan genel, eşzamansız çözümleme sağlar. Yanıtı ayrıştırma işlemi uygulamaya bırakılır.
Android 9 (API düzeyi 28) ve önceki sürümlerini çalıştıran cihazlarda platform DNS çözümleyici yalnızca A
ve AAAA
kayıtlarını destekler. Bu araç, bir adla ilişkili IP adreslerini aramanıza olanak tanır ancak diğer kayıt türlerini desteklemez.
NDK tabanlı uygulamalar için android_res_nsend
başlıklı makaleyi inceleyin.
Ağ işlemlerini bir depo ile kapsama
Ağ işlemlerini gerçekleştirme sürecini basitleştirmek ve uygulamanızın çeşitli bölümlerinde kod tekrarını azaltmak için depo tasarım kalıbını kullanabilirsiniz. Depo, veri işlemlerini işleyen ve belirli veriler veya kaynaklar üzerinde temiz bir API soyutlaması sağlayan bir sınıftır.
Aşağıdaki örnekte olduğu gibi, ağ işlemleri için HTTP yöntemini, URL'yi, bağımsız değişkenleri ve yanıt türünü belirten bir arayüz bildirmek üzere Retrofit'i kullanabilirsiniz:
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); }
Bir depo sınıfında işlevler, ağ işlemlerini kapsayabilir ve sonuçlarını gösterebilir. Bu kapsülleme, depoyu çağıran bileşenlerin verilerin nasıl depolandığını bilmesine gerek kalmamasını sağlar. Verilerin depolanma şekliyle ilgili gelecekte yapılacak değişiklikler de yalnızca depo sınıfıyla sınırlı kalır. Örneğin, API uç noktalarında güncelleme gibi uzaktan bir değişiklik yapmanız veya yerel önbelleğe alma uygulamak istemeniz gerekebilir.
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); } }
Yanıt vermeyen bir kullanıcı arayüzü oluşturmamak için ana iş parçacığında ağ işlemleri gerçekleştirmeyin. Android, varsayılan olarak ağ işlemlerini ana kullanıcı arayüzü iş parçacığı dışındaki bir iş parçacığında gerçekleştirmenizi gerektirir. Ana iş parçacığında ağ işlemleri gerçekleştirmeye çalışırsanız NetworkOnMainThreadException
oluşturulur.
Önceki kod örneğinde, ağ işlemi aslında tetiklenmez. UserRepository
işlevini çağıran, iş parçacığını eş yordamlar veya enqueue()
işlevini kullanarak uygulamalıdır. Kotlin coroutine'leri kullanarak iş parçacığı oluşturmanın nasıl uygulanacağını gösteren İnternetten veri alma adlı codelab'de daha fazla bilgi bulabilirsiniz.
Yapılandırma değişikliklerinden etkilenmeme
Ekran döndürme gibi bir yapılandırma değişikliği olduğunda parçanız veya etkinliğiniz yok edilip yeniden oluşturulur. Yalnızca az miktarda veri tutabilen parça etkinliğinizin örnek durumunda kaydedilmeyen tüm veriler kaybolur. Bu durumda, ağ isteklerinizi tekrar yapmanız gerekebilir.
Verilerinizin yapılandırma değişikliklerinden etkilenmemesi için ViewModel
kullanabilirsiniz. ViewModel
bileşeni, kullanıcı arayüzüyle ilgili verileri yaşam döngüsüne duyarlı bir şekilde depolamak ve yönetmek için tasarlanmıştır. Yukarıdaki UserRepository
kullanılarak ViewModel
, gerekli ağ isteklerini yapabilir ve LiveData
kullanarak sonucu parçanıza veya etkinliğinize sağlayabilir:
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 } }); } }
İlgili kılavuzları okuyun
Bu konuyla ilgili daha fazla bilgi edinmek için aşağıdaki ilgili kılavuzlara bakın:
- Ağ pil tüketimini azaltma: Genel bakış
- Düzenli güncellemelerin etkisini en aza indirme
- Web tabanlı içerik
- Uygulamayla ilgili temel bilgiler
- Uygulama mimarisi kılavuzu