[해결법]MediaPlayer: Couldn’t open java.io.FileNotFoundException: No content provider: MediaPlayer: Couldn’t open content://0@settings/system/ringtone_cache open failed: ENOENT (No such file or directory)
여태 몰랐다. 오류가 발생하고 있음을… 오류는 발생하였지만, 정상 동작하였기 때문에 알 수 없었다. 그러다 몇 일 전 테스트 하는 과정에 우연히 오류로그를 보게되었다.
2020-06-23 08:12:33.281 13494-13494/com.test.test W/MediaPlayer: Couldn't open
java.io.FileNotFoundException: No content provider:
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1673)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1503)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1420)
at android.media.MediaPlayer.attemptDataSource(MediaPlayer.java:1101)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1073)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1001)
at android.media.Ringtone.setUri(Ringtone.java:332)
at android.media.RingtoneManager.getRingtone(RingtoneManager.java:728)
at android.media.RingtoneManager.getRingtone(RingtoneManager.java:703)
at android.media.RingtoneManager.getRingtone(RingtoneManager.java:666)
at com.test.test.SettingActivity.o(:1094)
at com.test.test.SettingActivity.c(:986)
at com.test.test.SettingActivity.onCreate(:276)
at android.app.Activity.performCreate(Activity.java:7825)
at android.app.Activity.performCreate(Activity.java:7814)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1306)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2020-06-23 08:12:33.282 13494-13494/com.test.test
■오류가 밸상한 코드
private String getRingToneName() {
try {
SharedPreferences sp = getSharedPreferences(MY_PM_PREF, Activity.MODE_PRIVATE);
Uri pickedUri = Uri.parse(sp.getString(POWER_OFF_RINGTONE, ""));
RingtoneManager ringtoneManager = new RingtoneManager(SettingActivity.this);
Ringtone ringtone = ringtoneManager.getRingtone(SettingActivity.this, pickedUri);
return ringtone.getTitle(SettingActivity.this);
} catch (Exception e){
return "";
}
}
오류가 발생한 위치 : Ringtone ringtone = ringtoneManager.getRingtone(SettingActivity.this, pickedUri);
벨소리를 지정한 경우에는 FileNotFoundException이 발생하지 않는다. 벨소리를 지정하지 않은 경우에 발생한다.
SharedPreferences 클래스를 사용하여 저장해둔 벨소리 정보(sp.getString(POWER_OFF_RINGTONE,””) 가 없어서 발생하는 케이스이다.
해결방법 : 벨소리를 설정하기 전이라면, 휴대폰에 설정된 기본 벨소리 정보를 가져올 수 있다. getDefaultUri(RingtoneManager.TYPE_RINGTONE) 메소드를 사용하면 된다. if문을 사용하여 분기하였다.
■오류 해결 코드
private String getRingToneName() {
try {
SharedPreferences sp = getSharedPreferences(MY_PM_PREF, Activity.MODE_PRIVATE);
Uri pickedUri = Uri.parse(sp.getString(POWER_OFF_RINGTONE, ""));
RingtoneManager ringtoneManager = new RingtoneManager(SettingActivity.this);
Ringtone ringtone;
if( sp.getString(POWER_OFF_RINGTONE, "").equals("")) {
pickedUri = ringtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
ringtone = ringtoneManager.getRingtone(SettingActivity.this, pickedUri);
}else{
ringtone = ringtoneManager.getRingtone(SettingActivity.this, pickedUri);
}
return ringtone.getTitle(SettingActivity.this);
} catch (Exception e){
return "" ;
}
}
생각하지도 못했던 곳에서 오류가 발생하였다. 하나의 오류가 이렇게 해결이 되니, 앱의 안정성에 도움이 되겠지만….코로나 여파일까, 아니면 fabric 서비스의 종료일까… 이유는 알 수 없지만, 일일 설치자 수가 급격하게 떨어졌다. 기존에 하루 2000명 대의 사람들이 다운받았던 앱인데, 몇 달 전부터 800명대를 유지하고 있다.
■ 추가적으로 open failed: ENOENT (No such file or directory) 오류가 발생한다면 저장소 권한 부여가 필요하다.
2020-06-23 08:55:23.395 12005-12005/com.test.test W/MediaPlayer: Couldn't open content://0@settings/system/ringtone_cache
java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)
at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:149)
at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:705)
at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1689)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1505)
at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1422)
at android.media.MediaPlayer.attemptDataSource(MediaPlayer.java:1111)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1073)
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1008)
at com.lge.media.MediaPlayerEx.setDataSource(MediaPlayerEx.java:222)
at android.media.Ringtone.setUri(Ringtone.java:565)
at android.media.RingtoneManager.getRingtone(RingtoneManager.java:791)
at android.media.RingtoneManager.getRingtone(RingtoneManager.java:763)
at android.media.RingtoneManager.getRingtone(RingtoneManager.java:726)
at com.test.test.SettingActivity.getPowerOffRingToneName(SettingActivity.java:392)
at com.test.test.SettingActivity.loadSharedPref(SettingActivity.java:376)
at com.test.test.SettingActivity.onCreate(SettingActivity.java:231)
at android.app.Activity.performCreate(Activity.java:7812)
at android.app.Activity.performCreate(Activity.java:7801)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3298)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3462)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2063)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7615)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
휴대폰에 있는mp3 파일등의 미디어 정보를 가져오고자 할때, 저장소권한을 부여 후 가져올 수 있다. 하지만, 벨소리 마져 저장소 권한이 필요한지는 몰랐다. 아이러니하게도 권한을 부여하지 않으면 오류만 발생할 뿐 벨소리 제목도 가져올 수 있고 벨소리 또한 정상적으로 동작한다. 안드로이드 운영체제의 구멍인가??????????????