معنى - request permission android




Android M-تحقق من إذن وقت التشغيل-كيفية تحديد ما إذا كان المستخدم قد حدد "عدم السؤال مرة أخرى"؟ (16)

أرغب أيضًا في الحصول على المعلومات عما إذا كان المستخدم قد اختار "لم يطلب مرة أخرى" من عدمه. لقد حققت "حلاً تقريبًا" بعلم قبيح ، لكن قبل أن أخبرك كيف ، سوف أخبرك عن حافزي:

أرغب في تقديم وظيفة تشير إلى إذن في البداية. إذا كان المستخدم يستخدمه وليس لديه حقوق ، فسيحصل على مربع الحوار الأول من الأعلى أو الثاني والثالث. عندما يختار المستخدم "لا تسأل مرة أخرى" ، أود تعطيل الوظيفة وعرضها بشكل مختلف. - يتم تشغيل الإجراء الخاص بي عن طريق إدخال نص الدوار ، وأود أيضًا إضافة "(تم إلغاء الإذن)" إلى نص التسمية المعروض. هذا يوضح للمستخدم: "هناك وظائف ولكن لا يمكنني استخدامها ، بسبب إعدادات الأذونات الخاصة بي". ومع ذلك ، لا يبدو هذا ممكنًا ، حيث لا يمكنني التحقق من اختيار "عدم طرح السؤال مرة أخرى" من عدمه.

لقد توصلت إلى حل يمكنني العيش معه من خلال تمكين وظيفتي دائمًا عن طريق فحص إذن نشط. أقوم بعرض رسالة Toast في onRequestPermissionsResult () في حالة حدوث استجابة سلبية ولكن فقط إذا لم أقم بإظهار النافذة المنبثقة المخصصة. لذلك إذا اختار المستخدم "لا تسأل مرة أخرى" ، فسيحصل على رسالة توست فقط. إذا كان المستخدم مترددًا في اختيار "لا تسأل أبدًا مرة أخرى" ، فإنه يحصل فقط على الأساس المنطقي المخصص وطلب الإذن المنبثق من قبل نظام التشغيل ولكن ليس نخب ، لأن ثلاثة إخطارات متتالية سيكون الكثير من الألم.

وفقًا لهذا: http://developer.android.com/preview/features/runtime-permissions.html#coding ، يمكن للتطبيق التحقق من أذونات وقت التشغيل وطلب أذونات إذا لم يتم منحها بالفعل. سيتم عرض مربع الحوار التالي بعد ذلك:

في حال رفض المستخدم إذنًا مهمًا ، يجب أن يعرض تطبيق IMO شرحًا لسبب الحاجة إلى الإذن وما هو تأثير الانخفاض. يحتوي مربع الحوار هذا على خيارين:

  1. أعد المحاولة مرة أخرى (تم طلب الإذن مرة أخرى)
  2. رفض (سيعمل التطبيق بدون هذا الإذن).

إذا قام المستخدم بالتحقق من Never ask again ، فلا يجب عرض مربع الحوار الثاني مع الشرح ، خاصةً إذا كان المستخدم قد رفض من قبل. والسؤال الآن هو: كيف يعرف تطبيقي ما إذا كان المستخدم قد تحقق من Never ask again ؟ لا onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) IMO onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) هذه المعلومات.

والسؤال الثاني هو: هل لدى Google خطط لدمج رسالة مخصصة في مربع حوار الأذونات الذي يفسر لماذا يحتاج التطبيق إلى إذن؟ وبهذه الطريقة لن يكون هناك حوار ثانٍ من شأنه أن يجعل بالتأكيد أفضل.


التوسع في mVck الجواب الصورة أعلاه، يحدد منطق التالية سواء "نسأل مرة أخرى أبدا" تم التحقق من طلب الإذن إعطاء:

