अपने ऐप्लिकेशन की सुरक्षा को बेहतर बनाएं

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

इस पेज पर, ऐप्लिकेशन की सुरक्षा को बेहतर बनाने के कई सबसे सही तरीके बताए गए हैं.

सुरक्षित तरीके से बातचीत करना

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

ऐप्लिकेशन के बीच सुरक्षित तरीके से डेटा शेयर करना

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

ऐप्लिकेशन चुनने वाला टूल दिखाना

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

Kotlin

val intent = Intent(Intent.ACTION_SEND)
val possibleActivitiesList: List<ResolveInfo> =
        packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL)

// Verify that an activity in at least two apps on the user's device
// can handle the intent. Otherwise, start the intent only if an app
// on the user's device can handle the intent.
if (possibleActivitiesList.size > 1) {

    // Create intent to show chooser.
    // Title is something similar to "Share this photo with."

    val chooser = resources.getString(R.string.chooser_title).let { title ->
        Intent.createChooser(intent, title)
    }
    startActivity(chooser)
} else if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
}

Java

Intent intent = new Intent(Intent.ACTION_SEND);
List<ResolveInfo> possibleActivitiesList = getPackageManager()
        .queryIntentActivities(intent, PackageManager.MATCH_ALL);

// Verify that an activity in at least two apps on the user's device
// can handle the intent. Otherwise, start the intent only if an app
// on the user's device can handle the intent.
if (possibleActivitiesList.size() > 1) {

    // Create intent to show chooser.
    // Title is something similar to "Share this photo with."

    String title = getResources().getString(R.string.chooser_title);
    Intent chooser = Intent.createChooser(intent, title);
    startActivity(chooser);
} else if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
}

इससे जुड़ी जानकारी:

हस्ताक्षर के आधार पर अनुमतियां लागू करना

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <permission android:name="my_custom_permission_name"
                android:protectionLevel="signature" />

इससे जुड़ी जानकारी:

अपने ऐप्लिकेशन के कॉन्टेंट की सेवा देने वाली कंपनियों को ऐक्सेस देने की अनुमति न देना

अगर आपको अपने ऐप्लिकेशन से किसी ऐसे ऐप्लिकेशन पर डेटा नहीं भेजना है जिसका मालिकाना हक आपके पास नहीं है, तो अन्य डेवलपर के ऐप्लिकेशन को अपने ऐप्लिकेशन के ContentProvider ऑब्जेक्ट ऐक्सेस करने से साफ़ तौर पर मना कर दें. यह सेटिंग तब ज़्यादा अहम होती है, जब आपका ऐप्लिकेशन Android 4.1.1 (एपीआई लेवल 16) या उससे पहले के वर्शन पर चलने वाले डिवाइसों पर इंस्टॉल किया जा सकता हो. इसकी वजह यह है कि Android के उन वर्शन पर, <provider> एलिमेंट का android:exported एट्रिब्यूट डिफ़ॉल्ट रूप से true होता है.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <application ... >
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.myapp.fileprovider"
            ...
            android:exported="false">
            <!-- Place child elements of <provider> here. -->
        </provider>
        ...
    </application>
</manifest>

संवेदनशील जानकारी दिखाने से पहले, क्रेडेंशियल मांगना

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

बायोमेट्रिक क्रेडेंशियल का अनुरोध करने के तरीके के बारे में ज़्यादा जानने के लिए, बायोमेट्रिक पुष्टि करने के बारे में गाइड देखें.

नेटवर्क की सुरक्षा के उपाय लागू करना

नीचे दिए गए सेक्शन में बताया गया है कि अपने ऐप्लिकेशन के नेटवर्क की सुरक्षा को कैसे बेहतर बनाया जा सकता है.

टीएलएस ट्रैफ़िक का इस्तेमाल करना

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

Kotlin

val url = URL("https://www.google.com")
val urlConnection = url.openConnection() as HttpsURLConnection
urlConnection.connect()
urlConnection.inputStream.use {
    ...
}

Java

URL url = new URL("https://www.google.com");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.connect();
InputStream in = urlConnection.getInputStream();

नेटवर्क की सुरक्षा से जुड़ा कॉन्फ़िगरेशन जोड़ना

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

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

  1. अपने ऐप्लिकेशन के मेनिफ़ेस्ट में कॉन्फ़िगरेशन का एलान करें:
  2. <manifest ... >
        <application
            android:networkSecurityConfig="@xml/network_security_config"
            ... >
            <!-- Place child elements of <application> element here. -->
        </application>
    </manifest>
  3. res/xml/network_security_config.xml में मौजूद एक्सएमएल रिसॉर्स फ़ाइल जोड़ें.

    साफ़-साफ़ दिखने वाले टेक्स्ट को बंद करके, यह तय करें कि किसी खास डोमेन पर आने वाले सभी ट्रैफ़िक को एचटीटीपीएस का इस्तेमाल करना चाहिए:

    <network-security-config>
        <domain-config cleartextTrafficPermitted="false">
            <domain includeSubdomains="true">secure.example.com</domain>
            ...
        </domain-config>
    </network-security-config>

    डेवलपमेंट की प्रोसेस के दौरान, उपयोगकर्ता के इंस्टॉल किए गए सर्टिफ़िकेट को अनुमति देने के लिए, <debug-overrides> एलिमेंट का इस्तेमाल किया जा सकता है. यह एलिमेंट, डिबग करने और जांच करने के दौरान, आपके ऐप्लिकेशन के रिलीज़ कॉन्फ़िगरेशन पर असर डाले बिना, ऐप्लिकेशन के सुरक्षा से जुड़े अहम विकल्पों को बदल देता है. यहां दिए गए स्निपेट में, अपने ऐप्लिकेशन की नेटवर्क सुरक्षा कॉन्फ़िगरेशन एक्सएमएल फ़ाइल में इस एलिमेंट को तय करने का तरीका बताया गया है:

    <network-security-config>
        <debug-overrides>
            <trust-anchors>
                <certificates src="user" />
            </trust-anchors>
        </debug-overrides>
    </network-security-config>

मिलती-जुलती जानकारी: नेटवर्क की सुरक्षा से जुड़ा कॉन्फ़िगरेशन

अपना ट्रस्ट मैनेजर बनाना

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

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

इन चरणों को पूरा करने के तरीके के बारे में ज़्यादा जानने के लिए, किसी ऐसी सर्टिफ़िकेट देने वाली संस्था से जुड़ी समस्या को हल करने के बारे में चर्चा देखें जिसकी जानकारी आपको नहीं है.

इससे जुड़ी जानकारी:

वेबव्यू ऑब्जेक्ट का इस्तेमाल सावधानी से करना

WebView आपके ऐप्लिकेशन में मौजूद ऑब्जेक्ट, लोगों को ऐसी साइटों पर ले जाने की अनुमति नहीं देते जिन पर आपका कंट्रोल नहीं है. जब भी हो सके, अपने ऐप्लिकेशन के WebView ऑब्जेक्ट से लोड किए गए कॉन्टेंट पर पाबंदी लगाने के लिए, अनुमति वाली सूची का इस्तेमाल करें.

इसके अलावा, जब तक आपके पास अपने ऐप्लिकेशन के WebView ऑब्जेक्ट में मौजूद कॉन्टेंट को पूरी तरह से कंट्रोल करने और उस पर भरोसा करने की सुविधा न हो, तब तक JavaScript इंटरफ़ेस के लिए सहायता को कभी चालू न करें.

एचटीएमएल मैसेज चैनलों का इस्तेमाल करना

अगर आपके ऐप्लिकेशन को Android 6.0 (एपीआई लेवल 23) और उसके बाद के वर्शन पर चलने वाले डिवाइसों पर, JavaScript इंटरफ़ेस की सहायता का इस्तेमाल करना है, तो वेबसाइट और अपने ऐप्लिकेशन के बीच कम्यूनिकेट करने के बजाय, एचटीएमएल मैसेज चैनलों का इस्तेमाल करें. इस बारे में यहां दिए गए कोड स्निपेट में बताया गया है:

Kotlin

val myWebView: WebView = findViewById(R.id.webview)

// channel[0] and channel[1] represent the two ports.
// They are already entangled with each other and have been started.
val channel: Array<out WebMessagePort> = myWebView.createWebMessageChannel()

// Create handler for channel[0] to receive messages.
channel[0].setWebMessageCallback(object : WebMessagePort.WebMessageCallback() {

    override fun onMessage(port: WebMessagePort, message: WebMessage) {
        Log.d(TAG, "On port $port, received this message: $message")
    }
})

