前言
最近在研究Android的音视频播放,我在Demo中连 Music 的存储路径都读不出来,orz...
于是乎,大行百度,来学习一下Android的存储,研究了各个Android版本下的权限管理。参考https://blog.csdn.net/w18756901575/article/details/52085157的读取图片示例开始,来了解一下 Android权限管理的发展史。
—— PS:我朋友说我学习搞错了方向,认证反思了一下,的确如此。毕竟自己的主攻方向不在Android的界面开发上,不能在这个上面花太多时间。
示例源代码
参考https://blog.csdn.net/w18756901575/article/details/52085157
主要就是 MainActivity.java 和 activity_main.xml
- MainActivity.java
package com.example.demopermission;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import java.io.File;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mBtnImage;
//调用系统相册-选择图片
private static final int IMAGE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtnImage = (Button) findViewById(R.id.btnImg);
mBtnImage.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnImg:
/* 简单查看一下文件*/
File f = new File(Environment.getExternalStorageDirectory() + "/Download");
Log.d("MSG", "absolute path " + f.getAbsolutePath());
Log.d("MSG", "is dir " + f.isDirectory());
Log.d("MSG", "is canRead " + f.canRead());
Log.d("MSG", "is canWrite " + f.canWrite());
if ( f.listFiles() == null) {
Log.d("MSG", "f is null ");
}
else {
Log.d("MSG", "f is not null ");
}
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, IMAGE);
break;
default:
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case IMAGE:
if (resultCode == Activity.RESULT_OK && data != null) {
Uri selectedImage = data.getData();
String[] filePathColumns = {MediaStore.Images.Media.DATA};
Cursor c = getContentResolver().query(selectedImage, filePathColumns, null, null, null);
c.moveToFirst();
int columnIndex = c.getColumnIndex(filePathColumns[0]);
String imagePath = c.getString(columnIndex);
showImage(imagePath);
c.close();
}
break;
default:
break;
}
}
//加载图片
private void showImage(String path){
Bitmap bm = BitmapFactory.decodeFile(path);
((ImageView)findViewById(R.id.imgView)).setImageBitmap(bm);
}
}
- activity_main.xml
Android 版本 和 权限管理
加载上面的代码,会发现无法提取图片,主要是Android限制了你的权限。
Android 6.0之前 (API 23 以下)
静态配置,仅需要在 AndroidManifest.xml 里进行声明
—— 我自己的环境 是 minSdkVersion 23 的版本,这种方式肯定没用
Android 10.0 (API 29 以下)
- AndroidManifest.xml 里进行声明
- Activity 中动态声明
public void requestPermission()
{
String[] permissionList = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
int targetSdkVersion = 0;
try {
final PackageInfo info = this.getPackageManager().getPackageInfo(this.getPackageName(), 0);
targetSdkVersion = info.applicationInfo.targetSdkVersion;//获取应用的Target版本
Log.d("targetSdkVersion: ", String.valueOf(targetSdkVersion));
} catch (PackageManager.NameNotFoundException e) {
Log.e("PackageInfo", "get targetSdkVersion failed.");
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Build.VERSION.SDK_INT是获取当前手机版本 Build.VERSION_CODES.M为6.0系统
//如果系统>=6.0
if (targetSdkVersion >= Build.VERSION_CODES.M) {
//第 1 步: 检查是否有相应的权限
boolean isAllGranted = checkPermissionAllGranted(permissionList);
if (isAllGranted) {
//Log.e("err","所有权限已经授权!");
return;
}
// 一次请求多个权限, 如果其他有权限是已经授予的将会自动忽略掉
ActivityCompat.requestPermissions(this, permissionList, 1);
}
}
}
private boolean checkPermissionAllGranted(String[] permissions) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
//申请权限结果返回处理
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
boolean isAllGranted = true;
// 判断是否所有的权限都已经授予了
for (int grant : grantResults) {
if (grant != PackageManager.PERMISSION_GRANTED) {
isAllGranted = false;
break;
}
}
if (isAllGranted) {
// 所有的权限都授予了
Toast.makeText(MainActivity.this, "授权成功", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "授权失败", Toast.LENGTH_LONG).show();
}
}
}
亲测有效
Android 10.0 及 以上
这里我就不深究了,不想花时间了;
主要就是 Android 10.0 对于权限管理的一些变更 巴拉巴拉的
--- build.gradle 中直接改 targetSdkVersion
不想劳神的办法
defaultConfig {
applicationId "com.example.demopermission"
minSdkVersion 23
targetSdkVersion 28 ## 直接改
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}