Разрешения на выполнение приложений для 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.
    }
}

Что такое "MY_PERMISSIONS_REQUEST_READ_CONTACTS" в этом примере? Он говорит, что это константа int, определяемая приложением, но означает ли это, что я должен создать Constants.java и объявить открытый static int? Каким должно быть значение?

В других примерах я вижу, что люди используют 1 здесь, или 0 или 0xFFEEDDCC, но я не могу найти объяснения, что это такое. Может кто-нибудь объяснить мне, что нужно здесь и почему? (В моем случае мне нужно убедиться, что у приложения есть разрешение на доступ к прекрасному местоположению)

Документация ActivityCompat гласит: "Код запроса конкретного приложения соответствует результату, указанному в onRequestPermissionsResult"? Это не помогает мне.

Ответ 1

Что такое "MY_PERMISSIONS_REQUEST_READ_CONTACTS" в этом примере?

Это int, чтобы связать конкретный вызов requestPermissions() с соответствующим обратным вызовом onRequestPermissionsResult().

Под обложками requestPermissions() используется startActivityForResult(); этот int выполняет ту же роль, что и в startActivityForResult().

означает ли это, что я должен создать Constants.java и объявить открытый static int?

Я бы просто сделал это private static final int в активности. Но вы можете объявить его там, где хотите.

Каким должно быть значение?

Кажется, я помню, что он должен быть ниже 0x8000000, но в противном случае он может быть любым, что вы хотите. Значение, которое вы используете для каждого вызова requestPermissions() в действии, должно иметь отличный int, но фактические цифры не имеют значения.

Если ваша активность имеет только один вызов requestPermissions(), значение int действительно не имеет значения. Но многие приложения будут иметь несколько вызовов requestPermissions() в активности. В этом случае разработчику может понадобиться знать в onRequestPermissionsResult(), для чего этот запрос является результатом.

Ответ 2

Посмотрите чуть дальше в документации в разделе "Обратиться к запросу запроса разрешений", и вы увидите его цель.

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

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // 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
    }
}

Поскольку константа используется вами, вы можете дать ей любое значение, которое вам нравится, как public static final int. Каждое запрашиваемое разрешение требует своей постоянной.

Ответ 3

Я просмотрел все ответы, но не удовлетворил свой точный необходимый ответ, поэтому вот пример, который я написал и отлично работает, даже если пользователь нажимает флажок Больше не спрашивать.

  1. Создайте метод, который будет вызываться, когда вы хотите запросить разрешение во время выполнения, например readContacts() или вы также можете использовать openCamera() как показано ниже:

    private void readContacts() {
        if (!askContactsPermission()) {
            return;
        } else {
            queryContacts();
        } }
    

Теперь нам нужно сделать askContactsPermission(), вы также можете назвать его как askCameraPermission() или любое askCameraPermission() разрешение, которое вы собираетесь запрашивать.

    private boolean askContactsPermission() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        return true;
    }
    if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
        return true;
    }
    if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
        Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
                .setAction(android.R.string.ok, new View.OnClickListener() {
                    @Override
                    @TargetApi(Build.VERSION_CODES.M)
                    public void onClick(View v) {
                        requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
                    }
                }).show();
    } else if (contactPermissionNotGiven) {
        openPermissionSettingDialog();
    } else {
        requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
        contactPermissionNotGiven = true;

    }
    return false;
}

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

    private View parentLayout;
    private boolean contactPermissionNotGiven;;


/**
 * Id to identity READ_CONTACTS permission request.
 */
private static final int REQUEST_READ_CONTACTS = 0;

Теперь последний шаг для переопределения метода onRequestPermissionsResult как показано ниже:

/**
 * Callback received when a permissions request has been completed.
 */
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    if (requestCode == REQUEST_READ_CONTACTS) {
        if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            queryContacts();
        }
    }
}

Здесь мы закончили с разрешениями RunTime, надстройкой является openPermissionSettingDialog() который просто открывает экран настроек, если пользователь навсегда отключил разрешение, установив флажок "Больше не спрашивать". ниже метод:

    private void openPermissionSettingDialog() {
    String message = getString(R.string.message_permission_disabled);
    AlertDialog alertDialog =
            new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
                    .setMessage(message)
                    .setPositiveButton(getString(android.R.string.ok),
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    Intent intent = new Intent();
                                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                    Uri uri = Uri.fromParts("package", getPackageName(), null);
                                    intent.setData(uri);
                                    startActivity(intent);
                                    dialog.cancel();
                                }
                            }).show();
    alertDialog.setCanceledOnTouchOutside(true);
}

Что мы пропустили? 1. Определение используемых строк в strings.xml

<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
    <string name="message_permission_disabled">You have disabled the permissions permanently,
        To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
        pressing OK you will be navigated to Settings screen</string>
  1. Инициализация parentLayout переменной внутри onCreate метода

    parentLayout = findViewById (R.id.content);

  2. Определение необходимого разрешения в AndroidManifest.xml

<uses-permission android:name="android.permission.READ_CONTACTS" />
  1. Метод queryContacts, основанный на вашей потребности или разрешении времени выполнения, вы можете вызвать свой метод, до которого это permission было необходимо. в моем случае я просто использую загрузчик, чтобы получить контакт, как показано ниже:

    private void queryContacts() {
    getLoaderManager().initLoader(0, null, this);}
    

Это прекрасно работает счастливое кодирование :)

Ответ 4

public class SplashActivity extends RuntimePermissionsActivity {


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    SplashActivity.super.requestAppPermissions(new
                    String[]{android.Manifest.permission.READ_PHONE_STATE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE}, R.string.app_name
            , 20);

}

@Override
public void onPermissionsGranted(int requestCode) {


    try {
        TelephonyManager tele = (TelephonyManager) getApplicationContext()
                .getSystemService(Context.TELEPHONY_SERVICE);

        String imei =tele.getDeviceId()
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public abstract class RuntimePermissionsActivity extends AppCompatActivity {
private SparseIntArray mErrorString;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mErrorString = new SparseIntArray();
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    int permissionCheck = PackageManager.PERMISSION_GRANTED;
    for (int permission : grantResults) {
        permissionCheck = permissionCheck + permission;
    }
    if ((grantResults.length > 0) && permissionCheck == PackageManager.PERMISSION_GRANTED) {
        onPermissionsGranted(requestCode);
    } else {

        finish();

    }
}

public void requestAppPermissions(final String[] requestedPermissions,
                                  final int stringId, final int requestCode) {
    mErrorString.put(requestCode, stringId);
    int permissionCheck = PackageManager.PERMISSION_GRANTED;
    boolean shouldShowRequestPermissionRationale = false;
    for (String permission : requestedPermissions) {
        permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
        shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale || ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
    }
    if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
        if (shouldShowRequestPermissionRationale) {
            ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
            /*Snackbar.make(findViewById(android.R.id.content), stringId,
                    Snackbar.LENGTH_INDEFINITE).setAction("GRANT",
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
                        }
                    }).show();*/
        } else {
            ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
        }
    } else {
        onPermissionsGranted(requestCode);
    }
}

public abstract void onPermissionsGranted(int requestCode);

}