// Send a message from channel[1] to channel[0].
channel[1].postMessage(WebMessage("My secure message"))

Java

WebView myWebView = (WebView) findViewById(R.id.webview);

// channel[0] and channel[1] represent the two ports.
// They are already entangled with each other and have been started.
WebMessagePort[] channel = myWebView.createWebMessageChannel();

// Create handler for channel[0] to receive messages.
channel[0].setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
    @Override
    public void onMessage(WebMessagePort port, WebMessage message) {
         Log.d(TAG, "On port " + port + ", received this message: " + message);
    }
});

// Send a message from channel[1] to channel[0].
channel[1].postMessage(new WebMessage("My secure message"));

इससे जुड़ी जानकारी:

सही अनुमतियां देना

अपने ऐप्लिकेशन के सही तरीके से काम करने के लिए, सिर्फ़ उतनी अनुमतियों का अनुरोध करें जितनी ज़रूरी हैं. जब आपके ऐप्लिकेशन को अनुमतियों की ज़रूरत न हो, तो उन्हें हटा दें.

अनुमतियों को बाद में देने के लिए इंटेंट का इस्तेमाल करना

जब भी हो सके, अपने ऐप्लिकेशन में कोई ऐसी अनुमति न जोड़ें जिसकी ज़रूरत किसी दूसरे ऐप्लिकेशन में पूरी की जा सकती है. इसके बजाय, किसी ऐसे ऐप्लिकेशन को अनुरोध भेजने के लिए इंटेंट का इस्तेमाल करें जिसके पास पहले से ही ज़रूरी अनुमति है.

नीचे दिए गए उदाहरण में, उपयोगकर्ताओं को READ_CONTACTS और WRITE_CONTACTS अनुमतियों का अनुरोध करने के बजाय, किसी संपर्क ऐप्लिकेशन पर ले जाने के लिए इंटेंट का इस्तेमाल करने का तरीका बताया गया है:

Kotlin

// Delegates the responsibility of creating the contact to a contacts app,
// which has already been granted the appropriate WRITE_CONTACTS permission.
Intent(Intent.ACTION_INSERT).apply {
    type = ContactsContract.Contacts.CONTENT_TYPE
}.also { intent ->
    // Make sure that the user has a contacts app installed on their device.
    intent.resolveActivity(packageManager)?.run {
        startActivity(intent)
    }
}

Java

// Delegates the responsibility of creating the contact to a contacts app,
// which has already been granted the appropriate WRITE_CONTACTS permission.
Intent insertContactIntent = new Intent(Intent.ACTION_INSERT);
insertContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);

// Make sure that the user has a contacts app installed on their device.
if (insertContactIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(insertContactIntent);
}

इसके अलावा, अगर आपके ऐप्लिकेशन को फ़ाइल-आधारित I/O (इनपुट/आउटपुट) करने की ज़रूरत है, जैसे कि स्टोरेज ऐक्सेस करना या कोई फ़ाइल चुनना, तो इसके लिए उसे खास अनुमतियों की ज़रूरत नहीं होती. इसकी वजह यह है कि सिस्टम आपके ऐप्लिकेशन की ओर से ये काम पूरा कर सकता है. इसके अलावा, जब कोई उपयोगकर्ता किसी खास यूआरआई पर कॉन्टेंट चुनता है, तो कॉल करने वाले ऐप्लिकेशन को चुने गए रिसॉर्स की अनुमति मिल जाती है.

इससे जुड़ी जानकारी:

सभी ऐप्लिकेशन के साथ डेटा सुरक्षित तरीके से शेयर करना

अपने ऐप्लिकेशन के कॉन्टेंट को अन्य ऐप्लिकेशन के साथ ज़्यादा सुरक्षित तरीके से शेयर करने के लिए, ये सबसे सही तरीके अपनाएं:

  • ज़रूरत के हिसाब से, रीड-ओनली या सिर्फ़ लिखने की अनुमतियां लागू करें.
  • FLAG_GRANT_READ_URI_PERMISSION और FLAG_GRANT_WRITE_URI_PERMISSION फ़्लैग का इस्तेमाल करके, क्लाइंट को डेटा का ऐक्सेस एक बार दें.
  • डेटा शेयर करते समय, file:// यूआरआई के बजाय content:// यूआरआई का इस्तेमाल करें. FileProvider के उदाहरण, आपके लिए यह काम करते हैं.

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

