Ağa bağlanma

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
            }
        });
    }
}

Bu konuyla ilgili daha fazla bilgi edinmek için aşağıdaki ilgili kılavuzlara göz atın: