Поиск по сайту:

Пример разрешений во время выполнения Android


Добро пожаловать в пример разрешений среды выполнения Android. С введением Android 6.0 Marshmallow Google изменил способ обработки разрешений приложением. В этом руководстве мы рассмотрим новые разрешения среды выполнения Android и способы их обработки. Если не обращаться должным образом, это может привести к сбою приложения.

Что такое разрешения среды выполнения Android?

С появлением Android 6.0 (SDK 23) у пользователей запрашиваются определенные разрешения во время выполнения, когда они становятся необходимыми для использования. Итак, первый вопрос, который приходит нам на ум: будут ли старые приложения работать на Android Marshmallow? Ответ «да», если targetSdkVersion равен 22 или меньше. Таким образом, разрешения среды выполнения Android поддерживают обратную совместимость. Теперь это не означает, что мы можем работать со старой моделью разрешений, установив версию sdk на 22. Пользователь, использующий Marshmallow, может отозвать опасные разрешения (мы обсудим опасные и обычные разрешения позже) в меню «Настройки» -> «Приложения». -> Разрешения. В случае, если мы попытаемся вызвать какую-либо функцию, требующую разрешения, которое пользователь еще не предоставил, функция внезапно выдаст исключение (java.lang.SecurityException), что приведет к сбою приложения. Следовательно, нам нужно реализовать эту новую модель разрешений Android в нашем приложении.

Опасные и нормальные разрешения для Android

Android определяет некоторые разрешения как опасные, а некоторые — как обычные. Общим для обоих типов является то, что они должны быть определены в файле манифеста. Начиная с Android 6.0 во время выполнения проверяются только опасные разрешения, а обычные разрешения — нет. Примером обычного разрешения является android.permission.INTERNET. Опасные разрешения сгруппированы по категориям, чтобы пользователю было легче понять, что они разрешают делать приложению. Если пользователь принимает одно разрешение в группе/категории, он принимает всю группу. Примером опасного разрешения являются android.permission.FINE_LOCATION и android.permission.COARSE_LOCATION. Включение любого из разрешений местоположения включает все.

Запрос разрешений среды выполнения Android

Метод requestPermissions(String[] разрешения, int requestCode); — это общедоступный метод, который используется для запроса опасных разрешений. Мы можем запросить несколько опасных разрешений, передав массив строк разрешений. Примечание. Разрешения Android, принадлежащие двум разным группам, будут предлагать пользователю отдельный диалог для каждой из них. Если они принадлежат к одной и той же группе, будет отображаться только одно диалоговое окно. Результаты запросов будут переданы в метод onRequestPermissionResult. Пример: допустим, мы хотим получить доступ к камере и местоположению в нашем приложении. Оба разрешения опасны. Мы будем отображать запрос на доступ к этим разрешениям при запуске приложения. Давайте добавим разрешения в массив строк и вызовем requestPermissions, как показано ниже:

String[] perms = {"android.permission.FINE_LOCATION", "android.permission.CAMERA"};

int permsRequestCode = 200; 
requestPermissions(perms, permsRequestCode);

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

    switch(permsRequestCode){

        case 200:

            boolean locationAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
            boolean cameraAccepted = grantResults[1]==PackageManager.PERMISSION_GRANTED;

            break;

    }

}

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

checkSelfPermission(String perm);

Он возвращает целочисленное значение PERMISSION_GRANTED или PERMISSION_DENIED. Примечание. Если пользователь отклоняет разрешение, которое имеет решающее значение для приложения, то shouldShowRequestPermissionRationale(Stringразрешение); используется для описания необходимости разрешения пользователю. Давайте разработаем приложение, которое проверяет наличие разрешения. Если нет, то он запрашивается во время выполнения.

Структура проекта разрешений среды выполнения Android

Код разрешений среды выполнения Android

content_main.xml содержит две кнопки для проверки и запроса разрешений.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.journaldev.runtimepermissions.MainActivity"
    tools:showIn="@layout/activity_main">
    <Button
        android:id="@+id/check_permission"
        android:layout_width="match_parent"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content"
        android:text="Check Permission"/>
    <Button
        android:id="@+id/request_permission"
        android:layout_below="@+id/check_permission"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Request Permission"/>
</RelativeLayout>

MainActivity.java определяется, как показано ниже.

package com.journaldev.runtimepermissions;

import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

import android.view.View;
import android.widget.Button;

import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.CAMERA;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int PERMISSION_REQUEST_CODE = 200;
    private View view;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Button check_permission = (Button) findViewById(R.id.check_permission);
        Button request_permission = (Button) findViewById(R.id.request_permission);
        check_permission.setOnClickListener(this);
        request_permission.setOnClickListener(this);


    }


    @Override
    public void onClick(View v) {

        view = v;

        int id = v.getId();
        switch (id) {
            case R.id.check_permission:
                if (checkPermission()) {

                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

                } else {

                    Snackbar.make(view, "Please request permission.", Snackbar.LENGTH_LONG).show();
                }
                break;
            case R.id.request_permission:
                if (!checkPermission()) {

                    requestPermission();

                } else {

                    Snackbar.make(view, "Permission already granted.", Snackbar.LENGTH_LONG).show();

                }
                break;
        }

    }

    private boolean checkPermission() {
        int result = ContextCompat.checkSelfPermission(getApplicationContext(), ACCESS_FINE_LOCATION);
        int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);

        return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED;
    }

    private void requestPermission() {

        ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_CODE:
                if (grantResults.length > 0) {

                    boolean locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                    boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;

                    if (locationAccepted && cameraAccepted)
                        Snackbar.make(view, "Permission Granted, Now you can access location data and camera.", Snackbar.LENGTH_LONG).show();
                    else {

                        Snackbar.make(view, "Permission Denied, You cannot access location data and camera.", Snackbar.LENGTH_LONG).show();

                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
                                showMessageOKCancel("You need to allow access to both the permissions",
                                        new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                                    requestPermissions(new String[]{ACCESS_FINE_LOCATION, CAMERA},
                                                            PERMISSION_REQUEST_CODE);
                                                }
                                            }
                                        });
                                return;
                            }
                        }

                    }
                }


                break;
        }
    }


    private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(MainActivity.this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", null)
                .create()
                .show();
    }

}

Примечание. Добавьте разрешения, которые должны проверяться во время выполнения, в файле манифеста над тегом приложения как;

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

В приведенном выше коде проверяются и запрашиваются два разрешения: CAMERA и LOCATION. Импорт полного имени класса статического разрешения позволяет нам написать только объект PERMISSION вместо полного пути. checkPermission() вызывает checkSelfPermission для каждого из разрешений. requestPermission() вызывает ActivityCompat.requestPermissions(this, new String[]{ACCESS_FINE_LOCATION, CAMERA}, PERMISSION_REQUEST_CODE);. onRequestPermissionsResult проверяет, предоставлены ли разрешения или нет. В нашем коде, если оба разрешения не предоставлены, появляется диалоговое окно с предупреждением, показывающее обязательную необходимость запроса разрешений. Для этого вызывается shouldShowRequestPermissionRationale(Stringразрешение), который вызывает диалоговое окно предупреждения, показывающее необходимость разрешений. Вы можете отозвать разрешения вручную в меню «Настройки» -> «Приложения» -> «Разрешения». Примечание. Методы, специфичные для разрешения времени выполнения, доступны только с API 23. Следовательно, для каждого из методов проверяется следующее условие:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)

Скачать пример проекта разрешения среды выполнения Android

Ссылка: https://developer.android.com/training/permissions/requesting.html