"open failed: EACCES (Permission denied)"读取SD卡报错解决办法

一、前言

最近在学习安卓,也碰到了各种各样的bug,这次的这个bug折腾了我一整个晚上!!所以整理出来让大家少栽跟头…


二、问题背景

实现一个简单的从模拟器的SD卡中读取数据实现音乐的播放暂停和停止
关键代码如下:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏显示
        //获取要播放的音频文件
        File file=new File("/sdcard/han10cm.mp3");
        if (file.exists()){
            Log.i(TAG ,"加载mediaPlayer");
            mediaPlayer=MediaPlayer.create(this,Uri.parse(file.getAbsolutePath()));
            //检查出错输出日志...
            boolean ifNull=(mediaPlayer==null);
            Log.i(TAG,"文件地址"+Uri.fromFile(file));
            Log.i(TAG,"mediaPlayer是否为空"+ifNull);
        }else {
            Log.i(TAG,"文件不存在");
            Toast.makeText(this, "要播放的音频不存在", Toast.LENGTH_SHORT).show();
            return;
        }

        final ImageView btn_play=findViewById(R.id.btn_play);
        final ImageView btn_stop=findViewById(R.id.btn_stop);

        //播放/暂停按钮的监听内容
        btn_play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ...
            }

        });

三、报错问题

  1. 问题最开始的发现是报空指针异常

在这里插入图片描述
于是我加了 if (mediaPlayer != null) 进行判断

  1. 之后虽然不报错了,但是很显然点击按钮不会有任何反应,因为mediaPlayer是空的,之后我发现又报了另外一个错:

在这里插入图片描述
然后我就Google了各种解决 No content provider的解决办法,发现还是不行,但是也有收获:发现很多人都提到,这个问题出现的大部分原因都是因为权限问题

  1. 由于我的报错信息中并没有提到权限问题,所以我决定一步步Debug(如上述代码所示),终于!!Debug发现在获创建mediaPlayer获取音频时后面显示"open failed: EACCES (Permission denied)",找到问题就成功了一半!

四、最终解决

  1. 找到模拟器中的权限设置,允许应用存储空间权限
    在这里插入图片描述
  2. 在AndroidManifest.xml文件加入这两行允许读写权限
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    

**进行以上两步之后我的问题其实还是没有得到解决…

  1. 将targetSdkVersion设置为小于23,然后重新编译

    targetSdkVersion小于23的应用默认授予了所申请的所有权限,所以如果你以前的APP设置的targetSdkVersion低于23,在运行时也不会崩溃,但这也只是一个临时的救急策略,用户还是可以在设置中取消授予的权限。

    defaultConfig {
            applicationId "com.neu.music"
            minSdkVersion 15
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
    
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }
    

到这里,不出意外程序应该能正常运行了(我反正是可以了…hhh),接下来是补充完善内容

  1. 检查并申请权限

    我们需要在用到权限的地方,每次都检查是否APP已经拥有权限,
    比如我们有一个下载功能,需要写SD卡的权限,
    我们在写入之前检查是否有WRITE_EXTERNAL_STORAGE权限,没有则申请权限

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            //申请WRITE_EXTERNAL_STORAGE权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    WRITE_EXTERNAL_STORAGE_REQUEST_CODE);
        }

请求权限后,系统会弹出请求权限的Dialog

具体参考: https://www.jianshu.com/p/b4a8b3d4f587


五、总结

总得来说,程序报错之后去网上找解决办法固然重要,但是自己耐下心来一步步Debug找出出现问题的那个具体的点更为重要!!!多输出日志,设断点…找到错误也不会太难~


**题外话:找Bug太费时间啦!!太让人头秃啦!!啊啊啊!!写文章又花了四十分钟…世界要是没有Bug该会多么美好!!!希望对你们有帮助…~加油!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值