Как мы различаем никогда спрошенный от выяснения остановки в полномочиях M Android во время выполнения?

Когда дело доходит до полномочий времени выполнения Предварительного просмотра Разработчика M, согласно Google:

  1. Если Вы никогда не просили определенное разрешение прежде, просто попросите его

  2. Если бы Вы спросили прежде, и пользователь сказал "нет", и пользователь затем пытается делать что-то, чему нужно отклоненное разрешение, то необходимо предложить пользователю объяснять, почему Вам нужно разрешение, прежде чем Вы продолжите запрашивать разрешение снова

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

Однако у нас только есть один метод, shouldShowRequestPermissionRationale(), возврат a boolean, и у нас есть три состояния. Нам нужен способ отличить никогда спрошенное состояние от спрашивающего остановку состояния, поскольку мы добираемся false от shouldShowRequestPermissionRationale() для обоих.

Для полномочий, требуемых на первом показе приложения, это не большая проблема. Существует много рецептов для определения, что это - вероятно, первый показ Вашего приложения (например, boolean значение в SharedPreferences), и таким образом, Вы предполагаете, что, если это - первый показ Вашего приложения, Вы находитесь в никогда спрошенном состоянии.

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

В тех случаях мы, как предполагается, отслеживаем, попросили ли мы разрешение сами? Или есть ли что-то в API Android M, который я пропускаю, который говорит нам, спросили ли мы прежде или нет?

62
задан 10 August 2015 в 23:48

5 ответов

После попытки всего ответа здесь и некоторого другого сообщения по Интернету. Я узнал это, я должен использовать sharedPreference isLocationPermissionDialogShown (ложь по умолчанию) и каждая вещь работы согласно ожидаемому.

  1. , Если в первый раз, который спрашивают относительно разрешения. В этом случае shouldShowRequestPermissionRationale возвраты false и isLocationPermissionDialogShown также false
  2. Во второй раз shouldShowRequestPermissionRationale возврат true и при показе диалогового окна мы устанавливаем isLocationPermissionDialogShown на true. и когда мы проверяем условие, оба будут true
  3. , Каждый Раз до Никогда Не Спрашивает Снова отмеченный shouldShowRequestPermissionRationale возврат true и isLocationPermissionDialogShown возвраты true
  4. , Если Никогда Не Спрашивают Снова отмеченный shouldShowRequestPermissionRationale возврат false и isLocationPermissionDialogShown возвраты true. Который является тем, в чем мы нуждаемся.

проверьте рабочий пример.

public class MainActivity extends AppCompatActivity {
    SharedPreferences sharedPreferences;
    String locationPermission;
    String prefLocationPermissionKey = "isLocationPermissionDialogShown";
    private final int PERMISSION_REQUEST_CODE_LOCATION = 1001;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        locationPermission = Manifest.permission.ACCESS_FINE_LOCATION;
        sharedPreferences = getSharedPreferences("configuration", MODE_PRIVATE);

        //check for android version
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            //Check for permission
            if (checkSelfPermission(locationPermission) != PackageManager.PERMISSION_GRANTED) {
                //check if clarification dialog should be shown.
                if (shouldShowRequestPermissionRationale(locationPermission)) {
                    showClarificationDialog(locationPermission, PERMISSION_REQUEST_CODE_LOCATION);
                } else  {
                    requestPermissions(new String[] { locationPermission}, PERMISSION_REQUEST_CODE_LOCATION);
                }
            } else {
                Log.d("nets-debug", "permission already grranted");
            }
        }

    }

    @Override
    @TargetApi(Build.VERSION_CODES.M)
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
            //for location permission
            if (requestCode == PERMISSION_REQUEST_CODE_LOCATION) {
                boolean isLocationPermissionDialogShown = sharedPreferences.getBoolean(prefLocationPermissionKey, false);

                if (!shouldShowRequestPermissionRationale(locationPermission) && isLocationPermissionDialogShown) {
                    // user selected Never Ask Again. do something
                    Log.d("nets-debug", "never ask again");
                } else {
                    // all other conditions like first time asked, previously denied etc are captured here and can be extended if required.
                    Log.d("nets-debug", "all other cases");
                }
            }

        }

    }

    @TargetApi(Build.VERSION_CODES.M)
    public void showClarificationDialog(final String permission, final int requestCode) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Permission Required");
        builder.setMessage("Please grant Location permission to use all features of this app");
        builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putBoolean(prefLocationPermissionKey, true);
                editor.apply();
                requestPermissions(new String[] {permission}, requestCode);
            }
        });
        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(getApplicationContext(), "This permission required", Toast.LENGTH_LONG).show();
            }
        });
        builder.create().show();
    }

}

