नेटवर्क से कनेक्ट करें

अपने ऐप्लिकेशन में नेटवर्क से जुड़े काम करने के लिए, आपके मेनिफ़ेस्ट में ये अनुमतियां शामिल होनी चाहिए:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

सुरक्षित नेटवर्क कम्यूनिकेशन के लिए सबसे सही तरीके

अपने ऐप्लिकेशन में नेटवर्किंग की सुविधा जोड़ने से पहले, आपको यह पक्का करना होगा कि नेटवर्क पर डेटा और जानकारी भेजने के दौरान, वे सुरक्षित रहें. ऐसा करने के लिए, नेटवर्किंग की सुरक्षा के सबसे सही तरीके अपनाएं:

  • नेटवर्क पर भेजे जाने वाले उपयोगकर्ता के संवेदनशील या निजी डेटा की मात्रा कम करें.
  • अपने ऐप्लिकेशन से एसएसएल पर सारा नेटवर्क ट्रैफ़िक भेजें.
  • नेटवर्क सुरक्षा कॉन्फ़िगरेशन बनाएं. इससे आपके ऐप्लिकेशन को पसंद के मुताबिक सर्टिफ़िकेट अथॉरिटी (सीए) पर भरोसा करने में मदद मिलेगी. इसके अलावा, सुरक्षित तरीके से बातचीत करने के लिए, उन सिस्टम सीए के सेट पर पाबंदी लगाई जा सकती है जिन पर आपका ऐप्लिकेशन भरोसा करता है.

नेटवर्किंग के सुरक्षित सिद्धांतों को लागू करने के तरीके के बारे में ज़्यादा जानने के लिए, नेटवर्किंग की सुरक्षा से जुड़ी सलाह देखें.

कोई एचटीटीपी क्लाइंट चुनना

नेटवर्क से कनेक्ट किए गए ज़्यादातर ऐप्लिकेशन, डेटा भेजने और पाने के लिए एचटीटीपी का इस्तेमाल करते हैं. Android प्लैटफ़ॉर्म में HttpsURLConnection क्लाइंट शामिल होता है. यह TLS, स्ट्रीमिंग अपलोड और डाउनलोड, कॉन्फ़िगर किए जा सकने वाले टाइम आउट, IPv6, और कनेक्शन पूल करने की सुविधा के साथ काम करता है.

नेटवर्किंग ऑपरेशन के लिए, तीसरे पक्ष की लाइब्रेरी भी उपलब्ध हैं. इनमें बेहतर लेवल के एपीआई होते हैं. ये कई सुविधाओं के साथ काम करते हैं. जैसे, अनुरोध के बॉडी को सीरियलाइज़ करना और जवाब के बॉडी को डीसीरियलाइज़ करना.

  • Retrofit: Square का, जेवीएम के लिए एक सुरक्षित एचटीटीपी क्लाइंट. इसे OkHttp के आधार पर बनाया गया है. Retrofit की मदद से, क्लाइंट इंटरफ़ेस को एलान के तौर पर बनाया जा सकता है. साथ ही, इसमें कई 'सीरियलाइज़ेशन लाइब्रेरी' काम करती हैं.
  • Ktor: यह JetBrains का एचटीटीपी क्लाइंट है. इसे पूरी तरह से Kotlin के लिए बनाया गया है और यह कोरूटीन की मदद से काम करता है. Ktor, कई इंजन, सिरियलाइज़र, और प्लैटफ़ॉर्म के साथ काम करता है.

डीएनएस क्वेरी हल करना

Android 10 (एपीआई लेवल 29) और इसके बाद के वर्शन वाले डिवाइसों में, क्लियरटेक्स्ट लुकअप और DNS-over-TLS मोड, दोनों के ज़रिए खास डीएनएस लुकअप के लिए, पहले से ही सहायता उपलब्ध होती है. DnsResolver एपीआई, सामान्य और एक साथ काम न करने वाला रिज़ॉल्यूशन उपलब्ध कराता है. इसकी मदद से, SRV, NAPTR, और अन्य तरह के रिकॉर्ड देखे जा सकते हैं. जवाब को पार्स करने की ज़िम्मेदारी ऐप्लिकेशन की होती है.

Android 9 (एपीआई लेवल 28) और उससे पहले के वर्शन वाले डिवाइसों पर, प्लैटफ़ॉर्म का डीएनएस रिज़ॉल्वर सिर्फ़ A और AAAA रिकॉर्ड के साथ काम करता है. इससे, किसी नाम से जुड़े आईपी पते देखे जा सकते हैं. हालांकि, यह किसी दूसरे तरह के रिकॉर्ड के साथ काम नहीं करता.

