使用权限
如果应用AndroidManifest.xml中列出正常权限,系统会自动授予这些权限,如果是危险权限,系统会要求用户明确授予这些权限。Android 发出请求的方式取决于系统版本和应用的targetSdkVersion:
- 如果设备运行的是 Android 6.0(API 级别 23)或更高版本,并且应用的 targetSdkVersion 是 23 或更高版本,则应用需要在运行时向用户请求权限。用户可随时修改权限,因此应用在每次执行相关动作时均需检查是否具备所需的权限。
- 如果设备运行的是 Android 5.1(API 级别 22)或更低版本,并且应用的 targetSdkVersion 是 22 或更低版本,则系统会在用户安装应用时要求用户授予权限。如果将新权限添加到更新的应用版本,系统会在用户更新应用时要求授予该权限。用户一旦安装应用,他们撤销权限的唯一方式是卸载应用。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.app.myapp" >
<uses-permission android:name="android.permission.RECEIVE_SMS" />
...
</manifest>
权限组
如果设备运行的是 Android 6.0(API 级别 23),并且应用的 targetSdkVersion 是 23 或更高版本,则当用户请求危险权限时系统会发生以下行为:
- 如果应用请求其清单中列出的危险权限,而应用目前在权限组中没有任何权限,则系统会向用户显示一个对话框,描述应用要访问的权限组,对话框不描述该组内的具体权限。
- 如果应用请求其清单中列出的危险权限,而应用在同一权限组中已有另一项危险权限,则系统会立即授予该权限,而无需与用户进行任何交互。例如,如果某应用已经请求并且被授予了 READ_CONTACTS 权限,然后它又请求 WRITE_CONTACTS,系统将立即授予该权限。
如果设备运行的是 Android 5.1(API 级别 22)或更低版本,并且应用的 targetSdkVersion 是 22 或更低版本,则系统会在安装时要求用户授予权限。再次强调,系统只告诉用户应用需要的权限组,而不告知具体权限。
危险权限和权限组:
权限组 | 权限 |
---|---|
CALENDAR | READ_CALENDAR,WRITE_CALENDAR |
CAMERA | CAMERA |
CONTACTS | READ_CONTACTS,WRITE_CONTACTS,GET_ACCOUNTS |
LOCATION | ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION |
MICROPHONE | RECORD_AUDIO |
PHONE | READ_PHONE_STATE,CALL_PHONE,READ_CALL_LOG,WRITE_CALL_LOG,ADD_VOICEMAIL,USE_SIP,PROCESS_OUTGOING_CALLS |
SENSORS | BODY_SENSORS |
SMS | SEND_SMS,RECEIVE_SMS,READ_SMS,RECEIVE_WAP_PUSH,RECEIVE_MMS |
STORAGE | READ_EXTERNAL_STORAGE,WRITE_EXTERNAL_STORAGE |
检查权限
从 Android 6.0(API 级别 23)开始,用户可随时从任何应用撤消权限,即使应用以较低的 API 级别为目标平台也是如此。因此,即使应用昨天使用了相机,也不能认为它今天仍具有该权限。要检查您是否具有某项权限,请调用 ContextCompat.checkSelfPermission()。
请求权限
我们可以调用 requestPermissions() 方法来请求相应权限。此方法异步运行。它会立即返回结果,并且在用户响应提示后,系统会利用相应结果来调用应用的回调方法,在调用过程中传递的请求代码与应用传递给 requestPermissions() 的请求代码相同。
处理权限请求响应
当用户响应您应用的权限请求时,系统会调用您应用的 onRequestPermissionsResult() 方法,在调用过程中向其传递用户响应。您的应用必须替换该方法,以查明是否已向其授予相应权限。在回调过程中传递的请求代码与传递给 requestPermissions() 的请求代码相同。
解释为什么应用需要权限
如果用户之前拒绝了某项权限,shouldShowRequestPermissionRationale()返回 true,这个时候最好显示提示信息向用户解释为什么需要这个权限。
如果自安装App以来没有向用户请求过该权限,或者用户之前拒绝了某项权限并且选中了权限请求对话框中的不再询问选项,或者设备政策禁止该权限,shouldShowRequestPermissionRationale()返回 false。
public class MainActivity extends AppCompatActivity {
private static final int READ_PHONE_STATE_REQUEST_CODE=2;
private ActivityMainBinding mBinding;
private void getPhoneNumber(){
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
if (tm!=null){
Toast.makeText(this,tm.getLine1Number(),Toast.LENGTH_LONG).show();
}
}
private void attemptGetPhoneNumber(){
//检查是否有此权限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED){
getPhoneNumber();
}else{
//请求权限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PHONE_STATE},
READ_PHONE_STATE_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case READ_PHONE_STATE_REQUEST_CODE:{
if (grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
getPhoneNumber();
}
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding= DataBindingUtil.setContentView(this,R.layout.activity_main);
mBinding.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
attemptGetPhoneNumber();
}
});
}
}
网友评论