在相应Activity.java里添加以下代码,这里以 WRITE_EXTERNAL_STORAGE 为例
public void requestPower() { if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)){ //第一次上面这个方法返回的是false,之后就一直返回true }else{ ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);//核心 //此处会弹出一个框框询问你是否给予权限 } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode==1){ for(int i=0;i<permissions.length;i++){//可能有多个权限,需要观测是否为PERMISSION_GRANTED状态 if(grantResults[i]==PackageManager.PERMISSION_GRANTED){ Toast.makeText(this, "权限" + permissions[i] + "申请成功", Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(this, "权限" + permissions[i] + "申请失败", Toast.LENGTH_SHORT).show(); } } } }弹出的询问框无论选择 是 还是 否,之后都不再会询问,因为ActivityCompat.shouldShowRequestPermissionRationale会返回true。
//显然这块代码的核心是ActivityCompat.requestPermissions(Context context, String[] permissions, int requestCode);这个方法
通过Environment.getExternalStorageDirectory().getAbsolutePath()拿到sd卡路径 filePath(String) 后 ,通过File file = new File(filePath + "/xxx");来创建之前,加上 requestPower();
当然,既然是动态申请,在Manifest文件里也要记得添加好要动态申请的这个权限。
总结
1.判读是否获得权限
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ //还没获得这个权限 }
2.申请权限(这个方法被调用时就会出现一个框框)
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
3.权限申请的回调方法
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode==1){ for(int i=0;i<permissions.length;i++){//可能有多个权限,需要观测是否为PERMISSION_GRANTED状态 if(grantResults[i]==PackageManager.PERMISSION_GRANTED){ Toast.makeText(this, "权限" + permissions[i] + "申请成功", Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(this, "权限" + permissions[i] + "申请失败", Toast.LENGTH_SHORT).show(); } } } }
顺便随便说说我遇到的一个问题:
由于app在sd目录下已经创建了一个一个xxx文件夹,卸载这个应用后此文件依然会存在
再安装测试,此时在弹出权限选择框之前app发生崩溃
报错行代码为:
FileOutputStream fos = new FileOutputStream(path);
分析发现报错原因并不是path不存在,而正是因为存在才引起的问题
原因是弹出权限框时,此时说明还没有得到写入权限,但由于有了以前创建的那个xxx文件夹,之后的代码便以已经有权限的状态去尝试写入修改,当然会崩溃了。(我的处理方式是 若没有xxx文件夹时会创建,若失败(说明还没有权限)会返回false,之后跳出不再执行之后的代码,若已有xxx文件,则直接执行之后的代码)
总的来说,因为有了xxx文件,让其误以为已经有写入权限,毕竟有了xxx文件夹并不代表可以再创建文件,因为xxx文件可能是之前被卸载的app所留下的东西,而此时并没有写入的权限
解决只要在之后的代码前加上一个简单的 if 判断即可