Android Marshmallow 6.0在运行时请求权限

时间:2015-12-08 07:16:15

标签: java android android-6.0-marshmallow runtime-permissions

我正在Marshmallow 6.0上测试我的应用,并且android.permission.READ_EXTERNAL_STORAGE正在关闭它,即使已经在Manifest中定义了它。在某处我读过,如果我在运行时请求权限,那么它就不会强行关闭你的应用程序。我也读过this android document,它用于请求运行时权限。

所以,我开始知道我们可以在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.
    }
}

上面的代码有一个回调方法onRequestPermissionsResult,可以得到结果。

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {

     }
}

我的问题是准确地向用户请求权限的位置?我们应该在应用程序启动时使用请求权限,还是应该在需要权限时使用?

11 个答案:

答案 0 :(得分:8)

这对我有用!!! 在您的应用程序的启动活动中,执行以下操作,

1)为请求代码

声明一个int变量
  

String[] mPermission = {Manifest.permission.READ_CONTACTS, Manifest.permission.READ_SMS, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE};

2)声明一个字符串数组,其中包含您需要的权限数,

try {
            if (ActivityCompat.checkSelfPermission(this, mPermission[0])
                    != MockPackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(this, mPermission[1])
                            != MockPackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(this, mPermission[2])
                            != MockPackageManager.PERMISSION_GRANTED ||
                    ActivityCompat.checkSelfPermission(this, mPermission[3])
                            != MockPackageManager.PERMISSION_GRANTED) {

                ActivityCompat.requestPermissions(this,
                        mPermission, REQUEST_CODE_PERMISSION);

              // If any permission aboe not allowed by user, this condition will execute every tim, else your else part will work
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

3)Next检查onCreate方法的运行时权限条件

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        Log.e("Req Code", "" + requestCode);
        if (requestCode == REQUEST_CODE_PERMISSION) {
            if (grantResults.length == 4 &&
                    grantResults[0] == MockPackageManager.PERMISSION_GRANTED &&
                    grantResults[1] == MockPackageManager.PERMISSION_GRANTED &&
                    grantResults[2] == MockPackageManager.PERMISSION_GRANTED &&
                    grantResults[3] == MockPackageManager.PERMISSION_GRANTED) {

               // Success Stuff here

            }
        }

    }

4)现在声明onRequestPermissionsResult方法来检查请求代码,

class Object1 {
    private Object2 object2 = new Object2();

    /* Setter Method for Object2 */
    public void setObject2(Object2 object2) {
         this.object2 = object2;
    }

    public void method1() {
        String info = object2.getInfo();
        // ...
        // working with info, which I want to test
        // ...
    }
}

答案 1 :(得分:3)

通常,请求在需要时立即获得权限。通过这种方式,您可以告知用户您需要权限的原因以及处理权限更容易拒绝。

考虑用户在您的应用运行时撤消权限的情况:如果您在启动时请求它并且从不在以后检查它,则可能会导致意外行为或异常。

答案 2 :(得分:3)

在我看来,你的问题没有一个正确答案。我强烈建议您查看此官方permissions patterns page

Google建议的一些事情:

  

"您的权限策略取决于您请求的权限类型的清晰度和重要性。这些模式提供了向用户引入权限的不同方式。"

     

"应该事先要求关键权限。可以在上下文中请求辅助权限。"

     

"不太清楚的权限应该提供有关权限涉及的内容的教育,无论是在前期还是在上下文中完成。"

This illustration可能会让您更好地理解。

也许最重要的是,无论您是在前台还是在上下文中询问权限,都应该记住,用户可以随时撤消这些权限(例如,您的应用仍在运行,在后台运行) )。

您应该确保您的应用程序不会因为您在应用程序的最开始时提出权限并且认为用户没有更改他/她对该权限的偏好而崩溃。

答案 3 :(得分:2)

这样做

private static final int  REQUEST_ACCESS_FINE_LOCATION = 111;

在你的onCreate

