Android运行时权限 - 如何实现

时间:2016-02-02 21:17:28

标签: java android permissions android-6.0-marshmallow

Android Developer Documentation给出了在运行时请求权限的示例:

// 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's 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”是什么?它说这是一个app定义的int常量,但这是否意味着我应该创建一个Constants.java并声明一个公共的静态int?价值应该是什么?

在其他示例中,我看到人们在这里使用1,或0或0xFFEEDDCC,但我无法找到它的解释。有人可以向我解释一下需要去哪里以及为什么? (在我的情况下,我需要确保应用程序有权访问正确的位置)

ActivityCompat文档说“应用程序特定的请求代码与报告给onRequestPermissionsResult的结果相匹配”?这对我没有帮助。

4 个答案:

答案 0 :(得分:19)

  

什么是" MY_PERMISSIONS_REQUEST_READ_CONTACTS"在这个例子中?

int个特定呼叫与相应的requestPermissions()回调联系起来onRequestPermissionsResult()

在幕后,requestPermissions()使用startActivityForResult();此intstartActivityForResult()中的角色相同。

  

这是否意味着我应该创建一个Constants.java并声明一个public static int?

我只想在活动中将其设为private static final int。但是,您可以在任何地方声明它。

  

价值应该是什么?

我似乎记得它需要低于0x8000000,否则它可以是你想要的任何东西。您在活动中为每个requestPermissions()调用使用的值应该是不同的int,但实际数字并不重要。

如果您的活动只有一次requestPermissions()来电,则int值无关紧要。但是,许多应用会在一项活动中进行多次requestPermissions()次调用。在这种情况下,开发人员可能需要在onRequestPermissionsResult()中知道这是什么请求。

答案 1 :(得分:2)

在&#34下的文档中稍微向下看一下;处理权限请求响应"你会看到它的目的。

一个名为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赋予它任何值。请求的每个权限都需要自己的常量。

答案 2 :(得分:1)

我查看了所有答案,但没有满足我确切需要的答案,因此,这是我编写并可以正常使用的示例,即使用户单击不再询问复选框。 / p>

  1. 创建一个方法,当您想请求运行时权限时将调用该方法,例如readContacts(),或者也可以拥有openCamera(),如下所示:

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

现在我们需要输入askContactsPermission(),您也可以将其命名为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();
        }
    }
}

在这里,我们已完成运行时权限,附加项为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

  3. 中定义所需的权限

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

  1. queryContacts方法,根据您的需要或运行时权限,您可以在需要permission之前调用您的方法。就我而言,我只是使用加载程序来获取联系人,如下所示:

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

这很不错,编码很愉快:)

答案 3 :(得分:0)

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);

}