स्टोर ब्लॉक करें

कई उपयोगकर्ता अब भी Android डिवाइस सेट अप करते समय, अपने क्रेडेंशियल मैनेज करते हैं. यह मैन्युअल प्रोसेस चुनौतीपूर्ण हो सकती है और अक्सर इससे उपयोगकर्ता अनुभव खराब होता है. Block Store API, Google Play services की लाइब्रेरी है. यह ऐप्लिकेशन को उपयोगकर्ता के क्रेडेंशियल सेव करने का तरीका उपलब्ध कराती है. इससे, उपयोगकर्ता के पासवर्ड सेव करने से जुड़ी जटिलता या सुरक्षा से जुड़े जोखिम से बचा जा सकता है.

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

Block Store का इस्तेमाल करने के फ़ायदे:

  • डेवलपर के लिए, क्रेडेंशियल को एन्क्रिप्ट (सुरक्षित) करके सेव करने का तरीका. जब भी संभव हो, क्रेडेंशियल को एंड-टू-एंड एन्क्रिप्ट (E2EE) किया जाता है.
  • उपयोगकर्ता नाम और पासवर्ड के बजाय टोकन सेव करें.
  • साइन इन फ़्लो से जुड़ी समस्याओं को हल करना.
  • उपयोगकर्ताओं को जटिल पासवर्ड मैनेज करने की परेशानी से बचाना.
  • Google, उपयोगकर्ता की पहचान की पुष्टि करता है.

शुरू करने से पहले

अपने ऐप्लिकेशन को तैयार करने के लिए, नीचे दिए गए सेक्शन में दिया गया तरीका अपनाएं.

अपने ऐप्लिकेशन को कॉन्फ़िगर करना

प्रोजेक्ट-लेवल की build.gradle फ़ाइल में, buildscript और allprojects, दोनों सेक्शन में Google की Maven रिपॉज़िटरी शामिल करें:

buildscript {
  repositories {
    google()
    mavenCentral()
  }
}

allprojects {
  repositories {
    google()
    mavenCentral()
  }
}

Block Store API के लिए, Google Play services की डिपेंडेंसी को अपने मॉड्यूल की Gradle बिल्ड फ़ाइल में जोड़ें. आम तौर पर, यह फ़ाइल app/build.gradle होती है:

dependencies {
  implementation 'com.google.android.gms:play-services-auth-blockstore:16.4.0'
}

यह कैसे काम करता है

ब्लॉक स्टोर की मदद से, डेवलपर 16 बाइट तक के ऐरे सेव और वापस ला सकते हैं. इसकी मदद से, उपयोगकर्ता के मौजूदा सेशन की अहम जानकारी सेव की जा सकती है. साथ ही, इस जानकारी को अपनी पसंद के मुताबिक सेव किया जा सकता है. इस डेटा को एंड-टू-एंड एन्क्रिप्ट (E2EE) किया जा सकता है. साथ ही, Block Store के साथ काम करने वाला इन्फ़्रास्ट्रक्चर, बैकअप और रिस्टोर करने वाले इन्फ़्रास्ट्रक्चर के ऊपर बनाया गया है.

इस गाइड में, उपयोगकर्ता के टोकन को Block Store में सेव करने के इस्तेमाल के उदाहरण के बारे में बताया गया है. यहां बताया गया है कि Block Store का इस्तेमाल करने वाला ऐप्लिकेशन कैसे काम करेगा:

  1. अपने ऐप्लिकेशन के पुष्टि करने के फ़्लो के दौरान या उसके बाद कभी भी, उपयोगकर्ता के पुष्टि करने वाले टोकन को Block Store में सेव किया जा सकता है, ताकि बाद में उसे वापस पाया जा सके.
  2. टोकन को डिवाइस में सेव किया जाएगा. साथ ही, इसे क्लाउड पर भी बैक अप किया जा सकता है. अगर मुमकिन हो, तो इसे एंड-टू-एंड एन्क्रिप्ट (पूरी तरह सुरक्षित) किया जाएगा.
  3. जब उपयोगकर्ता किसी नए डिवाइस पर डेटा वापस लाने की प्रोसेस शुरू करता है, तब डेटा ट्रांसफ़र होता है.
  4. अगर उपयोगकर्ता, ऐप्लिकेशन को वापस लाने के दौरान उसे वापस लाता है, तो आपका ऐप्लिकेशन नए डिवाइस पर Block Store से सेव किया गया टोकन वापस पा सकता है.

टोकन सेव करना

जब कोई उपयोगकर्ता आपके ऐप्लिकेशन में साइन इन करता है, तो आपके पास उस उपयोगकर्ता के लिए जनरेट किए गए पुष्टि करने वाले टोकन को Block Store में सेव करने का विकल्प होता है. इस टोकन को, यूनीक की जोड़ी की वैल्यू का इस्तेमाल करके सेव किया जा सकता है. हर एंट्री में ज़्यादा से ज़्यादा 4 केबी की वैल्यू हो सकती है. टोकन को सेव करने के लिए, StoreBytesData.Builder के किसी इंस्टेंस पर setBytes() और setKey() को कॉल करें. इससे, सोर्स डिवाइस पर उपयोगकर्ता के क्रेडेंशियल सेव हो जाएंगे. Block Store में टोकन सेव करने के बाद, उसे एन्क्रिप्ट (सुरक्षित) करके डिवाइस में सेव किया जाता है.

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

JavaKotlin
  BlockstoreClient client = Blockstore.getClient(this);
  byte[] bytes1 = new byte[] { 1, 2, 3, 4 };  // Store one data block.
  String key1 = "com.example.app.key1";
  StoreBytesData storeRequest1 = StoreBytesData.Builder()
          .setBytes(bytes1)
          // Call this method to set the key value pair the data should be associated with.
          .setKeys(Arrays.asList(key1))
          .build();
  client.storeBytes(storeRequest1)
    .addOnSuccessListener(result -> Log.d(TAG, "stored " + result + " bytes"))
    .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
  val client = Blockstore.getClient(this)

  val bytes1 = byteArrayOf(1, 2, 3, 4) // Store one data block.
  val key1 = "com.example.app.key1"
  val storeRequest1 = StoreBytesData.Builder()
    .setBytes(bytes1) // Call this method to set the key value with which the data should be associated with.
    .setKeys(Arrays.asList(key1))
    .build()
  client.storeBytes(storeRequest1)
    .addOnSuccessListener { result: Int ->
      Log.d(TAG,
            "Stored $result bytes")
    }
    .addOnFailureListener { e ->
      Log.e(TAG, "Failed to store bytes", e)
    }
के साथ सेव किया जाता है.

डिफ़ॉल्ट टोकन का इस्तेमाल करना

StoreBytes का इस्तेमाल करके, बिना किसी पासकोड के सेव किए गए डेटा को डिफ़ॉल्ट पासकोड BlockstoreClient.DEFAULT_BYTES_DATA_KEY का इस्तेमाल करके एन्क्रिप्ट (सुरक्षित) किया जाता है.

JavaKotlin
  BlockstoreClient client = Blockstore.getClient(this);
  // The default key BlockstoreClient.DEFAULT_BYTES_DATA_KEY.
  byte[] bytes = new byte[] { 9, 10 };
  StoreBytesData storeRequest = StoreBytesData.Builder()
          .setBytes(bytes)
          .build();
  client.storeBytes(storeRequest)
    .addOnSuccessListener(result -> Log.d(TAG, "stored " + result + " bytes"))
    .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
  val client = Blockstore.getClient(this);
  // the default key BlockstoreClient.DEFAULT_BYTES_DATA_KEY.
  val bytes = byteArrayOf(1, 2, 3, 4)
  val storeRequest = StoreBytesData.Builder()
    .setBytes(bytes)
    .build();
  client.storeBytes(storeRequest)
    .addOnSuccessListener { result: Int ->
      Log.d(TAG,
            "stored $result bytes")
    }
    .addOnFailureListener { e ->
      Log.e(TAG, "Failed to store bytes", e)
    }

टोकन वापस पाना

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

यहां दिए गए सैंपल में, खास कुंजियों के आधार पर कई टोकन वापस पाने का तरीका बताया गया है.

JavaKotlin
BlockstoreClient client = Blockstore.getClient(this);

// Retrieve data associated with certain keys.
String key1 = "com.example.app.key1";
String key2 = "com.example.app.key2";
String key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY; // Used to retrieve data stored without a key

List requestedKeys = Arrays.asList(key1, key2, key3); // Add keys to array
RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder()
    .setKeys(requestedKeys)
    .build();

client.retrieveBytes(retrieveRequest)
    .addOnSuccessListener(
        result -> {
          Map<String, BlockstoreData> blockstoreDataMap = result.getBlockstoreDataMap();
          for (Map.Entry<String, BlockstoreData> entry : blockstoreDataMap.entrySet()) {
            Log.d(TAG, String.format(
                "Retrieved bytes %s associated with key %s.",
                new String(entry.getValue().getBytes()), entry.getKey()));
          }
        })
    .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
val client = Blockstore.getClient(this)

// Retrieve data associated with certain keys.
val key1 = "com.example.app.key1"
val key2 = "com.example.app.key2"
val key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY // Used to retrieve data stored without a key

val requestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array

val retrieveRequest = RetrieveBytesRequest.Builder()
  .setKeys(requestedKeys)
  .build()

client.retrieveBytes(retrieveRequest)
  .addOnSuccessListener { result: RetrieveBytesResponse ->
    val blockstoreDataMap =
      result.blockstoreDataMap
    for ((key, value) in blockstoreDataMap) {
      Log.d(ContentValues.TAG, String.format(
        "Retrieved bytes %s associated with key %s.",
        String(value.bytes), key))
    }
  }
  .addOnFailureListener { e: Exception? ->
    Log.e(ContentValues.TAG,
          "Failed to store bytes",
          e)
  }

सभी टोकन वापस पाना.

BlockStore में सेव किए गए सभी टोकन को वापस पाने का तरीका यहां बताया गया है.

JavaKotlin
BlockstoreClient client = Blockstore.getClient(this)

// Retrieve all data.
RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder()
    .setRetrieveAll(true)
    .build();

client.retrieveBytes(retrieveRequest)
    .addOnSuccessListener(
        result -> {
          Map<String, BlockstoreData> blockstoreDataMap = result.getBlockstoreDataMap();
          for (Map.Entry<String, BlockstoreData> entry : blockstoreDataMap.entrySet()) {
            Log.d(TAG, String.format(
                "Retrieved bytes %s associated with key %s.",
                new String(entry.getValue().getBytes()), entry.getKey()));
          }
        })
    .addOnFailureListener(e -> Log.e(TAG, "Failed to store bytes", e));
val client = Blockstore.getClient(this)

val retrieveRequest = RetrieveBytesRequest.Builder()
  .setRetrieveAll(true)
  .build()

client.retrieveBytes(retrieveRequest)
  .addOnSuccessListener { result: RetrieveBytesResponse ->
    val blockstoreDataMap =
      result.blockstoreDataMap
    for ((key, value) in blockstoreDataMap) {
      Log.d(ContentValues.TAG, String.format(
        "Retrieved bytes %s associated with key %s.",
        String(value.bytes), key))
    }
  }
  .addOnFailureListener { e: Exception? ->
    Log.e(ContentValues.TAG,
          "Failed to store bytes",
          e)
  }

डिफ़ॉल्ट पासकोड वापस पाने का तरीका यहां बताया गया है.

JavaKotlin
BlockStoreClient client = Blockstore.getClient(this);
RetrieveBytesRequest retrieveRequest = new RetrieveBytesRequest.Builder()
    .setKeys(Arrays.asList(BlockstoreClient.DEFAULT_BYTES_DATA_KEY))
    .build();
client.retrieveBytes(retrieveRequest);
val client = Blockstore.getClient(this)

val retrieveRequest = RetrieveBytesRequest.Builder()
  .setKeys(Arrays.asList(BlockstoreClient.DEFAULT_BYTES_DATA_KEY))
  .build()
client.retrieveBytes(retrieveRequest)

टोकन मिटाना

BlockStore से टोकन मिटाने की ज़रूरत इन वजहों से पड़ सकती है:

  • उपयोगकर्ता, साइन आउट करने के यूज़र फ़्लो से गुज़रता है.
  • टोकन रद्द कर दिया गया है या वह अमान्य है.

टोकन वापस पाने की तरह ही, यह भी तय किया जा सकता है कि किन टोकन को मिटाना है. इसके लिए, उन कुंजियों का कलेक्शन सेट करें जिन्हें मिटाना है.

यहां दिए गए उदाहरण में, कुछ कुंजियों को मिटाने का तरीका बताया गया है:

JavaKotlin
BlockstoreClient client = Blockstore.getClient(this);

// Delete data associated with certain keys.
String key1 = "com.example.app.key1";
String key2 = "com.example.app.key2";
String key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY; // Used to delete data stored without key

List requestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array
DeleteBytesRequest deleteRequest = new DeleteBytesRequest.Builder()
      .setKeys(requestedKeys)
      .build();
client.deleteBytes(deleteRequest)
val client = Blockstore.getClient(this)

// Retrieve data associated with certain keys.
val key1 = "com.example.app.key1"
val key2 = "com.example.app.key2"
val key3 = BlockstoreClient.DEFAULT_BYTES_DATA_KEY // Used to retrieve data stored without a key

val requestedKeys = Arrays.asList(key1, key2, key3) // Add keys to array

val retrieveRequest = DeleteBytesRequest.Builder()
      .setKeys(requestedKeys)
      .build()

client.deleteBytes(retrieveRequest)

सभी टोकन मिटाना

यहां दिए गए उदाहरण में, BlockStore में सेव किए गए सभी टोकन मिटाने का तरीका बताया गया है:

JavaKotlin
// Delete all data.
DeleteBytesRequest deleteAllRequest = new DeleteBytesRequest.Builder()
      .setDeleteAll(true)
      .build();
client.deleteBytes(deleteAllRequest)
.addOnSuccessListener(result -> Log.d(TAG, "Any data found and deleted? " + result));

  val deleteAllRequest = DeleteBytesRequest.Builder()
  .setDeleteAll(true)
  .build()
retrieve bytes, the key BlockstoreClient.DEFAULT_BYTES_DATA_KEY can be used
in the RetrieveBytesRequest instance in order to get your saved data

The following example shows how to retrieve the default key.

Java

End-to-end encryption

In order for end-to-end encryption to be made available, the device must be running Android 9 or higher, and the user must have set a screen lock (PIN, pattern, or password) for their device. You can verify if encryption will be available on the device by calling isEndToEndEncryptionAvailable().

The following sample shows how to verify if encryption will be available during cloud backup:

client.isEndToEndEncryptionAvailable()
       
.addOnSuccessListener { result ->
         
Log.d(TAG, "Will Block Store cloud backup be end-to-end encrypted? $result")
       
}

क्लाउड बैकअप की सुविधा चालू करना

क्लाउड बैकअप की सुविधा चालू करने के लिए, अपने StoreBytesData ऑब्जेक्ट में setShouldBackupToCloud() तरीका जोड़ें. setShouldBackupToCloud() को 'सही है' पर सेट करने पर, Block Store समय-समय पर क्लाउड में सेव किए गए बाइट का बैकअप लेगा.

यहां दिए गए सैंपल में, सिर्फ़ तब क्लाउड बैकअप चालू करने का तरीका बताया गया है, जब क्लाउड बैकअप एंड-टू-एंड एन्क्रिप्ट (E2EE) हो:

val client = Blockstore.getClient(this)
val storeBytesDataBuilder = StoreBytesData.Builder()
        .setBytes(/* BYTE_ARRAY */)

client.isEndToEndEncryptionAvailable()
        .addOnSuccessListener { isE2EEAvailable ->
          if (isE2EEAvailable) {
            storeBytesDataBuilder.setShouldBackupToCloud(true)
            Log.d(TAG, "E2EE is available, enable backing up bytes to the cloud.")

            client.storeBytes(storeBytesDataBuilder.build())
                .addOnSuccessListener { result ->
                  Log.d(TAG, "stored: ${result.getBytesStored()}")
                }.addOnFailureListener { e ->
                  Log.e(TAG, Failed to store bytes, e)
                }
          } else {
            Log.d(TAG, "E2EE is not available, only store bytes for D2D restore.")
          }
        }

जांच करने का तरीका

डेवलपमेंट के दौरान, डेटा को वापस लाने के फ़्लो की जांच करने के लिए, यहां दिए गए तरीके अपनाएं.

एक ही डिवाइस से ऐप्लिकेशन को अनइंस्टॉल/फिर से इंस्टॉल करना

अगर उपयोगकर्ता ने बैकअप सेवाएं चालू की हैं (इसकी जांच सेटिंग > Google > बैकअप में जाकर की जा सकती है), तो Block Store का डेटा, ऐप्लिकेशन को अनइंस्टॉल/फिर से इंस्टॉल करने पर भी बना रहता है.

जांच करने के लिए, यह तरीका अपनाएं:

  1. अपने टेस्ट ऐप्लिकेशन में Block Store API को इंटिग्रेट करें.
  2. अपना डेटा सेव करने के लिए, Block Store API को ट्रिगर करने के लिए टेस्ट ऐप्लिकेशन का इस्तेमाल करें.
  3. टेस्ट ऐप्लिकेशन को अनइंस्टॉल करें. इसके बाद, उसी डिवाइस पर ऐप्लिकेशन को फिर से इंस्टॉल करें.
  4. अपना डेटा वापस पाने के लिए, Block Store API को ट्रिगर करने के लिए टेस्ट ऐप्लिकेशन का इस्तेमाल करें.
  5. पुष्टि करें कि वापस लाए गए बाइट, अनइंस्टॉल करने से पहले सेव किए गए बाइट जैसे ही हों.

डिवाइस से डिवाइस

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

क्लाउड से डेटा वापस लाना

  1. अपने टेस्ट ऐप्लिकेशन में Block Store API को इंटिग्रेट करें. टेस्ट ऐप्लिकेशन को Play Store पर सबमिट करना होगा.
  2. सोर्स डिवाइस पर, अपने डेटा को सेव करने के लिए, Block Store API को ट्रिगर करने के लिए टेस्ट ऐप्लिकेशन का इस्तेमाल करें. इसके लिए, shouldBackUpToCloud को true पर सेट करें.
  3. O और उसके बाद के वर्शन वाले डिवाइसों पर, Block Store का क्लाउड बैकअप मैन्युअल तरीके से ट्रिगर किया जा सकता है: सेटिंग > Google > बैकअप पर जाएं. इसके बाद, “अभी बैकअप लें” बटन पर क्लिक करें.
    1. Block Store का क्लाउड बैकअप लेने की प्रोसेस पूरी हो गई है या नहीं, इसकी पुष्टि करने के लिए:
      1. बैकअप पूरा होने के बाद, “CloudSyncBpTkSvc” टैग वाली लॉग लाइन खोजें.
      2. आपको इस तरह की लाइनें दिखेंगी: “......, CloudSyncBpTkSvc: sync result: SUCCESS, ..., uploaded size: XXX bytes ...”
    2. Block Store का क्लाउड बैकअप लेने के बाद, पांच मिनट का “कूल डाउन” पीरियड होता है. इन पांच मिनट के दौरान, “अभी बैकअप लें” बटन पर क्लिक करने से, Block Store का कोई और क्लाउड बैकअप ट्रिगर नहीं होगा.
  4. टारगेट किए गए डिवाइस को फ़ैक्ट्री रीसेट करें और क्लाउड से डेटा वापस लाने की प्रोसेस को पूरा करें. ऐप्लिकेशन को वापस लाने की प्रोसेस के दौरान, अपने टेस्ट ऐप्लिकेशन को वापस लाने के लिए चुनें. क्लाउड से डेटा वापस पाने के तरीकों के बारे में ज़्यादा जानकारी के लिए, क्लाउड से डेटा वापस पाने के काम करने वाले तरीके लेख पढ़ें.
  5. टारगेट डिवाइस पर, अपना डेटा वापस पाने के लिए, Block store API को ट्रिगर करने के लिए टेस्ट ऐप्लिकेशन का इस्तेमाल करें.
  6. पुष्टि करें कि वापस लाए गए बाइट, सोर्स डिवाइस में सेव किए गए बाइट जैसे ही हों.

डिवाइस से जुड़ी ज़रूरी शर्तें

एंड-टू-एंड एन्क्रिप्शन (E2EE)

  • एंड-टू-एंड एन्क्रिप्शन (E2EE) की सुविधा, Android 9 (API 29) और उसके बाद के वर्शन वाले डिवाइसों पर काम करती है.
  • एंड-टू-एंड एन्क्रिप्शन की सुविधा चालू करने और उपयोगकर्ता के डेटा को सही तरीके से एन्क्रिप्ट करने के लिए, डिवाइस में पिन, पैटर्न या पासवर्ड से स्क्रीन लॉक सेट होना ज़रूरी है.

एक डिवाइस से दूसरे डिवाइस पर डेटा वापस लाने की प्रोसेस

एक डिवाइस से दूसरे डिवाइस पर डेटा वापस लाने के लिए, आपके पास सोर्स डिवाइस और टारगेट डिवाइस होना चाहिए. ये वे दो डिवाइस होंगे जिनके बीच डेटा ट्रांसफ़र किया जा रहा है.

बैकअप लेने के लिए, सोर्स डिवाइसों में Android 6 (एपीआई 23) और उसके बाद का वर्शन होना चाहिए.

Android 9 (एपीआई 29) और इसके बाद के वर्शन वाले डिवाइसों पर, डेटा को वापस पाने की सुविधा टारगेट करें.

एक डिवाइस से दूसरे डिवाइस पर डेटा वापस लाने के बारे में ज़्यादा जानकारी यहां मिल सकती है.

क्लाउड बैकअप और डेटा वापस लाने की प्रोसेस

क्लाउड पर बैकअप लेने और उसे वापस लाने के लिए, सोर्स डिवाइस और टारगेट डिवाइस की ज़रूरत होगी.

बैकअप लेने के लिए, सोर्स डिवाइसों में Android 6 (एपीआई 23) और उसके बाद का वर्शन होना चाहिए.

टारगेट डिवाइसों को वेंडर के हिसाब से इस्तेमाल किया जा सकता है. Pixel डिवाइसों पर, Android 9 (एपीआई 29) से इस सुविधा का इस्तेमाल किया जा सकता है. इसके अलावा, अन्य सभी डिवाइसों पर Android 12 (एपीआई 31) या इसके बाद के वर्शन का इस्तेमाल किया जाना चाहिए.