一、前言
最近在学习安卓,也碰到了各种各样的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) {
...
}
});
三、报错问题
- 问题最开始的发现是报空指针异常
于是我加了 if (mediaPlayer != null) 进行判断
- 之后虽然不报错了,但是很显然点击按钮不会有任何反应,因为mediaPlayer是空的,之后我发现又报了另外一个错:
然后我就Google了各种解决 No content provider的解决办法,发现还是不行,但是也有收获:发现很多人都提到,这个问题出现的大部分原因都是因为权限问题。
- 由于我的报错信息中并没有提到权限问题,所以我决定一步步Debug(如上述代码所示),终于!!Debug发现在获创建mediaPlayer获取音频时后面显示"open failed: EACCES (Permission denied)",找到问题就成功了一半!
四、最终解决
- 找到模拟器中的权限设置,允许应用存储空间权限
- 在AndroidManifest.xml文件加入这两行允许读写权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
**进行以上两步之后我的问题其实还是没有得到解决…
- 将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),接下来是补充完善内容
-
检查并申请权限
我们需要在用到权限的地方,每次都检查是否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该会多么美好!!!希望对你们有帮助…~加油!