Kotlin

// Create an Intent to launch a PDF viewer for a file owned by this app.
Intent(Intent.ACTION_VIEW).apply {
    data = Uri.parse("content://com.example/personal-info.pdf")

    // This flag gives the started app read access to the file.
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}.also { intent ->
    // Make sure that the user has a PDF viewer app installed on their device.
    intent.resolveActivity(packageManager)?.run {
        startActivity(intent)
    }
}

Java

// Create an Intent to launch a PDF viewer for a file owned by this app.
Intent viewPdfIntent = new Intent(Intent.ACTION_VIEW);
viewPdfIntent.setData(Uri.parse("content://com.example/personal-info.pdf"));

// This flag gives the started app read access to the file.
viewPdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Make sure that the user has a PDF viewer app installed on their device.
if (viewPdfIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(viewPdfIntent);
}

ध्यान दें: लिखने की अनुमति वाली ऐप्लिकेशन होम डायरेक्ट्री से फ़ाइलें चलाना, W^X के उल्लंघन के दायरे में आता है. इस वजह से, Android 10 (एपीआई लेवल 29) और उसके बाद के वर्शन को टारगेट करने वाले ऐसे ऐप्लिकेशन जो भरोसेमंद नहीं हैं वे ऐप्लिकेशन की होम डायरेक्ट्री में मौजूद फ़ाइलों पर exec() को ट्रिगर नहीं कर सकते. वे सिर्फ़ ऐप्लिकेशन की APK फ़ाइल में एम्बेड किए गए बाइनरी कोड को ट्रिगर कर सकते हैं. इसके अलावा, Android 10 और उसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन, dlopen() की मदद से खोली गई फ़ाइलों के एक्ज़ीक्यूटेबल कोड में, मेमोरी में बदलाव नहीं कर सकते. इसमें, टेक्स्ट को दूसरी जगह ले जाने वाली, शेयर की गई ऑब्जेक्ट (.so) फ़ाइलें शामिल हैं.

इससे जुड़ी जानकारी: android:grantUriPermissions

डेटा को सुरक्षित तरीके से सेव करना

आपके ऐप्लिकेशन को उपयोगकर्ता की संवेदनशील जानकारी का ऐक्सेस ज़रूरत पड़ सकता है. हालांकि, उपयोगकर्ता आपके ऐप्लिकेशन को अपने डेटा का ऐक्सेस सिर्फ़ तब देते हैं, जब उन्हें भरोसा हो कि आपके पास डेटा को सुरक्षित रखने की ज़रूरी जानकारी है.

निजी डेटा को डिवाइस के स्टोरेज में सेव करना

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

यहां दिया गया कोड स्निपेट, इंटरनल स्टोरेज में डेटा लिखने का एक तरीका दिखाता है:

Kotlin

// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
val FILE_NAME = "sensitive_info.txt"
val fileContents = "This is some top-secret information!"
File(filesDir, FILE_NAME).bufferedWriter().use { writer ->
    writer.write(fileContents)
}

Java

// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
final String FILE_NAME = "sensitive_info.txt";
String fileContents = "This is some top-secret information!";
try (BufferedWriter writer =
             new BufferedWriter(new FileWriter(new File(getFilesDir(), FILE_NAME)))) {
    writer.write(fileContents);
} catch (IOException e) {
    // Handle exception.
}

नीचे दिया गया कोड स्निपेट, इनवर्स ऑपरेशन दिखाता है. इसमें, इंटरनल स्टोरेज से डेटा पढ़ा जा रहा है:

Kotlin

val FILE_NAME = "sensitive_info.txt"
val contents = File(filesDir, FILE_NAME).bufferedReader().useLines { lines ->
    lines.fold("") { working, line ->
        "$working\n$line"
    }
}

Java

final String FILE_NAME = "sensitive_info.txt";
StringBuffer stringBuffer = new StringBuffer();
try (BufferedReader reader =
             new BufferedReader(new FileReader(new File(getFilesDir(), FILE_NAME)))) {

    String line = reader.readLine();
    while (line != null) {
        stringBuffer.append(line).append('\n');
        line = reader.readLine();
    }
} catch (IOException e) {
    // Handle exception.
}

इससे जुड़ी जानकारी:

इस्तेमाल के उदाहरण के आधार पर, बाहरी स्टोरेज में डेटा सेव करना

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