boolean hasPermissionLocation = (ContextCompat.checkSelfPermission(getApplicationContext(),
            Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
    if (!hasPermissionLocation) {
        ActivityCompat.requestPermissions(ThisActivity.this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                REQUEST_ACCESS_FINE_LOCATION);
    }

然后检查结果

   @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode)
    {

        case REQUEST_ACCESS_FINE_LOCATION: {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                Toast.makeText(ThisActivity.this, "Permission granted.", Toast.LENGTH_SHORT).show();

                //reload my activity with permission granted
                finish();
                startActivity(getIntent());

            } else
            {
                Toast.makeText(ThisActivity.this, "The app was not allowed to get your location. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            }
        }

    }

}

答案 4 :(得分:1)

对于请求运行时权限,我使用GitHub Library

Build.gradle文件

中添加库
dependencies {
     compile 'gun0912.ted:tedpermission:1.0.3'
}

创建活动并添加PermissionListener

public class MainActivity extends AppCompatActivity{

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);



    PermissionListener permissionlistener = new PermissionListener() {
        @Override
        public void onPermissionGranted() {
            Toast.makeText(RationaleDenyActivity.this, "Permission Granted", Toast.LENGTH_SHORT).show();
            //Camera Intent and access Location logic here
        }

        @Override
        public void onPermissionDenied(ArrayList<String> deniedPermissions) {
            Toast.makeText(RationaleDenyActivity.this, "Permission Denied\n" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
        }
    };


    new TedPermission(this)
            .setPermissionListener(permissionlistener)
            .setRationaleTitle(R.string.rationale_title)
            .setRationaleMessage(R.string.rationale_message) // "we need permission for access camera and find your location"
            .setDeniedTitle("Permission denied")
            .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
            .setGotoSettingButtonText("Settings")
            .setPermissions(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .check();
   }
}

string.xml

<resources>

    <string name="rationale_title">Permission required</string>
    <string name="rationale_message">we need permission for read <b>camera</b> and find your <b>location</b></string>

</resources>

答案 5 :(得分:1)

    Android Easy Runtime Permissions with Dexter:
    1. Dexter Permissions Library

    To get started with Dexter, add the dependency in your build.gradle

    dependencies {
        // Dexter runtime permissions
        implementation 'com.karumi:dexter:4.2.0'
    }

    1.1 Requesting Single Permission
    To request a single permission, you can use withPermission() method by passing the required permission. You also need a PermissionListener callback to receive the state of the permission.

    > onPermissionGranted() will be called once the permission is granted.

    > onPermissionDenied() will be called when the permission is denied. Here you can check whether the permission is permanently denied by using response.isPermanentlyDenied() condition.

    The below code requests CAMERA permission.

Dexter.withActivity(this)
                .withPermission(Manifest.permission.CAMERA)
                .withListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted(PermissionGrantedResponse response) {
                        // permission is granted, open the camera
                    }

                    @Override
                    public void onPermissionDenied(PermissionDeniedResponse response) {
                        // check for permanent denial of permission
                        if (response.isPermanentlyDenied()) {
                            // navigate user to app settings
                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                }).check();

1.2 Requesting Multiple Permissions
To request multiple permissions at the same time, you can use withPermissions() method. Below code requests STORAGE and LOCATION permissions.

Dexter.withActivity(this)
                .withPermissions(
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        // check if all permissions are granted
                        if (report.areAllPermissionsGranted()) {
                            // do you work now
                        }

                        // check for permanent denial of any permission
                        if (report.isAnyPermissionPermanentlyDenied()) {
                            // permission is denied permenantly, navigate user to app settings
                        }
                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                })
                .onSameThread()
                .check();

答案 6 :(得分:0)

一个很好的解释和HowTo可以在这里找到:

https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en

我编写了这段代码来检查并在运行时在BaseActivity.class中请求权限,BaseActivity.class是我实现的每个其他Activity.class的父级:

public static final int PERMISSION_REQUEST = 42;
public static final int MULTIPLE_PERMISSION_REQUEST = 43;

//Marshmallow Permission Model
public boolean requestPermission(String permission /* Manifest.permission...*/) {
    if (ContextCompat.checkSelfPermission(this,
            permission) != PackageManager.PERMISSION_GRANTED) {
        if (Utils.hasMarshmallow())
            ActivityCompat.requestPermissions(this,
                    new String[]{permission}, PERMISSION_REQUEST
            );
        else {
            requestPermissions(new String[]{permission},
                    PERMISSION_REQUEST);
        }
        return false;
    } else {
        return true;
    }
}

public boolean requestPermission(String... permissions) {
    final List<String> permissionsList = new ArrayList<String>();

    for (String perm : permissions) {
        addPermission(permissionsList, perm);
    }

    if (permissionsList.size() > 0) {
        if (Utils.hasMarshmallow())
            requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                    MULTIPLE_PERMISSION_REQUEST);
        else
            ActivityCompat.requestPermissions(this, permissionsList.toArray(new String[permissionsList.size()]),
                    MULTIPLE_PERMISSION_REQUEST);
        return false;
    } else
        return true;
}


private boolean addPermission(List<String> permissionsList, String permission) {
    if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
        permissionsList.add(permission);
        // Check for Rationale Option
        if (Utils.hasMarshmallow())
            if (!shouldShowRequestPermissionRationale(permission))
                return false;
    }
    return true;
}

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

简单示例:

activity.requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE);

如果已经授予了权限,则返回结果将通知您。

答案 7 :(得分:0)

调用此功能我们可以允许用户打开对话框,询问是否允许摄像机和录制音频。

    if ( ActivityCompat.shouldShowRequestPermissionRationale (this, Manifest.permission.CAMERA) ||
            ActivityCompat.shouldShowRequestPermissionRationale (this,
                    Manifest.permission.RECORD_AUDIO) ) {
        Toast.makeText (this,
                R.string.permissions_needed,
                Toast.LENGTH_LONG).show ();
    } else {
        ActivityCompat.requestPermissions (
                this,
                new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
                CAMERA_MIC_PERMISSION_REQUEST_CODE);
    }

答案 8 :(得分:0)

https://material.io/guidelines/patterns/permissions.html 此链接将为您提供可以询问权限的不同类型的方案。根据您的需求进行选择。

答案 9 :(得分:0)

我喜欢短代码。我使用RxPermission获得许可。

RxPermission是最好的库,它使权限代码出乎意料的只有1行。

RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.CAMERA,
         Manifest.permission.READ_PHONE_STATE) // ask single or multiple permission once
.subscribe(granted -> {
    if (granted) {
       // All requested permissions are granted
    } else {
       // At least one permission is denied
    }
});

添加您的build.gradle

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

dependencies {
    implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
    implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}

这不容易吗?

答案 10 :(得分:-1)

if ( ActivityCompat.shouldShowRequestPermissionRationale (this, Manifest.permission.CAMERA) ||
                ActivityCompat.shouldShowRequestPermissionRationale (this,
                        Manifest.permission.RECORD_AUDIO) ) {
            Toast.makeText (this,
                    R.string.permissions_needed,
                    Toast.LENGTH_LONG).show ();
        } else {
            ActivityCompat.requestPermissions (
                    this,
                    new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
                    CAMERA_MIC_PERMISSION_REQUEST_CODE);
        }
相关问题