Hope это поможет.

1
ответ дан 31 October 2019 в 14:20
<час>

ПОЭТОМУ НАКОНЕЦ МОЕ ВРЕМЯ НАСТУПИЛ ДЛЯ ОТВЕТА НА ВОПРОС С <часа> COMMONSWARE

Бизнес-flow:-

1. , Когда пользователь нажмет на "deny permission" впервые, я покажу диалоговое окно объяснения для объяснения необходимости разрешения. Затем, если пользователь нажмет на кнопку "отмены" на диалоговом окне объяснения, то я покажу сообщение показа тоста, "Дайте разрешение получить местоположение".

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

3. , Таким образом, с этого времени диалоговое окно разрешения не покажут. Также диалоговое окно объяснения не покажут.

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

Проверка code:-

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)){
                AlertDialogHelper.showDialogWithYesNoCallback(mContext, getString(R.string.confirm), getString(R.string.please_give_permission_to_get_location), new onItemClickReturnBoolean() {
                    @Override
                    public void onItemClick(Boolean status) {
                        if(status){
                            ActivityCompat.requestPermissions(SplashScreenActivity.this,permissions,AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE);
                        }
                        else{
                            ShowToast.showShortToast(SplashScreenActivity.this,getString(R.string.please_give_permission_to_get_location));
                            finish();
                        }
                    }
                });
            }
            else{
                ActivityCompat.requestPermissions(this,permissions,AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE);
            }
        }
        else{
            gettingLocationAfterPermissionGranted();
        }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode == AppConfig.FINE_LOCATION_PERMISSION_REQUEST_CODE){
            if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
                gettingLocationAfterPermissionGranted();
            }
            else{
                if(ActivityCompat.shouldShowRequestPermissionRationale(SplashScreenActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)){
                    ShowToast.showShortToast(this,getString(R.string.please_give_permission_to_get_location));
                }
                else{
                    ShowToast.showShortToast(this,getString(R.string.please_give_location_permission_from_app_settings));
                }
                finish();
            }
        }
    }

этот репозиторий: https://<час> github.com/debChowdhury/PermissionHelperEasy

Easy peasy

<час>
0
ответ дан 31 October 2019 в 14:20

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

public boolean mPermissionRationaleDialogShown = false;

public void checkPermission() {
    if (ContextCompat.checkSelfPermission(this, "PermissionName")
            != PackageManager.PERMISSION_GRANTED) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, "PermissionName")) {
            showPermissionRequiredDialog();
        } else {
            askPermission();
        }
    } else {
       // Permission Granted
    }
}

public void askPermission() {
    ActivityCompat.requestPermissions(this,
            new String[]{"PermissionName"}, permissionRequestCode);
}

public void showPermissionRequiredDialog() {
    mPermissionRationaleDialogShown = true;
    // Dialog to show why permission is required
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == PERMISSION_REQUEST_CODE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Permission Granted
        } else {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, "PermissionName")
                    && !mPermissionRationaleDialogShown) {
                // Permission dialog was shown for first time
            } else if (ActivityCompat.shouldShowRequestPermissionRationale(this, "PermissionName")
                    && mPermissionRationaleDialogShown){
                // User deny permission without Never ask again checked
            } else if (!ActivityCompat.shouldShowRequestPermissionRationale(this, PERMISSION_READ_EXTERNAL)
                    && mPermissionRationaleDialogShown) {
                // User has checked Never ask again during this permission request
            } else {
                // No permission dialog shown to user has user has previously checked Never ask again. Here we can show dialog to open setting screen to change permission
            }
        }
    } else {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}
1
ответ дан 31 October 2019 в 14:20

Я знаю, что отправляю очень поздно, но подробный пример может быть полезным для кого-то.

то, Что я заметил, если мы проверяем shouldShowRequestPermissionRationale () флаг в к onRequestPermissionsResult () метод обратного вызова, он показывает только два состояния.