अगर किसी फ़ाइल में निजी या संवेदनशील जानकारी शामिल नहीं है, लेकिन वह सिर्फ़ आपके ऐप्लिकेशन में उपयोगकर्ता के लिए काम की है, तो फ़ाइल को बाहरी स्टोरेज में ऐप्लिकेशन के हिसाब से बनी डायरेक्ट्री में सेव करें.

अगर आपके ऐप्लिकेशन को ऐसी फ़ाइल को ऐक्सेस या सेव करना है जो दूसरे ऐप्लिकेशन के लिए काम की है, तो इस्तेमाल के उदाहरण के आधार पर, इनमें से किसी एक एपीआई का इस्तेमाल करें:

स्टोरेज वॉल्यूम की उपलब्धता देखना

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

डेटा की पुष्टि करना

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

नीचे दिए गए कोड स्निपेट में, हैश की पुष्टि करने वाले टूल का उदाहरण दिया गया है:

Kotlin

val hash = calculateHash(stream)
// Store "expectedHash" in a secure location.
if (hash == expectedHash) {
    // Work with the content.
}

// Calculating the hash code can take quite a bit of time, so it shouldn't
// be done on the main thread.
suspend fun calculateHash(stream: InputStream): String {
    return withContext(Dispatchers.IO) {
        val digest = MessageDigest.getInstance("SHA-512")
        val digestStream = DigestInputStream(stream, digest)
        while (digestStream.read() != -1) {
            // The DigestInputStream does the work; nothing for us to do.
        }
        digest.digest().joinToString(":") { "%02x".format(it) }
    }
}

Java

Executor threadPoolExecutor = Executors.newFixedThreadPool(4);
private interface HashCallback {
    void onHashCalculated(@Nullable String hash);
}

boolean hashRunning = calculateHash(inputStream, threadPoolExecutor, hash -> {
    if (Objects.equals(hash, expectedHash)) {
        // Work with the content.
    }
});

if (!hashRunning) {
    // There was an error setting up the hash function.
}

private boolean calculateHash(@NonNull InputStream stream,
                              @NonNull Executor executor,
                              @NonNull HashCallback hashCallback) {
    final MessageDigest digest;
    try {
        digest = MessageDigest.getInstance("SHA-512");
    } catch (NoSuchAlgorithmException nsa) {
        return false;
    }

    // Calculating the hash code can take quite a bit of time, so it shouldn't
    // be done on the main thread.
    executor.execute(() -> {
        String hash;
        try (DigestInputStream digestStream =
                new DigestInputStream(stream, digest)) {
            while (digestStream.read() != -1) {
                // The DigestInputStream does the work; nothing for us to do.
            }
            StringBuilder builder = new StringBuilder();
            for (byte aByte : digest.digest()) {
                builder.append(String.format("%02x", aByte)).append(':');
            }
            hash = builder.substring(0, builder.length() - 1);
        } catch (IOException e) {
            hash = null;
        }

        final String calculatedHash = hash;
        runOnUiThread(() -> hashCallback.onHashCalculated(calculatedHash));
    });
    return true;
}

कैश मेमोरी फ़ाइलों में सिर्फ़ ग़ैर-संवेदनशील डेटा सेव करना

ऐप्लिकेशन के ग़ैर-संवेदनशील डेटा को तेज़ी से ऐक्सेस करने के लिए, उसे डिवाइस के कैश मेमोरी में सेव करें. एक एमबी से ज़्यादा साइज़ के कैश मेमोरी के लिए, getExternalCacheDir() का इस्तेमाल करें. 1 एमबी या उससे कम साइज़ के कैश मेमोरी के लिए, getCacheDir() का इस्तेमाल करें. दोनों तरीकों से आपको File ऑब्जेक्ट मिलता है, जिसमें आपके ऐप्लिकेशन का कैश मेमोरी में सेव किया गया डेटा होता है.

यहां दिए गए कोड स्निपेट में, उस फ़ाइल को कैश मेमोरी में सेव करने का तरीका बताया गया है जिसे आपके ऐप्लिकेशन ने हाल ही में डाउनलोड किया है:

Kotlin

val cacheFile = File(myDownloadedFileUri).let { fileToCache ->
    File(cacheDir.path, fileToCache.name)
}

Java

File cacheDir = getCacheDir();
File fileToCache = new File(myDownloadedFileUri);
String fileToCacheName = fileToCache.getName();
File cacheFile = new File(cacheDir.getPath(), fileToCacheName);

