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

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

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

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