private bool _bStorageRationaleBefore;
private bool _bStorageRationaleAfter;        
private const int ANDROID_PERMISSION_REQUEST_CODE__SDCARD = 2;
//private const int ANDROID_PERMISSION_REQUEST_CODE__CAMERA = 1;
private const int ANDROID_PERMISSION_REQUEST_CODE__NONE = 0;

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    switch (requestCode)
    {
        case ANDROID_PERMISSION_REQUEST_CODE__SDCARD:               
            _bStorageRationaleAfter = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
            bool bStorage = grantResults[0] == Permission.Granted;
            bool bNeverAskForStorage =
                !bStorage && (
                    _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
                    _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
                );      
            break;                
    }
}

private List<string> GetRequiredPermissions(out int requestCode)
{
    // Android v6 requires explicit permission granting from user at runtime for security reasons            
    requestCode = ANDROID_PERMISSION_REQUEST_CODE__NONE; // 0
    List<string> requiredPermissions = new List<string>();

    _bStorageRationaleBefore = ShouldShowRequestPermissionRationale(Android.Manifest.Permission.WriteExternalStorage);
    Permission writeExternalStoragePerm = ApplicationContext.CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage);
    //if(extStoragePerm == Permission.Denied)
    if (writeExternalStoragePerm != Permission.Granted)
    {
        requestCode |= ANDROID_PERMISSION_REQUEST_CODE__SDCARD;
        requiredPermissions.Add(Android.Manifest.Permission.WriteExternalStorage);
    }

    return requiredPermissions;
}

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

        // Android v6 requires explicit permission granting from user at runtime for security reasons
        int requestCode;
        List<string> requiredPermissions = GetRequiredPermissions(out requestCode);
        if (requiredPermissions != null && requiredPermissions.Count > 0)
        {
            if (requestCode >= ANDROID_PERMISSION_REQUEST_CODE__SDCARD)                    
            {
                _savedInstanceState = savedInstanceState;
                RequestPermissions(requiredPermissions.ToArray(), requestCode);
                return;
            }
        }
    }            

    OnCreate2(savedInstanceState);
}

وهو مقتطف من أدناه (للاطلاع على المثال الكامل ، انظر هذه answer )

public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
    switch (requestCode) {
        case PERMISSIONS_REQUEST_EXTERNAL_STORAGE: {
            if (grantResults.length > 0) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    // Denied
                } else {
                    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                        // To what you want
                    } else {
                       // Bob never checked click
                    }
                }
            }
        }
    }
}

لا بد لي من تنفيذ إذن ديناميكي للكاميرا. حيث تحدث 3 حالات ممكنة: 1. السماح ، 2. تم الرفض ، 3. لا تسأل مرة أخرى.

bool bStorage = grantResults[0] == Permission.Granted;
bool bNeverAskForStorage =
    !bStorage && (
        _bStorageRationaleBefore == true  && _bStorageRationaleAfter == false ||
        _bStorageRationaleBefore == false && _bStorageRationaleAfter == false
    );

للإجابة على السؤال بالتحديد ، ماذا يحدث عندما يضغط المستخدم "لا تسأل مرة أخرى"؟

الأسلوب / الوظيفة الغالبة

onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray)

صفيف grantResult يأتي ليكون فارغًا ، بحيث يمكنك القيام بشيء هناك ربما؟ ولكن ليس أفضل الممارسات.

كيفية التعامل مع "لا تسأل مرة أخرى"؟

أنا أعمل مع Fragment ، التي تتطلب إذنًا READ_EXTERNAL_STORAGE.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        when {
            isReadPermissionsGranted() -> {

                /**
                 * Permissions has been Granted
                 */

                getDirectories()
            }

            isPermissionDeniedBefore() -> {

                /**
                 * User has denied before, explain why we need the permission and ask again
                 */

                updateUIForDeniedPermissions()
                checkIfPermissionIsGrantedNow()

            }
            else -> {

                /**
                 * Need to ask For Permissions, First Time
                 */

                checkIfPermissionIsGrantedNow()

                /**
                 * If user selects, "Dont Ask Again" it will never ask again! so just update the UI for Denied Permissions
                 */

                updateUIForDeniedPermissions()

            }
        }
    }

وظائف أخرى تافهة.

// Is Read Write Permissions Granted
fun isReadWritePermissionGranted(context: Context): Boolean {
    return (ContextCompat.checkSelfPermission(
        context as Activity,
        Manifest.permission.READ_EXTERNAL_STORAGE
    ) == PackageManager.PERMISSION_GRANTED) and
            (ContextCompat.checkSelfPermission(
                context,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) == PackageManager.PERMISSION_GRANTED)
}

fun isReadPermissionDenied(context: Context) : Boolean {
    return ActivityCompat.shouldShowRequestPermissionRationale(
        context as Activity,
        PermissionsUtils.READ_EXTERNAL_STORAGE_PERMISSIONS)
}

يمكنك الاستماع جميلة.

مستمع

interface PermissionListener {
    fun onNeedPermission()
    fun onPermissionPreviouslyDenied(numberDenyPermission: Int)
    fun onPermissionDisabledPermanently(numberDenyPermission: Int)
    fun onPermissionGranted()
}

MainClass للحصول على إذن

class PermissionUtil {

    private val PREFS_FILENAME = "permission"
    private val TAG = "PermissionUtil"

    private fun shouldAskPermission(context: Context, permission: String): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val permissionResult = ActivityCompat.checkSelfPermission(context, permission)
            if (permissionResult != PackageManager.PERMISSION_GRANTED) {
                return true
            }
        }
        return false
    }

    fun checkPermission(context: Context, permission: String, listener: PermissionListener) {

        Log.i(TAG, "CheckPermission for $permission")

        if (shouldAskPermission(context, permission)) {

            // Load history permission
            val sharedPreference = context.getSharedPreferences(PREFS_FILENAME, 0)
            val numberShowPermissionDialog = sharedPreference.getInt(permission, 0)

            if (numberShowPermissionDialog == 0) {

                (context as? Activity)?.let {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(it, permission)) {
                        Log.e(TAG, "User has denied permission but not permanently")
                        listener.onPermissionPreviouslyDenied(numberShowPermissionDialog)
                    } else {
                        Log.e(TAG, "Permission denied permanently.")
                        listener.onPermissionDisabledPermanently(numberShowPermissionDialog)
                    }
                } ?: kotlin.run {
                    listener.onNeedPermission()
                }

            } else {
                // Is FirstTime
                listener.onNeedPermission()
            }


            // Save history permission
            sharedPreference.edit().putInt(permission, numberShowPermissionDialog + 1).apply()


        } else {
            listener.onPermissionGranted()
        }

    }
}

تستخدم بهذه الطريقة

      PermissionUtil().checkPermission(this, Manifest.permission.ACCESS_FINE_LOCATION,
                object : PermissionListener {
                    override fun onNeedPermission() {
                        log("---------------------->onNeedPermission")

//                            ActivityCompat.requestPermissions([email protected],
//                                    Array(1) { Manifest.permission.ACCESS_FINE_LOCATION },
//                                    118)

                    }

                    override fun onPermissionPreviouslyDenied(numberDenyPermission: Int) {
                        log("---------------------->onPermissionPreviouslyDenied")
                    }

                    override fun onPermissionDisabledPermanently(numberDenyPermission: Int) {
                        log("---------------------->onPermissionDisabled")
                    }

                    override fun onPermissionGranted() {
                        log("---------------------->onPermissionGranted")
                    }

                })

تخطي onRequestPermissionsResult في النشاط أو شبكة fragmnet

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
 if (requestCode == 118) {
        if (permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            getLastLocationInMap()
        }
        }
    }


إليك طريقة لطيفة وسهلة للتحقق من حالة الأذونات الحالية:

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({GRANTED, DENIED, BLOCKED_OR_NEVER_ASKED })
    public @interface PermissionStatus {}

    public static final int GRANTED = 0;
    public static final int DENIED = 1;
    public static final int BLOCKED_OR_NEVER_ASKED = 2;

    @PermissionStatus 
    public static int getPermissionStatus(Activity activity, String androidPermissionName) {
        if(ContextCompat.checkSelfPermission(activity, androidPermissionName) != PackageManager.PERMISSION_GRANTED) {
            if(!ActivityCompat.shouldShowRequestPermissionRationale(activity, androidPermissionName)){
                return BLOCKED_OR_NEVER_ASKED;
            }
            return DENIED;
        }
        return GRANTED;
    }

تحذير: إرجاع BLOCKED_OR_NEVER_ASKED أول بدء تشغيل للتطبيق ، قبل قبول / رفض المستخدم للإذن من خلال مطالبة المستخدم (على أجهزة sdk 23+)

تحديث:

يبدو أيضًا أن مكتبة دعم Android لديها فئة android.support.v4.content.PermissionChecker متشابهة جدًا والتي تحتوي على checkSelfPermission() والتي تُرجع:

public static final int PERMISSION_GRANTED = 0;
public static final int PERMISSION_DENIED = -1;
public static final int PERMISSION_DENIED_APP_OP = -2;

بمجرد أن يقوم المستخدم بوضع علامة "لا تسأل مرة أخرى" ، لا يمكن عرض السؤال مرة أخرى. ولكن يمكن أن يشرح للمستخدم أنه سبق ورفض الإذن ويجب أن يمنح الإذن في الإعدادات. وأشره إلى الإعدادات ، مع الكود التالي:

@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {

    if (grantResults.length > 0
            && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // now, you have permission go ahead
        // TODO: something

    } else {

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.READ_CALL_LOG)) {
            // now, user has denied permission (but not permanently!)

        } else {

            // now, user has denied permission permanently!

            Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "You have previously declined this permission.\n" +
                "You must approve this permission in \"Permissions\" in the app settings on your device.", Snackbar.LENGTH_LONG).setAction("Settings", new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + BuildConfig.APPLICATION_ID)));

            }
        });
        View snackbarView = snackbar.getView();
        TextView textView = (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
        textView.setMaxLines(5);  //Or as much as you need
        snackbar.show();

        }

    }
    return;
}

جرب مكتبة الأذونات البسيطة هذه. سوف يتعامل مع جميع العمليات المتعلقة بالإذن في 3 خطوات سهلة. أنقذ وقتي. يمكنك إنهاء جميع الأعمال ذات الصلة إذن في 15 دقيقة .

يمكنه التعامل مع الرفض ، يمكنه التعامل مع لا يطلب مرة أخرى ، يمكنه الاتصال بإعدادات التطبيق للحصول على إذن ، يمكنه إعطاء رسالة عقلانية ، يمكن أن يعطي رسالة رفض ، يمكنه إعطاء قائمة بالأذونات المقبولة ، يمكنه إعطاء قائمة بالرفض أذونات وغيرها

https://github.com/ParkSangGwon/TedPermission

الخطوة 1: إضافة التبعية الخاصة بك

dependencies {
     compile 'gun0912.ted:tedpermission:2.1.1'
     //check the above link for latest libraries
}

Step2: اسأل الأذونات

TedPermission.with(this)
    .setPermissionListener(permissionlistener)
    .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
    .setPermissions(Manifest.permission.READ_CONTACTS, Manifest.permission.ACCESS_FINE_LOCATION)
    .check();

الخطوة 3: التعامل مع استجابة إذن

