Запросить разрешение на Runtime для Android Marshmallow 6.0

Я тестирую свое приложение на Marshmallow 6.0 и оно закрывается для android.permission.READ_EXTERNAL_STORAGE, даже если оно уже определено в Манифесте. Где-то я читал, что если я запрашиваю разрешение во время выполнения, это не заставит закрывать ваше приложение. Я также прочитал этот документ для Android, который предназначен для запроса разрешения во время выполнения.

Итак, я узнал, что мы можем запросить разрешение, подобное приведенному ниже, которое упоминается в документе Android.

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

У приведенного выше кода есть метод обратного вызова onRequestPermissionsResult, который получает результат.

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

     }
}

Мой вопрос: где именно запросить разрешение у пользователя? Должны ли мы использовать запрашивающее разрешение при запуске приложения или мы должны делать это, когда требуется разрешение?

Ответ 1

В общем, запросите необходимые разрешения, как только они вам понадобятся. Таким образом, вы можете сообщить пользователю, почему вам нужно разрешение и разрешить доступ к разрешениям намного проще.

Подумайте о сценариях, когда пользователь отменяет разрешение во время запуска вашего приложения: если вы запрашиваете его при запуске и никогда не проверяете его позже, это может привести к неожиданному поведению или исключениям.

Ответ 2

Это сработало для меня!!! В вашей активности Splash вашего приложения выполните следующие действия:

1) Объявите переменную int для кода запроса,

private static final int REQUEST_CODE_PERMISSION = 2;

2) Объявите массив строк с количеством необходимых вам разрешений,

 String[] mPermission = {Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS,
 Manifest.permission.ACCESS_FINE_LOCATION,
 Manifest.permission.WRITE_EXTERNAL_STORAGE};

3) Далее Проверьте условие разрешения времени выполнения на свой метод onCreate,

try {
            if (ActivityCompat.checkSelfPermission(this, mPermission[0])
                    != MockPackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(this, mPermission[1])
                            != MockPackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(this, mPermission[2])
                            != MockPackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(this, mPermission[3])
                            != MockPackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(this,
                        mPermission, REQUEST_CODE_PERMISSION);

              // If any permission aboe not allowed by user, this condition will execute every tim, else your else part will work
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

4) Теперь объявите метод onRequestPermissionsResult для проверки кода запроса,

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        Log.e("Req Code", "" + requestCode);
        if (requestCode == REQUEST_CODE_PERMISSION) {
            if (grantResults.length == 4 &&
                    grantResults[0] == MockPackageManager.PERMISSION_GRANTED &&
                    grantResults[1] == MockPackageManager.PERMISSION_GRANTED &&
                    grantResults[2] == MockPackageManager.PERMISSION_GRANTED &&
                    grantResults[3] == MockPackageManager.PERMISSION_GRANTED) {

               // Success Stuff here

            }
        }

    }

Ответ 3

По моему мнению, нет ни одного правильного ответа на ваш вопрос. Я настоятельно рекомендую вам посмотреть эту официальную страницу шаблонов разрешений.

Пара предложений, предложенных Google:

"Ваша стратегия разрешений зависит от ясности и важности типа разрешений, который вы запрашиваете. Эти шаблоны предлагают разные способы введения разрешений пользователю".

"Критические разрешения должны запрашиваться заранее. Вторичные разрешения могут запрашиваться в контексте."

"Разрешения, которые менее ясны, должны обеспечивать образование о том, что включает в себя разрешение, независимо от того, выполняются ли они заранее или в контексте".

Эта иллюстрация может дать вам лучшее понимание.

Возможно, самая важная вещь здесь заключается в том, что, спрашивая разрешение на передний план или в контексте, вы всегда должны помнить, что эти разрешения могут быть отменены пользователем в любое время (например, ваше приложение все еще работает в фоновом режиме).

Вы должны убедиться, что ваше приложение не сработало, потому что вы запросили разрешение в самом начале приложения и предположили, что пользователь не изменил его предпочтения в отношении этого разрешения.

Ответ 4

Сделайте это как

private static final int  REQUEST_ACCESS_FINE_LOCATION = 111;

В вашем onCreate

boolean hasPermissionLocation = (ContextCompat.checkSelfPermission(getApplicationContext(),
            Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
    if (!hasPermissionLocation) {
        ActivityCompat.requestPermissions(ThisActivity.this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_ACCESS_FINE_LOCATION);
    }

затем проверьте результат

   @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
    {

        case REQUEST_ACCESS_FINE_LOCATION: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                Toast.makeText(ThisActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();

                //reload my activity with permission granted
                finish();
                startActivity(getIntent());

            } else
            {
                Toast.makeText(ThisActivity.this, "The app was not allowed to get your location. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            }
        }

    }

}

Ответ 5

Для запроса разрешения на запуск я использую Библиотека GitHub

Добавить библиотеку в файл Build.gradle

dependencies {
     compile 'gun0912.ted:tedpermission:1.0.3'
}

Создайте активность и добавьте PermissionListener

public class MainActivity extends AppCompatActivity{

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);



    PermissionListener permissionlistener = new PermissionListener() {
        @Override
        public void onPermissionGranted() {
            Toast.makeText(RationaleDenyActivity.this, "Permission Granted", Toast.LENGTH_SHORT).show();
            //Camera Intent and access Location logic here
        }

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


    new TedPermission(this)
            .setPermissionListener(permissionlistener)
            .setRationaleTitle(R.string.rationale_title)
            .setRationaleMessage(R.string.rationale_message) // "we need permission for access camera and find your location"
            .setDeniedTitle("Permission denied")
            .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
            .setGotoSettingButtonText("Settings")
            .setPermissions(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .check();
   }
}

string.xml

<resources>

    <string name="rationale_title">Permission required</string>
    <string name="rationale_message">we need permission for read <b>camera</b> and find your <b>location</b></string>

</resources>

Ответ 6

    Android Easy Runtime Permissions with Dexter:
    1. Dexter Permissions Library

    To get started with Dexter, add the dependency in your build.gradle

    dependencies {
        // Dexter runtime permissions
        implementation 'com.karumi:dexter:4.2.0'
    }

    1.1 Requesting Single Permission
    To request a single permission, you can use withPermission() method by passing the required permission. You also need a PermissionListener callback to receive the state of the permission.

    > onPermissionGranted() will be called once the permission is granted.

    > onPermissionDenied() will be called when the permission is denied. Here you can check whether the permission is permanently denied by using response.isPermanentlyDenied() condition.

    The below code requests CAMERA permission.

Dexter.withActivity(this)
                .withPermission(Manifest.permission.CAMERA)
                .withListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted(PermissionGrantedResponse response) {
                        // permission is granted, open the camera
                    }

                    @Override
                    public void onPermissionDenied(PermissionDeniedResponse response) {
                        // check for permanent denial of permission
                        if (response.isPermanentlyDenied()) {
                            // navigate user to app settings
                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                }).check();

1.2 Requesting Multiple Permissions
To request multiple permissions at the same time, you can use withPermissions() method. Below code requests STORAGE and LOCATION permissions.

Dexter.withActivity(this)
                .withPermissions(
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        // check if all permissions are granted
                        if (report.areAllPermissionsGranted()) {
                            // do you work now
                        }

                        // check for permanent denial of any permission
                        if (report.isAnyPermissionPermanentlyDenied()) {
                            // permission is denied permenantly, navigate user to app settings
                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                })
                .onSameThread()
                .check();

Ответ 7

Хорошее объяснение и HowTo можно найти здесь:

https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en

Я написал этот код, чтобы проверить и запросить разрешения во время выполнения в BaseActivity.class, который является родителем для каждого другого Activity.class, который я реализовал:

public static final int PERMISSION_REQUEST = 42;
public static final int MULTIPLE_PERMISSION_REQUEST = 43;

//Marshmallow Permission Model
public boolean requestPermission(String permission /* Manifest.permission...*/) {
    if (ContextCompat.checkSelfPermission(this,
            permission) != PackageManager.PERMISSION_GRANTED) {
        if (Utils.hasMarshmallow())
            ActivityCompat.requestPermissions(this,
                    new String[]{permission}, PERMISSION_REQUEST
            );
        else {
            requestPermissions(new String[]{permission},
                    PERMISSION_REQUEST);
        }
        return false;
    } else {
        return true;
    }
}

public boolean requestPermission(String... permissions) {
    final List<String> permissionsList = new ArrayList<String>();

    for (String perm : permissions) {
        addPermission(permissionsList, perm);
    }

    if (permissionsList.size() > 0) {
        if (Utils.hasMarshmallow())
            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                    MULTIPLE_PERMISSION_REQUEST);
        else
            ActivityCompat.requestPermissions(this, permissionsList.toArray(new String[permissionsList.size()]),
                    MULTIPLE_PERMISSION_REQUEST);
        return false;
    } else
        return true;
}


private boolean addPermission(List<String> permissionsList, String permission) {
    if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
        permissionsList.add(permission);
        // Check for Rationale Option
        if (Utils.hasMarshmallow())
            if (!shouldShowRequestPermissionRationale(permission))
                return false;
    }
    return true;
}

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST:
        case MULTIPLE_PERMISSION_REQUEST: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

Пример простого вызова:

activity.requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE);

Результат возврата даст вам знать, предоставлено ли разрешение или нет.

Ответ 8

, вызывающий эту функцию, мы можем разрешить пользователю открывать диалог для запроса разрешения разрешить камеру и записывать аудио.

    if ( ActivityCompat.shouldShowRequestPermissionRationale (this, Manifest.permission.CAMERA) ||
            ActivityCompat.shouldShowRequestPermissionRationale (this,
                    Manifest.permission.RECORD_AUDIO) ) {
        Toast.makeText (this,
                R.string.permissions_needed,
                Toast.LENGTH_LONG).show ();
    } else {
        ActivityCompat.requestPermissions (
                this,
                new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
                CAMERA_MIC_PERMISSION_REQUEST_CODE);
    }

Ответ 9

https://material.io/guidelines/patterns/permissions.html Эта ссылка даст вам разные типы сценариев, где могут быть заданы разрешения. Выберите в соответствии с вашими потребностями.

Ответ 10

Мне нравится короткий код. Я использую RxPermission для разрешений.

RxPermission - лучшая библиотека, которая делает код разрешения неожиданным всего в 1 строку.

RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA,
         Manifest.permission.READ_PHONE_STATE) // ask single or multiple permission once
.subscribe(granted -> {
    if (granted) {
       // All requested permissions are granted
    } else {
       // At least one permission is denied
    }
});

добавить в build.gradle

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

dependencies {
    implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
    implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}

Разве это не легко?

Ответ 11

if ( ActivityCompat.shouldShowRequestPermissionRationale (this, Manifest.permission.CAMERA) ||
                ActivityCompat.shouldShowRequestPermissionRationale (this,
                        Manifest.permission.RECORD_AUDIO) ) {
            Toast.makeText (this,
                    R.string.permissions_needed,
                    Toast.LENGTH_LONG).show ();
        } else {
            ActivityCompat.requestPermissions (
                    this,
                    new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
                    CAMERA_MIC_PERMISSION_REQUEST_CODE);
        }