web-dev-qa-db-ja.com

checkSelfPermissionメソッドがtargetSdkVersion 22で機能しない

CheckSelfPermissionメソッドは期待どおりに機能せず、Android 6.0(Marshmallow)で常にゼロを返します。ターゲットSDKが22であり、ネットワーク接続にhttpクライアントを使用しているためです。以下はコードスニペットです。

private void insertDummyContactWrapper() {
    List<String> permissionsNeeded = new ArrayList<String>();

    final List<String> permissionsList = new ArrayList<String>();
    if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
        permissionsNeeded.add("GPS");
    if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
        permissionsNeeded.add("Read Contacts");
    if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
        permissionsNeeded.add("Write Contacts");

    if (permissionsList.size() > 0) {
        if (permissionsNeeded.size() > 0) {
            // Need Rationale
            String message = "You need to grant access to " + permissionsNeeded.get(0);
            for (int i = 1; i < permissionsNeeded.size(); i++)
                message = message + ", " + permissionsNeeded.get(i);
            showMessageOKCancel(message,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                                    REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
                        }
                    });
            return;
        }
        requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
        return;
    }

    insertDummyContact();
}

@TargetApi(Build.VERSION_CODES.M)
private boolean addPermission(List<String> permissionsList, String permission) {
    if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
        permissionsList.add(permission);
        // Check for Rationale Option
        if (!shouldShowRequestPermissionRationale(permission)) return false;
    }
    return true;
}

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

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {
            Map<String, Integer> perms = new HashMap<String, Integer>();
            // Initial
            perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.WRITE_CONTACTS, PackageManager.PERMISSION_GRANTED);
            // Fill with results
            for (int i = 0; i < permissions.length; i++)
                perms.put(permissions[i], grantResults[i]);
            // Check for ACCESS_FINE_LOCATION
            if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
                // All Permissions Granted
                insertDummyContact();
            } else {
                // Permission Denied
                Toast.makeText(MainActivity.this, "Some Permission is Denied", Toast.LENGTH_SHORT)
                        .show();
            }
        }
        break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}"
39
Mithun S

メソッドContext#checkSelfPermission(String)がAPI 23に追加されました。また、API 23の下では、許可が常に付与されるため、意味がありません。権限を処理する前に、APIバージョンを確認してください

private void insertDummyContactWrapper() {
    // the only way we insert the dummy contact if if we are below M.
    // Else we continue on and Prompt the user for permissions
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        insertDummyContact();
        return;
    }

    List<String> permissionsNeeded = new ArrayList<String>();

    final List<String> permissionsList = new ArrayList<String>();
    if (!addPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
        permissionsNeeded.add("GPS");
    if (!addPermission(permissionsList, Manifest.permission.READ_CONTACTS))
        permissionsNeeded.add("Read Contacts");
    if (!addPermission(permissionsList, Manifest.permission.WRITE_CONTACTS))
        permissionsNeeded.add("Write Contacts");
    if (permissionsList.size() > 0) {
        if (permissionsNeeded.size() > 0) {
            // Need Rationale
            String message = "You need to grant access to " + permissionsNeeded.get(0);
            for (int i = 1; i < permissionsNeeded.size(); i++)
                message = message + ", " + permissionsNeeded.get(i);
            showMessageOKCancel(message,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                                    REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
                        }
                    });
            return;
        }
        requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
    }
}

リファレンス: http://developer.Android.com/reference/Android/content/Context.html#checkSelfPermission(Java.lang.String)

16
JBirdVegas
  1. アプリケーションが23(Android M)より前のAPIレベルをターゲットにしている場合: ContextCompat#checkSelfPermissionContext#checkSelfPermission の両方が機能せず、常に0( PERMISSION_GRANTED )を返します。 Android 6.0(API 23)でアプリケーションを実行しても。

  2. 23より前のAPIレベルをターゲットにした場合、権限を気にする必要がないことは完全に真実ではありません。 23より前のAPIレベルをターゲットにした場合:

    • Android <6.0:すべて問題ありません。
    • Android 6.0:アプリケーションの実行時許可はデフォルトで付与されます(互換モードが適用されます)、butユーザーはAndroidで実行時許可を変更できます設定すると、問題が発生する可能性があります。
  3. 第1ポイントで述べたように、Android 6.0で23より前のAPIレベルをターゲットにすると、 ContextCompat#checkSelfPermission および Context#checkSelfPermission はしません作業。幸いなことに、 PermissionChecker#checkSelfPermission を使用して、実行時の権限を確認できます。

サンプルコード:

    public boolean selfPermissionGranted(String permission) {
        // For Android < Android M, self permissions are always granted.
        boolean result = true;

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

            if (targetSdkVersion >= Build.VERSION_CODES.M) {
                // targetSdkVersion >= Android M, we can
                // use Context#checkSelfPermission
                result = context.checkSelfPermission(permission)
                        == PackageManager.PERMISSION_GRANTED;
            } else {
                // targetSdkVersion < Android M, we have to use PermissionChecker
                result = PermissionChecker.checkSelfPermission(context, permission)
                        == PermissionChecker.PERMISSION_GRANTED;
            }
        }

        return result;
    }

ターゲットSDKバージョンを取得するには、次を使用できます。

    try {
        final PackageInfo info = context.getPackageManager().getPackageInfo(
                context.getPackageName(), 0);
        targetSdkVersion = info.applicationInfo.targetSdkVersion;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }

Android Mを搭載したNexus 5で動作します。

88
MikePtr

23より前のAPIレベルをターゲットとする場合、互換モードが適用されます。 Android 6.を実行しているデバイスでも、古い許可動作が実行されています。新しい許可システムを使用するには、API 23(またはそれ以降)をターゲットにする必要があります。

完全な動作はドキュメントで指定されています: https://developer.Android.com/training/permissions/requesting.html

5