ध्यान दें: अगर आपने अपने ऐप्लिकेशन का कैश मेमोरी, शेयर किए गए स्टोरेज में सेव करने के लिए getExternalCacheDir() का इस्तेमाल किया है, तो हो सकता है कि आपका ऐप्लिकेशन चलने के दौरान, उपयोगकर्ता इस स्टोरेज वाले मीडिया को बाहर निकाल दे. उपयोगकर्ता के इस व्यवहार की वजह से, कैश मेमोरी में डेटा सेव न होने की समस्या को ठीक करने के लिए लॉजिक शामिल करें.

चेतावनी: इन फ़ाइलों पर कोई सुरक्षा लागू नहीं होती. इसलिए, Android 10 (एपीआई लेवल 29) या इससे पहले के वर्शन को टारगेट करने वाला और WRITE_EXTERNAL_STORAGE अनुमति वाला कोई भी ऐप्लिकेशन, इस कैश मेमोरी का कॉन्टेंट ऐक्सेस कर सकता है.

मिलती-जुलती जानकारी: डेटा और फ़ाइल स्टोरेज की खास जानकारी

निजी मोड में SharedPreferences का इस्तेमाल करना

अपने ऐप्लिकेशन के SharedPreferences ऑब्जेक्ट बनाने या ऐक्सेस करने के लिए, getSharedPreferences() का इस्तेमाल करते समय MODE_PRIVATE का इस्तेमाल करें. इस तरह, सिर्फ़ आपका ऐप्लिकेशन, शेयर की गई प्राथमिकता फ़ाइल में मौजूद जानकारी को ऐक्सेस कर सकता है.

अगर आपको सभी ऐप्लिकेशन के साथ डेटा शेयर करना है, तो SharedPreferences ऑब्जेक्ट का इस्तेमाल न करें. इसके बजाय, सभी ऐप्लिकेशन में सुरक्षित तरीके से डेटा शेयर करने के लिए यह तरीका अपनाएं.

सुरक्षा लाइब्रेरी में EncryptedSharedPreferences क्लास भी उपलब्ध होती है. यह SharedPreferences क्लास को रैप करती है और कुंजियों और वैल्यू को अपने-आप एन्क्रिप्ट करती है.

इससे जुड़ी जानकारी:

सेवाओं और डिपेंडेंसी को अप-टू-डेट रखना

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

Google Play services की सुरक्षा देने वाली कंपनी की जानकारी देखना

ध्यान दें: यह सेक्शन सिर्फ़ उन डिवाइसों को टारगेट करने वाले ऐप्लिकेशन पर लागू होता है जिनमें Google Play services इंस्टॉल है.

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

यह पता लगाने के लिए कि आपके ऐप्लिकेशन के इंस्टॉल किए गए डिवाइस पर, Google Play services का वर्शन अप-टू-डेट है या नहीं, एसएसएल एक्सप्लॉइट से सुरक्षा पाने के लिए, सुरक्षा सेवा देने वाली कंपनी को अपडेट करने के बारे में गाइड में दिया गया तरीका अपनाएं.

इससे जुड़ी जानकारी:

ऐप्लिकेशन की सभी डिपेंडेंसी अपडेट करना

अपने ऐप्लिकेशन को डिप्लॉय करने से पहले, पक्का करें कि सभी लाइब्रेरी, SDK टूल, और अन्य डिपेंडेंसी अप-टू-डेट हों:

  • Android SDK टूल जैसी पहले पक्ष की डिपेंडेंसी के लिए, Android Studio में मौजूद अपडेट करने वाले टूल का इस्तेमाल करें. जैसे, SDK मैनेजर.
  • तीसरे पक्ष की डिपेंडेंसी के लिए, उन लाइब्रेरी की वेबसाइटें देखें जिनका इस्तेमाल आपका ऐप्लिकेशन करता है. साथ ही, उपलब्ध सभी अपडेट और सुरक्षा पैच इंस्टॉल करें.

इससे जुड़ी जानकारी: बिल्ड डिपेंडेंसी जोड़ना

ज़्यादा जानकारी

अपने ऐप्लिकेशन को ज़्यादा सुरक्षित बनाने के तरीके के बारे में ज़्यादा जानने के लिए, यहां दिए गए रिसॉर्स देखें: