Google Play services और रनटाइम की अनुमतियां

Android 6.0 Marshmallow के बाद से, Android ऐसे अनुमति मॉडल का इस्तेमाल करता है जो ऐप्लिकेशन इंस्टॉल करने और अपने-आप अपडेट होने की प्रोसेस को आसान बनाता है. ऐप्लिकेशन इंस्टॉल करने से पहले के बजाय रनटाइम पर अनुमतियों का अनुरोध किया जाता है. इसके अलावा, उपयोगकर्ता कुछ खास अनुमतियों को अस्वीकार कर सकते हैं. उपयोगकर्ताओं को यह सुविधा देने के लिए, आपको यह पक्का करना होगा कि जब कोई उपयोगकर्ता किसी खास अनुमति को चालू या बंद करता है, तो आपका ऐप्लिकेशन उम्मीद के मुताबिक काम करे.

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

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

ज़रूरी शर्तें

आपको अपनी AndroidManifest.xml फ़ाइल में अनुमतियों के बारे में एलान करना होगा. उदाहरण के लिए:

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

दिशा-निर्देश

एपीआई को कॉल करने से पहले, अनुमतियों की पुष्टि करें

आपको अपनी AndroidManifest.xml फ़ाइल में जिन एपीआई का इस्तेमाल करना है उनका एलान करने के बाद, एपीआई को कॉल करने से पहले पक्का करें कि आपके पास ज़रूरी अनुमति है. ऐसा ActivityCompat या ContextCompat में से checkSelfPermission तरीके का इस्तेमाल करके किया जा सकता है.

अगर कॉल 'गलत' दिखाता है, तो इसका मतलब है कि अनुमतियां नहीं दी गई हैं और आपको उनका अनुरोध करने के लिए, requestPermissions का इस्तेमाल करना चाहिए. इसका जवाब एक कॉलबैक में भेजा जाता है जो आपको अगले चरण में दिखेगा.

उदाहरण के लिए:

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
    != PackageManager.PERMISSION_GRANTED) {
  // Check Permissions Now
  ActivityCompat.requestPermissions(this,
      new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
      REQUEST_LOCATION);
} else {
  // permission has been granted, continue as usual
  Task<Location> locationResult = LocationServices
      .getFusedLocationProviderClient(this /** Context */)
      .getLastLocation();
}

अनुरोध की अनुमति पर कॉलबैक लागू करें

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

public void onRequestPermissionsResult(int requestCode,
                                       String[] permissions,
                                       int[] grantResults) {
    if (requestCode == REQUEST_LOCATION) {
        if(grantResults.length == 1
           && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // We can now safely use the API we requested access to
            Task<Location> locationResult = LocationServices
                .getFusedLocationProviderClient(this /** Context */)
                .getLastLocation();
        } else {
            // Permission was denied or request was cancelled
        }
    }
}

अनुमति की वजह दिखाएं

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

ऐसे में, requestPermissions पर कॉल करने से पहले, आपको shouldShowRequestPermissionRationale को कॉल करना चाहिए. अगर यह 'सही' दिखाता है, तो आपको अनुमति के लिए ज़्यादा संदर्भ दिखाने के लिए कुछ यूज़र इंटरफ़ेस (यूआई) बनाना चाहिए.

उदाहरण के लिए, आपका कोड कुछ ऐसा दिख सकता है:

if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
    != PackageManager.PERMISSION_GRANTED) {
    // Check Permissions Now
    private static final int REQUEST_LOCATION = 2;

    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
            Manifest.permission.ACCESS_FINE_LOCATION)) {
        // Display UI and wait for user interaction
    } else {
        ActivityCompat.requestPermissions(
            this, new String[]{Manifest.permission.LOCATION_FINE},
            ACCESS_FINE_LOCATION);
    }
} else {
    // permission has been granted, continue as usual
    Task<Location> locationResult = LocationServices
        .getFusedLocationProviderClient(this /** Context */)
        .getLastLocation();
}

कनेक्शन के काम न करने की समस्याओं को ठीक करना

अगर आपका ऐप्लिकेशन, काम न करने वाले GoogleApiClient का इस्तेमाल करता है, तो connect() को कॉल करने पर, Google Play services पुष्टि करता है कि उसके पास सभी ज़रूरी अनुमतियां हैं. जब Google Play services को अनुमति वाले ऐसे ग्रुप मिलते हैं जिनकी ज़रूरत होती है, तब connect() काम नहीं करता.

अगर connect() पर कॉल नहीं हो पाता है, तो पक्का करें कि आपका ऐप्लिकेशन कनेक्शन खराब होने को सही तरीके से हैंडल करता हो. अगर Google Play services के पास अनुमतियां नहीं हैं, तो यूज़र फ़्लो को शुरू करने और उन्हें ठीक करने के लिए, startResolutionForResult() शुरू करें.

उदाहरण के लिए:

@Override
public void onConnectionFailed(ConnectionResult result) {
    if (mResolvingError) {
        // Already attempting to resolve an error.
        return;
    } else if (result.hasResolution()) {
        try {
            mResolvingError = true;
            result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
        } catch (SendIntentException e) {
            // There was an error with the resolution intent. Try again.
            mGoogleApiClient.connect();
        }
    } else {
        // Show dialog using GooglePlayServicesUtil.getErrorDialog()
        showErrorDialog(result.getErrorCode());
        mResolvingError = true;
    }
}

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