在平时开发中肯定会遇到android.content.res.Resources$NotFoundException资源找不到的问题,最常见的就是setText()传入了一个int类型的数据,遇到这种问题很好解决,把int类型数据换成string就行了,原因太简单了不再解释。但是在开发中我遇到了另外一种现象,我们一起来分析一下采坑之路。
一,需求
1,项目中有个需求是在执行某个环节的时候播放一个短音频,类似于叮咚这种音频。产品提供好mp3文件,我把资源文件放在了raw下。
2,编写一个SoundPlayUtils工具类来播放短音频,代码如下:
public class SoundPlayUtils {
// SoundPool对象
private static SoundPool mSoundPlayer = new SoundPool(10,
AudioManager.STREAM_SYSTEM, 5);
private static SoundPlayUtils soundPlayUtils;
/**
* 初始化
*
* @param context
*/
public static SoundPlayUtils init(Context context) {
if (soundPlayUtils == null) {
synchronized (SoundPlayUtils.class) {
if (soundPlayUtils == null) {
soundPlayUtils = new SoundPlayUtils(context);
}
}
}
return soundPlayUtils;
}
public SoundPlayUtils(Context context) {
//如果有其他声音在此初始化
mSoundPlayer.load(context, R.raw.one, 1);
mSoundPlayer.load(context, R.raw.two, 1);
mSoundPlayer.load(context, R.raw.three, 1);
}
/**
* 播放声音
*
* @param soundID
*/
public void play(int soundID) {
Log.d("####","play voice:"+soundID);
mSoundPlayer.play(soundID, 1, 1, 0, 0, 1);
}
3,在需要调用的时候就SoundPlayUtils.init(mApplication).play(1)
其实这个工具类不是特别优雅,会存在一些问题,具体可以看这篇分享 SoundPool
二,问题
我们可以看出需求很简单,但是用户反馈了一个问题,我们跟踪后发现是在调用SoundPlayUtils.init(mApplication).play(1)后出现了android.content.res.Resources$NotFoundException。后来检查了代码,没有发现任何问题,raw资源下明明有相关资源,百思不得其解。
三,分析
综合以上进行分析
1,是不是在apk安装的时候文件损坏,或者安装出现异常导致的。后来用户说重启就可以了,如果是资源文件损坏重启也无法解决,除非重新安装apk。
2,会不会在我 mSoundPlayer.load的时候加载失败导致的,于是我把load相关的代码全都注释了,运行程序也没有问题。
3,我们知道在这行代码mSoundPlayer.load(context, R.raw.one, 1)其中R.raw.one它对应的是int类型的数据,在安卓中所有的资源都会映射对应一个id,这也是我们通常所说的R文件,那么会不会是映射出了问题。
4,另外我们用的是安卓4.4版本,这个问题是偶现,概率比较低。因此可以断定资源映射时出现了没有对应关系的资源。
四,解决
任何问题只要程序闪退了,肯定是大问题,出现这个问题如果没有异常捕获程序肯定闪退。因此即使找不到具体原因我们起码不能让程序闪退,所以目前解决办法在load的时候进行异常捕获。当然不是所有问题都能找到具体根源,希望有大牛详细的解释这个问题。
public SoundPlayUtils(Context context) {
//如果有其他声音在此初始化
try {
mSoundPlayer.load(context, R.raw.one, 1);
mSoundPlayer.load(context, R.raw.two, 1);
mSoundPlayer.load(context, R.raw.three, 1);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
}