NDK पर आधारित ऐप्लिकेशन के लिए, android_res_nsend देखें.

रिपॉज़िटरी की मदद से नेटवर्क ऑपरेशन को कवर करना

नेटवर्क ऑपरेशन करने की प्रोसेस को आसान बनाने और अपने ऐप्लिकेशन के अलग-अलग हिस्सों में कोड के डुप्लीकेट होने की संख्या को कम करने के लिए, आपके पास रिपॉज़िटरी डिज़ाइन पैटर्न का इस्तेमाल करने का विकल्प है. रिपॉज़िटरी एक क्लास है, जो डेटा ऑपरेशन को हैंडल करती है. साथ ही, किसी खास डेटा या संसाधन के लिए एपीआई का एक बेहतर वर्शन उपलब्ध कराती है.

Retrofit का इस्तेमाल करके, नेटवर्क ऑपरेशंस के लिए एचटीटीपी तरीका, यूआरएल, आर्ग्युमेंट, और रिस्पॉन्स टाइप बताने वाले इंटरफ़ेस का एलान किया जा सकता है. इसका उदाहरण यहां दिया गया है:

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

किसी रिपॉज़िटरी क्लास में, फ़ंक्शन नेटवर्क ऑपरेशन को इकट्ठा कर सकते हैं और उनके नतीजे दिखा सकते हैं. इस एन्कैप्सुलेशंस से यह पक्का होता है कि डेटा को कैसे सेव किया जाता है, यह जानकारी उन कॉम्पोनेंट को नहीं चाहिए जो डेटा को सेव करने के लिए रिपॉज़िटरी को कॉल करते हैं. आने वाले समय में, डेटा को सेव करने के तरीके में किए जाने वाले बदलाव भी, रिपॉज़िटरी क्लास में ही लागू होंगे. उदाहरण के लिए, हो सकता है कि आपको एपीआई एंडपॉइंट में अपडेट करने जैसा कोई रिमोट बदलाव करना हो या हो सकता है कि आपको लोकल कैश मेमोरी लागू करनी हो.

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

यूज़र इंटरफ़ेस (यूआई) के काम न करने से बचने के लिए, मुख्य थ्रेड पर नेटवर्क ऑपरेशन न करें. डिफ़ॉल्ट रूप से, Android के लिए ज़रूरी है कि आप मुख्य यूज़र इंटरफ़ेस (यूआई) थ्रेड के अलावा किसी दूसरी थ्रेड पर नेटवर्क ऑपरेशन करें. अगर मुख्य थ्रेड पर नेटवर्क ऑपरेशन करने की कोशिश की जाती है, तो NetworkOnMainThreadException को दिखाया जाता है.

पिछले कोड के उदाहरण में, नेटवर्क ऑपरेशन असल में ट्रिगर नहीं होता. UserRepository को कॉल करने वाले को, कोरूटीन या enqueue() फ़ंक्शन का इस्तेमाल करके थ्रेडिंग लागू करनी होगी. ज़्यादा जानकारी के लिए, इंटरनेट से डेटा पाना कोडलैब देखें. इसमें, Kotlin कोरुटिन का इस्तेमाल करके थ्रेडिंग को लागू करने का तरीका बताया गया है.

कॉन्फ़िगरेशन में बदलाव होने पर भी काम करना

जब कॉन्फ़िगरेशन में कोई बदलाव होता है, जैसे कि स्क्रीन घुमाना, तो आपके फ़्रैगमेंट या ऐक्टिविटी को मिटा दिया जाता है और फिर से बनाया जाता है. आपकी फ़्रैगमेंट गतिविधि के लिए, इंस्टेंस स्टेट में सेव न किया गया डेटा, खो जाता है. यह स्टेटस, सिर्फ़ थोड़े डेटा को सेव कर सकता है. ऐसा होने पर, आपको नेटवर्क के अनुरोध फिर से करने पड़ सकते हैं.

कॉन्फ़िगरेशन में बदलाव होने पर भी डेटा को सुरक्षित रखने के लिए, ViewModel का इस्तेमाल किया जा सकता है. ViewModel कॉम्पोनेंट को, लाइफ़साइकल के हिसाब से यूज़र इंटरफ़ेस (यूआई) से जुड़े डेटा को स्टोर और मैनेज करने के लिए डिज़ाइन किया गया है. UserRepository का इस्तेमाल करके, ViewModel ज़रूरी नेटवर्क अनुरोध कर सकता है और 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
            }
        });
    }
}

इस विषय के बारे में ज़्यादा जानने के लिए, इन गाइड देखें: