不使用第三方的权限库,只用系统API
系统API请求权限的时候只可以单个请求。
整个过程中有2个权限提示dialog
第一个:当我们第一次打开app,需要权限时,会弹出下面的dialog
对应的代码是:
ActivityCompat.requestPermissions(Activity, permissions, requestCode)
第二个:第一个的dialog,我么点击了拒绝后,当再次需要该权限时,会弹出下面的dialog
对应的代码还是:
ActivityCompat.requestPermissions(Activity, permissions, requestCode)
PackageManager中的常量
int PERMISSION_GRANTED = 0
有权限
PERMISSION_DENIED = -1
没有权限
先介绍用的的API:
检查是单个权限,这2个表达式结果是int
ActivityCompat.checkSelfPermission(context, permission)
ContextCompat.checkSelfPermission(context, permission)
判断有无权限:
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
//没有权限
ActivityCompat.requestPermissions(this, permissions, 50);
} else {
//有权限
}
请求权限:
ActivityCompat.requestPermissions(Activity, permissions, requestCode)
ContextCompat.requestPermissions(Activity, permissions, requestCode)
请求权限后,同意或拒绝 后会回调
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
在此方法中判断是否同意请求:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 50 && permissions[0].equals(permission) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
show("请求权限成功");
} else {
show("请求权限失败,请到设置页面设置权限");
}
}
是否需要权限解释:
boolean flag=shouldShowRequestPermissionRationale(Activity, permission)
true:用户拒绝此权限
false:用户拒绝此权限+“不再询问”
注意:一定要看上面说的那3中dialog。使用系统API,只有前2种dialog,分清这几种dialog,有助于分清权限的使用过程。
EasyPermissions
这个是google提供的,github 地址:EasyPermissions
上面官方提供的Sample,采用的maven,国内网络受限,我把libary module(easypermission)去掉了,改用添加远程依赖的方式,地址:
Demo:https://git.oschina.net/libraryDemo/EasyPermissions01
Google Android Guild:正常权限和危险权限
Google Android Guild:在运行时请求权限
效果图:
整个过程中有3个权限提示dialog
第一个:当我们第一次打开app,需要权限时,会弹出下面的dialog
对应的代码是:
EasyPermissions.hasPermissions(context, permissions)
第二个:第一个的dialog,我么点击了拒绝后,当再次需要该权限时,会弹出下面的dialog
对应的代码是:
EasyPermissions.requestPermissions(MainActivity.this, "App需要拍照权限", RC_CAMERA_PERM, permissions);
第三个:当我们点击了拒绝+不再询问时,会弹出下面的dialog
对应的代码是:
//自定义设置
new AppSettingsDialog.Builder(this)
.setTitle("拍照权限")
.setRationale("缺少拍照权限,将要跳转到设置界面")
.setPositiveButton("同意")
.setNegativeButton("取消")//"" 是无法隐藏取消按钮的,必须加空格
.setRequestCode(requestCode)
.build()
.show();
gradle
dependencies {
...
compile 'pub.devrel:easypermissions:0.2.1'
...
}
XML中还是需要声明权限-例:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
逻辑步骤
逻辑:
执行拍照操作,先判断有没有权限,有:拍照;没有:请求权限。
请求权限后,会弹出dialog,点击“确定”、“取消”会走不同的方法。
“确定”:onPermissionsGranted(int requestCode, List<String> perms)
“取消”:onPermissionsDenied(int requestCode, List<String> perms)
步骤
- 重写方法onRequestPermissionsResult(...)
- 需要权限的时候,先检查有没有这个权限
- 有:进行逻辑操作
- 没有:请求权限
- (可选)让类Activity或Fragment实现
EasyPermissions.PermissionCallbacks
- (可选)系统设置完成后
onRequestPermissionsResult(...)
把结果返回给EasyPermissions
onPermissionsGranted(...)``onPermissionsDenied(...)
是Activity
或Fragment
实现EasyPermissions.PermissionCallbacks
接口必须实现的方法。
hasPermissions(...)
检查是否有权限,内部调用的是checkSelfPermission(...)
requestPermissions(...)
请求权限
somePermissionPermanentlyDenied(this, perms)
如果必须需要改权限
Step1:onRequestPermissionsResult(…)
重写此方法,将结果转发给EasyPermissions
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
如果是多个权限
String[] perms = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS };
如果app刚开始安装,没有权限,那么会弹出下图:(有的手机安装时没有让你权限给与提示,只有打开app用到该权限时才提示)
如果点击“允许”,当下次再点击Camera按钮是,直接进入业务逻辑。
如果点击“拒绝”,我们再次点击Camera时,弹出下图,文字是我们自己写的
Step2:需要权限的时候,先检查有没有这个权限
注意:
EasyPermissions.hasPermissions(Activity, Manifest.permission.CAMERA)
有2步操作
1 方法返回的boolean(是否有权限)
2 如果没有权限,会展示给与权限页面(就是上图)
当点击“允许”后,进入我们自己写的逻辑页面,
当点击“拒绝”后,会进入onPermissionsDenied()
方法,前提是Activity/Fragment实现了EasyPermissions.PermissionCallbacks
接口
if (EasyPermissions.hasPermissions(MainActivity.this, Manifest.permission.CAMERA)) {
//有此权限
toast.setText("已经有CAMERA权限了");
toast.show();
} else {//没有此权限,需要重新申请 getResources().getString(R.string.positive_button)
EasyPermissions.requestPermissions(this, "请求camera权限", RC_CAMERA_PERM, Manifest.permission.CAMERA);
}
Step3:让类Activity或Fragment实现EasyPermissions.PermissionCallbacks
implements EasyPermissions.PermissionCallbacks
当我们点击了 “拒绝”+“不再询问”后,我们在点击Button,不会弹出任何dialog,如果要弹出提示页面,需要在
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
///
}
方法中自定义请求权限的dialog。
需要重写的方法:
//同意授权
@Override
public void onPermissionsGranted(int requestCode, List<String> list) {
toast.setText("Granted");
toast.show();
}
//拒绝授权。 同时点击“不在询问” + 拒绝后,调用这个方法
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
//用户点击拒绝后+不再询问后,弹出dialog,点击“确定”会去设置界面
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this, "点击确定去设置界面设置权限")
.setTitle("Title")
.setPositiveButton("确定2")
.setNegativeButton("取消2", null /* click listener */)
.setRequestCode(requestCode)
.build()
.show();
}
}
上面的Builder(activity,rationale)过时了,下面的是可行的
new AppSettingsDialog.Builder(this)
.setTitle("拍照权限")
.setRationale("缺少拍照权限,将要跳转到设置界面")
.setPositiveButton("同意")
.setNegativeButton(" ")//"" 是无法隐藏取消按钮的,必须加空格
.setRequestCode(requestCode)
.build()
.show();
Step4;系统设置完成后
在系统设置界面,设置完权限后,返回当前界面后调用这个方法
requestCode
是requestPermissions(...)
中设置的
resultCode
不需要判断,因为不管你给不给权限,resultCode
还是RESULT_CANCELED
,也就是0,所以需要重新判断有没有权限
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_LOCATION_CONTACTS_PERM) {
toast.setText("onActivityResult定位和获取联系人权限");
toast.show();
} else if (requestCode == RC_CAMERA_PERM) {
toast.setText("onActivityResult拍照权限");
toast.show();
getCamera();
}
}
@AfterPermissionGranted(RC_CAMERA_PERM)
private void getCamera() {
String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION};
if (EasyPermissions.hasPermissions(context, Manifest.permission.CAMERA)) {
toast.setText("已经有Camera权限了");
toast.show();
} else {
EasyPermissions.requestPermissions(MainActivity.this, "App需要拍照权限", RC_CAMERA_PERM, Manifest.permission.CAMERA);
}
}
问题
如何隐藏“取消”按钮?
是无法隐藏取消按钮的,必须加空格,已空白的效果显示,如果点击取该空白,dialog仍然会消失。
new AppSettingsDialog.Builder(this)
.setNegativeButton(" ")
如果点击了“拒绝”+“不在提示”,那么就真的不会在弹出dialog提示了,如果我们还想要提示,怎么办呢?
需要我们在方法
onPermissionsDenied(...)
中再创建dialog
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this).build().show();
}
完整代码
public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {
private Toast toast;
private static final int RC_CAMERA_PERM = 100;//camera权限
private static final int RC_LOCATION_CONTACTS_PERM = 101;//定位和联系人权限
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toast = Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT);
findViewById(R.id.btn_camera).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
cameraTask();
}
});
findViewById(R.id.btn_location_contracts).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
locationAndContactsTask();
}
});
}
@AfterPermissionGranted(RC_LOCATION_CONTACTS_PERM)
private void locationAndContactsTask() {
String[] perms = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS};
if (EasyPermissions.hasPermissions(MainActivity.this, perms)) {
toast.setText("已经获取READ_CONTACTS + ACCESS_FINE_LOCATION权限了");
toast.show();
} else {
EasyPermissions.requestPermissions(this, "请求定位和联系人权限", RC_LOCATION_CONTACTS_PERM, perms);
}
}
@AfterPermissionGranted(RC_CAMERA_PERM)
private void cameraTask() {
if (EasyPermissions.hasPermissions(MainActivity.this, Manifest.permission.CAMERA)) {
//有此权限
toast.setText("已经有CAMERA权限了");
toast.show();
} else {//没有此权限,需要重新申请 getResources().getString(R.string.positive_button)
EasyPermissions.requestPermissions(this, "请求camera权限", RC_CAMERA_PERM, Manifest.permission.CAMERA);
}
}
//官方demo推荐重写这个方法,没发现什么用处
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
//同意授权
@Override
public void onPermissionsGranted(int requestCode, List<String> list) {
toast.setText("Granted");
toast.show();
}
//同时点击“不在询问” + 拒绝后,调用这个方法
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
//用户点击拒绝后,弹出dialog,点击“确定”会去设置界面
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
new AppSettingsDialog.Builder(this, "点击确定去设置界面设置权限")
.setTitle("Title")
.setPositiveButton("确定2")
.setNegativeButton("取消2", null /* click listener */)
.setRequestCode(requestCode)
.build()
.show();
}
}
//在系统设置界面,设置完权限后,返回当前界面后调用这个方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_LOCATION_CONTACTS_PERM) {
toast.setText("onActivityResult定位和获取联系人权限");
toast.show();
} else if (requestCode == RC_CAMERA_PERM) {
toast.setText("onActivityResult拍照权限");
toast.show();
}
}
}
checkSelfPermission(“….”)
系统自带的检查权限的方法(API>=23)
int selfPermission = checkSelfPermission("android.permission.CAMERA");
0:有权限;-1:没有权限。