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

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

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

नेटवर्क पर सुरक्षित तरीके से कम्यूनिकेट करने के लिए आज़माए गए कुछ बेहतरीन तरीके

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

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

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

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

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

  • Retrofit: यह Square का, JVM के लिए टाइप-सेफ़ एचटीटीपी क्लाइंट है. इसे 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
            }
        });
    }
}

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