1:-возврат состояния true: - Любой пользователь времени нажимает полномочия Deny (включая самый первый раз.

ложь 2:-возвратов состояния:-, если пользователь выбирает s, “never спрашивает снова.

Вот является пример с несколькими разрешением request:-

, для приложения нужны 2 полномочий при запуске. SEND_SMS и ACCESS_FINE_LOCATION (оба упоминаются в manifest.xml).

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

enter image description here

public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if(checkAndRequestPermissions()) {
        // carry on the normal flow, as the case of  permissions  granted.
    }
}

private  boolean checkAndRequestPermissions() {
    int permissionSendMessage = ContextCompat.checkSelfPermission(this,
            Manifest.permission.SEND_SMS);
    int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
    List<String> listPermissionsNeeded = new ArrayList<>();
    if (locationPermission != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
    }
    if (permissionSendMessage != PackageManager.PERMISSION_GRANTED) {
        listPermissionsNeeded.add(Manifest.permission.SEND_SMS);
    }
    if (!listPermissionsNeeded.isEmpty()) {
        ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),REQUEST_ID_MULTIPLE_PERMISSIONS);
        return false;
    }
    return true;
}

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

необходимо проверить значение shouldShowRequestPermissionRationale () флаг в onRequestPermissionsResult () метод обратного вызова.

существует только два cases: -

Случай 1: - Любой пользователь времени нажимает полномочия Deny (включая самый первый раз), это возвратит true. Таким образом, когда пользователь отклоняет, мы можем показать больше объяснения и продолжать спрашивать снова.

Случай 2: - Только если пользователь выбирает “never, спрашивает again”, он возвратит false. В этом случае мы можем продолжить ограниченную функциональность и направить пользователя для активации полномочий от настроек для большего количества технических возможностей, или мы можем закончить установку, если полномочия тривиальны для приложения.

СЛУЧАЙ - 1

Case - 1

СЛУЧАЙ - 2

Case - 2

@Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        Log.d(TAG, "Permission callback called-------");
        switch (requestCode) {
            case REQUEST_ID_MULTIPLE_PERMISSIONS: {

                Map<String, Integer> perms = new HashMap<>();
                // Initialize the map with both permissions
                perms.put(Manifest.permission.SEND_SMS, PackageManager.PERMISSION_GRANTED);
                perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
                // Fill with actual results from user
                if (grantResults.length > 0) {
                    for (int i = 0; i < permissions.length; i++)
                        perms.put(permissions[i], grantResults[i]);
                    // Check for both permissions
                    if (perms.get(Manifest.permission.SEND_SMS) == PackageManager.PERMISSION_GRANTED
                            && perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                        Log.d(TAG, "sms & location services permission granted");
                        // process the normal flow
                        //else any one or both the permissions are not granted
                    } else {
                            Log.d(TAG, "Some permissions are not granted ask again ");
                            //permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
//                        // shouldShowRequestPermissionRationale will return true
                            //show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
                            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.SEND_SMS) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
                                showDialogOK("SMS and Location Services Permission required for this app",
                                        new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                switch (which) {
                                                    case DialogInterface.BUTTON_POSITIVE:
                                                        checkAndRequestPermissions();
                                                        break;
                                                    case DialogInterface.BUTTON_NEGATIVE:
                                                        // proceed with logic by disabling the related features or quit the app.
                                                        break;
                                                }
                                            }
                                        });
                            }
                            //permission is denied (and never ask again is  checked)
                            //shouldShowRequestPermissionRationale will return false
                            else {
                                Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
                                        .show();
    //                            //proceed with logic by disabling the related features or quit the app.
                            }
                    }
                }
            }
        }

    }

    private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
        new AlertDialog.Builder(this)
                .setMessage(message)
                .setPositiveButton("OK", okListener)
                .setNegativeButton("Cancel", okListener)
                .create()
                .show();
    }
65
ответ дан 31 October 2019 в 14:20

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

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

    public static final int GRANTED = 0;
    public static final int DENIED = 1;
    public static final int BLOCKED = 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;
            }
            return DENIED;
        }
        return GRANTED;
    }

Протест: возвраты ЗАБЛОКИРОВАЛИСЬ, первое приложение запускаются, прежде чем пользователь принял/отклонил разрешение посредством пользовательской подсказки (на sdk 23 + устройства)

, я также использовал, это ответило здесь.

-3
ответ дан 31 October 2019 в 14:20

Другие вопросы по тегам:

Похожие вопросы: