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

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

<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) और इसके बाद के वर्शन वाले डिवाइसों में, खास डीएनएस लुकअप की सुविधा पहले से मौजूद होती है. यह सुविधा, क्लियरटेक्स्ट लुकअप और डीएनएस-ओवर-टीएलएस मोड, दोनों के ज़रिए काम करती है. DnsResolver एपीआई, सामान्य और एसिंक्रोनस रिज़ॉल्यूशन उपलब्ध कराता है. इससे SRV, NAPTR, और अन्य रिकॉर्ड टाइप देखे जा सकते हैं. जवाब को पार्स करने का काम ऐप्लिकेशन को करना होता है.

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

एनडीके पर आधारित ऐप्लिकेशन के लिए, 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
            }
        });
    }
}

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