PermissionListener permissionlistener = new PermissionListener() {
    @Override
    public void onPermissionGranted() {
        Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onPermissionDenied(ArrayList<String> deniedPermissions) {
        Toast.makeText(MainActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
    }
};

قد تكون مفيدة لشخص ما: -

ما لاحظته هو أنه في حالة التحقق من إشارة shouldShowRequestPermissionRationale () إلى طريقة رد الاتصال onRequestPermissionsResult () ، فسيظهر حالتان فقط .

الحالة 1: - العودة الحقيقية: - في أي وقت يقوم المستخدم بالنقر فوق "رفض الأذونات" (بما في ذلك أول مرة).

الحالة 2: - إرجاع خطأ: - إذا اختار المستخدم "لا يسأل مرة أخرى".

رابط مثال عمل مفصل


لقد كتبت اختصارًا لطلب الإذن في Android M. هذا الرمز يعالج أيضًا التوافق مع الإصدارات الأقدم من إصدارات Android الأقدم.

يتم استخراج جميع التعليمات البرمجية القبيحة في جزء يرفق وينفصل عن النشاط الذي يطلب الأذونات. يمكنك استخدام PermissionRequestManager النحو التالي:

new PermissionRequestManager()
        // We need a AppCompatActivity here, if you are not using support libraries you will have to slightly change 
        // the PermissionReuqestManager class
        .withActivity(this)

        // List all permissions you need
        .withPermissions(android.Manifest.permission.CALL_PHONE, android.Manifest.permission.READ_CALENDAR)

        // This Runnable is called whenever the request was successfull
        .withSuccessHandler(new Runnable() {
            @Override
            public void run() {
                // Do something with your permissions!
                // This is called after the user has granted all 
                // permissions, we are one a older platform where 
                // the user does not need to grant permissions 
                // manually, or all permissions are already granted

            }
        })

        // Optional, called when the user did not grant all permissions
        .withFailureHandler(new Runnable() {
            @Override
            public void run() {
                // This is called if the user has rejected one or all of the requested permissions
                L.e(this.getClass().getSimpleName(), "Unable to request permission");

            }
        })

        // After calling this, the user is prompted to grant the rights
        .request();

ألقِ نظرة: https://gist.github.com/crysxd/385b57d74045a8bd67c4110c34ab74aa


من فضلك لا ترمي الحجارة على هذا الحل.

هذا يعمل ولكن قليلا "الاختراق".

عند استدعاء requestPermissions ، قم بتسجيل الوقت الحالي.

        mAskedPermissionTime = System.currentTimeMillis();

ثم في onRequestPermissionsResult

إذا لم يتم منح النتيجة ، تحقق من الوقت مرة أخرى.

 if (System.currentTimeMillis() - mAskedPermissionTime < 100)

نظرًا لأن المستخدم لم يتمكن من النقر بسرعة على زر الرفض ، نعلم أنه حدد "عدم السؤال مرة أخرى" لأن رد الاتصال فوري.

استخدم على مسؤوليتك الخاصة.


يجب أن تكون الطريقة shouldShowRequestPermissionRationale() مستخدمًا للتحقق مما إذا كان المستخدم قد حدد الخيار "لم يطلب مرة أخرى" ورفض الإذن. يوجد الكثير من أمثلة التعليمات البرمجية ، لذلك أفضل شرح كيفية استخدامها لهذا الغرض ، لأنني أعتقد أن اسمها وتنفيذه يجعلان الأمر أكثر تعقيدًا من حيث الواقع.

كما هو موضح في https://developer.android.com/training/permissions/requesting.html ، تُرجع هذه الطريقة بشكل صحيح إذا كان الخيار "لا تسأل أبدًا مرة أخرى" مرئيًا أو غير صحيح ؛ لذلك يُرجع الخطأ كاذبة في المرة الأولى التي يتم فيها عرض مربع حوار ، ثم يعود من المرة الثانية صحيحًا ، وفقط إذا رفض المستخدم إذن تحديد الخيار ، فيُرجع خطأً في هذه المرحلة.

لاكتشاف مثل هذه الحالة ، يمكنك إما الكشف عن التسلسل false-true-false ، أو (أكثر بساطة) يمكنك الحصول على علامة تتبع الوقت الأولي الذي يظهر فيه مربع الحوار. بعد ذلك ، تُرجع هذه الطريقة إما صحيحة أو خاطئة ، حيث سيسمح لك الخطأ باكتشاف متى يتم تحديد الخيار.


يمكنك تحديد ذلك عن طريق التحقق مما إذا كان مبرر الإذن سيظهر داخل طريقة رد الاتصال onRequestPermissionsResult() . وإذا وجدت أي أذونات تم تعيينها لعدم طرحها مرة أخرى مطلقًا ، فيمكنك أن تطلب من المستخدمين منح أذونات من الإعدادات.

تنفيذي الكامل سيكون مثل أدناه. إنه يعمل مع طلبات الأذونات الفردية أو المتعددة . استخدم ما يلي أو استخدم مكتبتي مباشرة.

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(permissions.length == 0){
        return;
    }
    boolean allPermissionsGranted = true;
    if(grantResults.length>0){
        for(int grantResult: grantResults){
            if(grantResult != PackageManager.PERMISSION_GRANTED){
                allPermissionsGranted = false;
                break;
            }
        }
    }
    if(!allPermissionsGranted){
        boolean somePermissionsForeverDenied = false;
        for(String permission: permissions){
            if(ActivityCompat.shouldShowRequestPermissionRationale(this, permission)){
                //denied
                Log.e("denied", permission);
            }else{
                if(ActivityCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED){
                    //allowed
                    Log.e("allowed", permission);
                } else{
                    //set to never ask again
                    Log.e("set to never ask again", permission);
                    somePermissionsForeverDenied = true;
                }
            }
        }
        if(somePermissionsForeverDenied){
            final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
            alertDialogBuilder.setTitle("Permissions Required")
                    .setMessage("You have forcefully denied some of the required permissions " +
                            "for this action. Please open settings, go to permissions and allow them.")
                    .setPositiveButton("Settings", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                                    Uri.fromParts("package", getPackageName(), null));
                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        }
                    })
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    })
                    .setCancelable(false)
                    .create()
                    .show();
        }
    } else {
        switch (requestCode) {
            //act according to the request code used while requesting the permission(s).
        }
    }
}

