我们在做Android开发时,经常会用到一些系统的权限,比如读写外部存储、读写联系人信息、调用电话短信、访问网络等。在Android 6.0之前,对于这些权限调用的声明,只需要在AndroidManifest文件中声明即可,就像下面这样:
读取权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
在android 6.0 (包括6.0)棉花糖版本之后,系统不会在软件安装的时候就赋予该app所有其申请的权限,对于一些危险级别的权限,app需要在运行时一个一个询问用户授予权限。这就是所谓的“权限动态授权”。(先在AndroidManifest中声明,再到代码中声明)
下面以读取权限为例(写了一个读取手机中多媒体文件的标题):
1在AndroidManifest声明
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2在代码中动态授权:
Main3Activity中
package com.zhh.quanxian;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.orhanobut.logger.Logger;
/**
* android自带的授权
*/
public class Main3Activity extends Activity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
initView();
initClick();
}
private void initView() {
button = findViewById(R.id.button);
}
private void initClick() {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//拿到当前版本号
int sdkVersion = Main3Activity.this.getApplicationInfo().targetSdkVersion;
Logger.t("111").d("版本号targetSdkVersion>>>" + sdkVersion);
// 判断当前版本
if (sdkVersion >= 23) {
Toast.makeText(Main3Activity.this, "6.0及以上动态授权", Toast.LENGTH_SHORT).show();
// 6.0以上单独申请权限
checkPermission();
} else {
Toast.makeText(Main3Activity.this, "6.0以下在主清单文件中授权", Toast.LENGTH_SHORT).show();
// Pre-Marshmallow
// 默认在主清单文件中授权
}
}
});
}
/**
* 检查授权
*/
private void checkPermission() {
//检查当前权限(若没有该权限,值为-1;若有该权限,值为0)
//授权读取权限,READ_EXTERNAL_STORAGE
int hasReadExternalStoragePermission = ContextCompat.checkSelfPermission(getApplication(), Manifest.permission.READ_EXTERNAL_STORAGE);
Log.e("PERMISION_CODE", hasReadExternalStoragePermission + "***");
if(hasReadExternalStoragePermission== PackageManager.PERMISSION_GRANTED){
Logger.t("111").d("已授权");
// 处理自己的逻辑
obtainMediaInfo();
}else{
Logger.t("111").d("没有授权");
//若没有授权,会弹出一个对话框(这个对话框是系统的,开发者不能自己定制),用户选择是否授权应用使用系统权限
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
}
/**
* 用户选择是否同意授权后,会回调这个方法
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(requestCode==1){
if(permissions[0].equals(Manifest.permission.READ_EXTERNAL_STORAGE)&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
//用户同意授权,执行读取文件的代码
Logger.t("111").d("同意授权");
obtainMediaInfo();
}else{
//若用户不同意授权,直接暴力退出应用。
// 当然,这里也可以有比较温柔的操作。
Logger.t("111").d("不同意授权");
finish();
}
}
}
/**
* 自己的业务逻辑
* 拿到手机中多媒体资源的名称
*/
private void obtainMediaInfo() {
// 自己的业务逻辑
// 拿到手机中多媒体资源的名称
Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
cursor.moveToFirst();
do {
String title = cursor.getString(cursor.getColumnIndex("title"));
Log.e("TITLE",title);
}while (cursor.moveToNext());
}
}
activity_main3中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zhh.quanxian.Main3Activity">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="授权" />
</LinearLayout>
3build.gradle文件中把targetSdkVersion的值改动到大于22测试即可
defaultConfig {
applicationId "com.zhh.quanxian"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
参考文章:
https://blog.csdn.net/jasper_success/article/details/78836899
源码下载:
https://download.csdn.net/download/zhaihaohao1/10591230