Reputation: 11
I'm trying to store the uri of a previously played song, using sharedPreferences. But when if fetch and reconstruct the uri in order to play the song i get the following error message:
05-03 20:43:14.642 8617-8716/com.stopwatch.app W/MediaPlayer: Couldn't open file on client side; trying server side: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{2c95b0 8617:com.stopwatch.app/u0a175} (pid=8617, uid=10175) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
05-03 20:43:14.658 8617-8716/com.stopwatch.app I/MediaPlayer: setDataSource(content://com.android.providers.media.documents/document/audio%3A18504)
05-03 20:43:14.661 8617-8716/com.stopwatch.app E/MediaPlayer: Unable to create media player
05-03 20:43:14.662 8617-8716/com.stopwatch.app W/System.err: java.io.IOException: setDataSource failed.: status=0x80000000
I don't get way I would need android.permission.MANAGE_DOCUMENTS and my IDE tell me that it is a permission only suited for system applications. My code looks like this:
if(prefs.contains("AudioFile")){
try {
String UriString = prefs.getString("AudioFile", null);
Uri uri = Uri.parse(UriString);
mediaPlayer.setDataSource(this, uri);
Gdx.app.log("Android Media Player", "Successfully got data");
} catch (IOException e) {
e.printStackTrace();
Gdx.app.log("Android Media Player", e.getMessage());
}
try {
mediaPlayer.prepare();
Gdx.app.log("Android Media Player", "Successfully prepared content");
} catch (IOException e) {
e.printStackTrace();
Gdx.app.log("Android Media Player", e.getMessage());
}
}
I have tried running it in the onCreate
method (which seems to be a bad idea) and through another method which is called on a button click, both failed.
Notice that if I start the application and retrieve the uri through an intent at initiate the mediaPlayer through:
protected void onActivityResult (int requestCode, int resultCode, Intent data){
if(requestCode == MUSIC_REQUEST){
if(resultCode == RESULT_OK){
Uri myUri = data.getData();
SharedPreferences.Editor editor = prefs.edit();
editor.putString("AudioFile", myUri.toString());
editor.commit();
System.out.println(myUri);
try {
mediaPlayer.setDataSource(this, myUri);
Gdx.app.log("Android Media Player", "Succesfully got data");
} catch (IOException e) {
e.printStackTrace();
Gdx.app.log("Android Media Player", e.getMessage());
}
try {
mediaPlayer.prepare();
Gdx.app.log("Android Media Player", "Succesfully prepared content");
} catch (IOException e) {
e.printStackTrace();
Gdx.app.log("Android Media Player", e.getMessage());
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
I have no problems, not even if I substitute with mediaPlayer.setDataSource(this, Uri.parse(myUri.toString)).
Upvotes: 1
Views: 1972
Reputation: 1
I got the same issue, I stored URI in shared preference for future use, first time when I am playing audio it's working fine but when I am clearing background then it's showing an error. I am giving the code that I used to resolve my problem.
public void playSound(Context context, Uri uri) {
stopSound(); // Stop any currently playing sound
/*- don't remove this code it's important for android 11 or above -*/
ContentResolver resolver = context.getContentResolver();
int takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
resolver.takePersistableUriPermission(uri, takeFlags);
/*----------------------------------------------------------------*/
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(context, uri);
mediaPlayer.setLooping(true);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (Exception e) {
Log.d(TAG, "playSound: " + e.getMessage());
}
}
Upvotes: 0
Reputation: 1006539
You cannot persist a Uri
value and expect it to work later. Those that have a content
scheme offer you access to the content for a very short time.
If you are using ACTION_OPEN_DOCUMENT
to get your Uri
, you can request long-term access to the content via takePersistableUriPermission()
on a ContentResolver
. You will still have to deal with the possibility that the user might move or delete the content, though.
If you are using ACTION_GET_CONTENT
to get your Uri
, either switch to ACTION_OPEN_DOCUMENT
(if your minSdkVersion
is 19 or higher) or make a copy of the content, then use your copy.
Upvotes: 4