Uygulamanızda ağ işlemleri gerçekleştirmek için manifest dosyanız aşağıdaki izinleri içermelidir:
<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ğ iletişimi işlevi eklemeden önce, ağ üzerinden veri aktarırken uygulamanızdaki verilerin ve bilgilerin güvende olduğundan emin olmanız gerekir. Bunu yapmak için ağ güvenliğiyle ilgili aşağıdaki en iyi uygulamaları izleyin:
- Ağ üzerinden ilettiğiniz hassas veya kişisel kullanıcı verisi miktarını en aza indirin.
- Uygulamanızdan gelen tüm ağ trafiğini SSL üzerinden gönderin.
- Uygulamanızın, özel sertifika yetkililerine (CA) güvenmesine veya güvenli iletişim için güvendiği sistem CA'ları grubunu kısıtlamasına olanak tanıyan bir ağ güvenliği yapılandırması oluşturmayı düşünün.
Güvenli ağ iletişimi ilkelerinin nasıl uygulanacağı hakkında daha fazla bilgi için ağ iletişimi güvenliği ipuçlarına bakın.
HTTP istemcisi seçin
Ağa bağlı uygulamaların çoğu, veri göndermek ve almak için HTTP kullanır. Android platformu; TLS, akış yükleme ve indirme, yapılandırılabilir zaman aşımları, IPv6 ve bağlantı havuzu oluşturmayı destekleyen HttpsURLConnection
istemcisini içerir.
Ağ iletişimi 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: Square'den JVM için tür güvenli bir HTTP istemci olan ve OkHttp'nin üzerine kurulmuştur. Retrofit, bir istemci arayüzünü bildirimli olarak oluşturmanızı sağlar ve çeşitli serileştirme kitaplığını destekler.
- Ktor: JetBrains'den, tamamen Kotlin için oluşturulmuş ve eş yordamlarla desteklenen bir HTTP istemcisi. Ktor, çeşitli motorları, serileştiricileri ve platformları destekler.
DNS sorgularını çözümleme
Android 10 (API düzeyi 29) ve sonraki sürümleri çalıştıran cihazlar, hem temizleme metin aramaları hem de DNS-over-TLS modu aracılığıyla özel DNS aramaları için yerleşik desteğe sahiptir.
DnsResolver
API; SRV
, NAPTR
ve diğer kayıt türlerini aramanıza olanak tanıyan genel, eşzamansız çözünürlük sunar. Yanıtın ayrıştırılması, gerçekleştirilecek uygulamaya bırakılır.
Android 9 (API düzeyi 28) ve önceki sürümleri çalıştıran cihazlarda platform DNS çözümleyici yalnızca A
ve AAAA
kayıtlarını destekler. Bu, bir adla ilişkili IP adreslerini aramanıza olanak tanır ancak başka kayıt türlerini desteklemez.
NDK tabanlı uygulamalar için bkz. android_res_nsend
.
Ağ işlemlerini bir depo ile kapsülleme
Ağ işlemleri gerçekleştirme sürecini basitleştirmek ve uygulamanızın çeşitli bölümlerinde kod yinelenmesini azaltmak için depo tasarım kalıbını kullanabilirsiniz. Depo, veri işlemlerini yürüten ve bazı belirli veriler veya kaynaklar üzerinde temiz bir API soyutlama sağlayan bir sınıftır.
Retrofit'i kullanarak 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ü aşağıdaki örnekte gösterildiği gibi belirtebilirsiniz:
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); }
Depo sınıfı içindeki işlevler, ağ işlemlerini kapsülleyip 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 biçiminde yapılacak gelecekteki değişiklikler de depo sınıfında izole edilir. Örneğin, API uç noktalarında güncelleme gibi uzaktan bir değişikliğiniz olabilir veya yerel önbelleğe almayı uygulamak isteyebilirsiniz.
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şturmaktan kaçınmak için ana iş parçacığında ağ işlemleri gerçekleştirmeyin. Varsayılan olarak Android, ana kullanıcı arayüzü iş parçacığı dışında bir iş parçacığı üzerinde ağ işlemleri gerçekleştirmenizi gerektirir. Ana iş parçacığında ağ işlemleri gerçekleştirmeye çalışırsanız bir NetworkOnMainThreadException
gönderilir.
Önceki kod örneğinde ağ işlemi aslında tetiklenmez. UserRepository
çağrısını yapan kişi, ileti dizisi oluşturmayı eş yordamlar veya enqueue()
işlevini kullanarak uygulamalıdır. Daha fazla bilgi için Get data from the Internet (İnternetten veri alma) adlı codelab'e göz atın. Bu kod, Kotlin eş yordamlarını kullanarak iş parçacıklarının nasıl uygulanacağını gösterir.
Yapılandırma değişikliklerinden kurtulma
Ekran döndürme gibi bir yapılandırma değişikliği gerçekleştiğinde, parçanız veya etkinliğiniz kaldırılır ve yeniden oluşturulur. Yalnızca küçük miktarda veri barındırabilen parça etkinliğiniz için örnek durumunda kaydedilmemiş tüm veriler kaybolur. Bu durumda, ağ isteklerinizi tekrar göndermeniz gerekebilir.
Verilerinizin, yapılandırma değişikliklerinden dayanması için bir ViewModel
kullanabilirsiniz. ViewModel
bileşeni, kullanıcı arayüzüyle ilgili verileri yaşam döngüsüne duyarlı bir şekilde depolayıp yönetmek için tasarlanmıştır. ViewModel
, önceki UserRepository
kullanarak gerekli ağ isteklerini yapabilir ve sonucu LiveData
kullanarak 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 göz atı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 rehberi