يمكنك التحقق من shouldShowRequestPermissionRationale() في onRequestPermissionsResult() .

https://youtu.be/C8lUdPVSzDk?t=2m23s

تحقق مما إذا كان قد تم منح الإذن أم لا في onRequestPermissionsResult() . إذا لم يكن الأمر كذلك ، تحقق من shouldShowRequestPermissionRationale() .

  1. إذا كانت هذه الطريقة true فقم بإيضاح سبب الحاجة إلى هذا الإذن المحدد. ثم اعتمادا على اختيار المستخدم مرة أخرى requestPermissions() .
  2. إذا ظهر خطأ ، false بإظهار رسالة خطأ مفادها أنه لم يتم منح الإذن والتطبيق لا يمكن المضي قدمًا أو تعطيل ميزة معينة.

أدناه هو رمز عينة.

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case STORAGE_PERMISSION_REQUEST:
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted :)
                downloadFile();
            } else {
                // permission was not granted
                if (getActivity() == null) {
                    return;
                }
                if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    showStoragePermissionRationale();
                } else {
                    Snackbar snackbar = Snackbar.make(getView(), getResources().getString(R.string.message_no_storage_permission_snackbar), Snackbar.LENGTH_LONG);
                    snackbar.setAction(getResources().getString(R.string.settings), new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (getActivity() == null) {
                                return;
                            }
                            Intent intent = new Intent();
                            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
                            intent.setData(uri);
                            OrderDetailFragment.this.startActivity(intent);
                        }
                    });
                    snackbar.show();
                }
            }
            break;
    }
}

على ما يبدو ، خرائط جوجل يفعل هذا بالضبط للحصول على إذن الموقع.


شرح كامل لكل حالة إذن

/**
 *    Case 1: User doesn't have permission
 *    Case 2: User has permission
 *
 *    Case 3: User has never seen the permission Dialog
 *    Case 4: User has denied permission once but he din't clicked on "Never Show again" check box
 *    Case 5: User denied the permission and also clicked on the "Never Show again" check box.
 *    Case 6: User has allowed the permission
 *
 */
public void handlePermission() {
    if (ContextCompat.checkSelfPermission(MainActivity.this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {
        // This is Case 1. Now we need to check further if permission was shown before or not

        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

            // This is Case 4.
        } else {
            // This is Case 3. Request for permission here
        }

    } else {
        // This is Case 2. You have permission now you can do anything related to it
    }
}

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        // This is Case 2 (Permission is now granted)
    } else {
        // This is Case 1 again as Permission is not granted by user

        //Now further we check if used denied permanently or not
        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            // case 4 User has denied permission but not permanently

        } else {
            // case 5. Permission denied permanently.
            // You can open Permission setting's page from here now.
        }

    }
}






android-6.0-marshmallow