java Android运行时权限-如何实现

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35163953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:49:30  来源:igfitidea点击:

Android runtime permissions- how to implement

javaandroidpermissionsandroid-6.0-marshmallow

提问by Andrew Torr

Android Developer Documentationgives this example of requesting permissions at runtime:

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'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.
    }
}

What is "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in this example? It says it's an app-defined int constant, but does that mean I should make a Constants.java and declare a public static int? What should the value be?

这个例子中的“MY_PERMISSIONS_REQUEST_READ_CONTACTS”是什么?它说它是一个应用程序定义的 int 常量,但这是否意味着我应该创建一个 Constants.java 并声明一个公共静态 int?价值应该是多少?

In other examples I see people use 1 here, or 0 or 0xFFEEDDCC, but I can't find an explanation of what it is. Can someone explain to me what needs to go here and why? (In my case, I need to make sure the app has permission to access fine location)

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

The ActivityCompat documentation says "Application specific request code to match with a result reported to onRequestPermissionsResult"? This does not help me.

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

回答by CommonsWare

What is "MY_PERMISSIONS_REQUEST_READ_CONTACTS" in this example?

这个例子中的“MY_PERMISSIONS_REQUEST_READ_CONTACTS”是什么?

It is an int, to tie a particular requestPermissions()call to the corresponding onRequestPermissionsResult()callback.

它是一个int, 将特定requestPermissions()调用绑定到相应的onRequestPermissionsResult()回调。

Under the covers, requestPermissions()uses startActivityForResult(); this intserves the same role as it does in startActivityForResult().

在幕后,requestPermissions()使用startActivityForResult(); 这int与它在 中的作用相同startActivityForResult()

does that mean I should make a Constants.java and declare a public static int?

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

I would just make it a private static final intin the activity. But, you can declare it wherever you want.

我只想让它成为private static final int活动中的一个。但是,你可以在任何你想要的地方声明它。

What should the value be?

价值应该是多少?

I seem to recall that it needs to be below 0x8000000, but otherwise it can be whatever you want. The value that you use for each requestPermissions()call in an activity should get a distinct int, but the actual numbers do not matter.

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

If your activity has only one requestPermissions()call, then the intvalue really does not matter. But many apps will have several requestPermissions()calls in an activity. In that case, the developer may need to know, in onRequestPermissionsResult(), what request this is the result for.

如果您的活动只有一个requestPermissions()调用,那么int值真的无关紧要。但是许多应用程序requestPermissions()在一个活动中会有多个调用。在这种情况下,开发人员可能需要知道onRequestPermissionsResult()这是什么请求的结果。

回答by George Mulligan

Look just a little further down in the documentation under "Handle the permissions request response" and you will see its purpose.

在“处理权限请求响应”下的文档中再往下看一点,您将看到它的用途。

A callback method called onRequestPermissionsResultgets sent back the same code as a parameter so you know which permission was being requested/granted:

一个名为的回调方法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
    }
}

Since the constant is used by you only you can give it whatever value you like as a public static final int. Each permission being requested needs its own constant.

由于常量仅供您使用,因此您可以将任何您喜欢的值作为public static final int. 请求的每个权限都需要自己的常量。

回答by HAXM

I went through all answers, but doesn't satisfied my exact needed answer, so here is an example that I wrote and perfectly works, even user clicks the Don't ask againcheckbox.

我浏览了所有答案,但没有满足我确切需要的答案,所以这里是我编写的一个示例,并且非常有效,即使用户单击了不再询问复选框。

  1. Create a method that will be called when you want to ask for runtime permission like readContacts()or you can also have openCamera()as shown below:

    private void readContacts() {
        if (!askContactsPermission()) {
            return;
        } else {
            queryContacts();
        } }
    
  1. 创建一个方法,当您想要请求运行时权限时将调用该方法,readContacts()或者您也可以具有openCamera()如下所示:

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

Now we need to make askContactsPermission(), you can also name it as askCameraPermission()or whatever permission you are going to ask.

现在我们需要 make 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;
}

Before writing this function make sure you have defined the below instance variable as shown:

在编写此函数之前,请确保您已定义以下实例变量,如下所示:

    private View parentLayout;
    private boolean contactPermissionNotGiven;;


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

Now final step to override the onRequestPermissionsResultmethod as shown below:

现在是覆盖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();
        }
    }
}

Here we are done with the RunTime permissions, the addon is the openPermissionSettingDialog()which simply open the Setting screen if user have permanently disable the permission by clicking Don't ask againcheckbox. below is the method:

在这里,我们完成了运行时权限,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);
}

What we missed ? 1. Defining the used strings in strings.xml

我们错过了什么?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. Initializing the parentLayoutvariable inside onCreatemethod

    parentLayout = findViewById(R.id.content);

  2. Defining the required permission in AndroidManifest.xml

  1. parentLayoutonCreate方法内部初始化变量

    parentLayout = findViewById(R.id.content);

  2. 定义所需的权限 AndroidManifest.xml

<uses-permission android:name="android.permission.READ_CONTACTS" />
  1. The queryContactsmethod, based on your need or the runtime permission you can call your method before which the permissionwas needed. in my case I simply use the loader to fetch the contact as shown below:

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

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

This works great happy coding :)

这很有效,编码愉快:)

回答by Hardip

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

}

}