Mediaplayer.Setdatasource() and Prepare() Not Working - Android

MediaPlayer.setDataSource() and prepare() not working - android

Try MediaPlayer.create(), you also may want to start only after player is actually ready, for example:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MediaPlayer player = MediaPlayer.create(this, Uri.parse("http://www.urltofile.com/file.mp3"));
player.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
}

MediaPlayer.setDataSource(String) not working with local files

Alternative Solution #1: Using Resources.getIdentifier()

Why not use getResources().getIdentifier() to get id of the resource and use the static MediaPlayer.create() as usual?

public int getIdentifier (String name, String defType, String defPackage)

getIdentifier() takes your resource name (test0), resource type(raw), your package name and returns the actual resource id.

 MediaPlayer mp;
//String filename = "android.resource://" + this.getPackageName() + "/raw/test0";
mp=MediaPlayer.create(getApplicationContext(), getResources().getIdentifier("test0","raw",getPackageName()));
mp.start();

I've tested this code and it works.


Update #1:

Alternative Solution #2: Using Uri.parse()

I've tested this code as well and it works too. Pass your resource path as URI to setDataSource(). I just made that change to your code to get it work.

String filename = "android.resource://" + this.getPackageName() + "/raw/test0";

mp = new MediaPlayer();
try { mp.setDataSource(this,Uri.parse(filename)); } catch (Exception e) {}
try { mp.prepare(); } catch (Exception e) {}
mp.start();


Update #2: Answer is NO

About setDataSource(String) call

After seeing your comment, it looks like you exactly want setDataSource(string) to be used for your purpose. I don't understand why. But, what I assume is, for some reason you are trying to avoid using "context". If that is not the case then the above two solutions should work perfectly for you or if you are trying to avoid context, I'm afraid that is not possible with the function with signature setDataSource(String) call. The reason is as below,

MediaPlayer setDataSource() function has these below options out of which you are only interested in setDataSource(String),

setDataSource Functions

setDataSource(String) internally calls setDataSource(String path, String[] keys, String[] values) function. If you can check its source,

public void setDataSource(String path)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(path, null, null);
}

and if you check setDataSource(String path, String[] keys, String[] values) code, you will see the below condition filtering the path based on its scheme, particularly if it is "file" scheme it calls setDataSource(FileDescriptor) or if scheme is non "file", it calls native JNI media function.

{
final Uri uri = Uri.parse(path);
final String scheme = uri.getScheme();
if ("file".equals(scheme)) {
path = uri.getPath();
} else if (scheme != null) {
// handle non-file sources
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
keys,
values);
return;
}
final File file = new File(path);
if (file.exists()) {
FileInputStream is = new FileInputStream(file);
FileDescriptor fd = is.getFD();
setDataSource(fd);
is.close();
} else {
throw new IOException("setDataSource failed.");
}
}

In the above code, your resource file URI scheme will not be null (android.resource://) and setDataSource(String) will try to use native JNI function nativeSetDataSource() thinking that your path is http/https/rtsp and obviously that call will fail as well without throwing any exception. Thats why your call to setDataSource(String) escapes without an exception and gets to prepare() call with the following exception.

Prepare failed.: status=0x1

So setDataSource(String) override cannot handle your resource file. You need to choose another override for that.

On the other side, check setDataSource(Context context, Uri uri, Map headers) which is used by setDataSource(Context context, Uri uri), it uses AssetFileDescriptor, ContentResolver from your context and openAssetFileDescriptor to open the URI which gets success as openAssetFileDescriptor() can open your resource file and finally the resultant fd is used to call setDataSource(FileDescriptor) override.

    AssetFileDescriptor fd = null;
try {
ContentResolver resolver = context.getContentResolver();
fd = resolver.openAssetFileDescriptor(uri, "r");
// :
// :
// :
if (fd.getDeclaredLength() < 0) {
setDataSource(fd.getFileDescriptor());
} else {
setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
}

To conclude, you cannot use setDataSource(String) override as is to use your resource mp3 file. Instead, if you want use string to play your resource file you can use either MediaPlayer.create() static function with getIdentifier() as given above or setDataSource(context,uri) as given in Update#1.

Refer to the complete source code for more understanding here: Android MediaPlayer


Update #3:

openFrameworks setDataSource(String):

As I have mentioned in the comments below, openFrameworks uses android MediaPlayer code asis. If you can refer to Line no: 4,

import android.media.MediaPlayer;

and Line no: 26, 27, 28 and 218

        player = new MediaPlayer();       //26
player.setDataSource(fileName); //27
player.prepare(); //28

private MediaPlayer player; //218

So, if you try to pass ardroid.resource//+ this.getPackageName() + "raw/test0" to setDataSource() using openFrameworks, you will still get the same exception as I explained in Update#2. Having said that, I just tried my luck searching Google to double sure what I am saying and found this openFrameworks forum link where one of the openFrameworks core developer arturo says,

don't know exactly how the mediaPlayer works but everything in res/raw
or bin/data gets copied to /sdcard/cc.openframeworks.packagename

Based on that comment, you may try using the copied path in setDataSource(). Using resource file on setDataSource(String) of MediaPlayer is not possible as it cannot accept resource file path. Please note that, I said "resource file path" starts with the scheme android.resource// which is actually a jar location (within your apk), not a physical location. Local file will work with setDataSource(String) which starts with the scheme file://.

To make you clearly understand what you are trying to do with a resource file, try executing this below code and see the result in logcat,

    try{
Log.d("RESURI", this.getClass().getClassLoader().getResource("res/raw/test0").toURI().toString());
}
catch(Exception e) {

}

You'll get the result as,

jar:file:/data/app/<packagename>/<apkname>.apk!/res/raw/test0

that is to show you that the resource file you are trying to access is not actually a file in physical path but a jar location (within apk) which you cannot access using setDataSource(String) method. (Try using 7zip to extract your apk file and you will see the res/raw/test0 in it).

Hope that helps.

PS: I know its bit lengthy answer, but I hope this explains it in detail. Leaving the alternative solutions in the top if that can help others.

mediaPlayer setDataSource doesn't work

setDataSource(String) throws IOException and IllegalArgumentException that you are not catching. You should wrap the two calls around a try-catch block

android mediaplayer SetDataSource(AssetFileDescriptor) does not work API 24

hmm apparently the method signature

_mediaPlayer.SetDataSource(assetFileDescriptor); 

was introduced in a later API, (I could not find in the documentation that this method signature is not valid in lower API versions)

but the method signature

_mediaPlayer.SetDataSource(assetFileDescriptor.FileDescriptor, assetFileDescriptor.StartOffset, assetFileDescriptor.Length);

does seem to work < API24

Why does MediaPlayer not prepare?

Of course, I thank all my friends who put their most effort to answer this problem of mine, but none of them solved the main issue.

How I came to find a way to get rid of this situation:

I tried another Host for my files and it worked. So I decided to move all my data and databases to another Host.

Android media player error with the prepare statement

The MediaPlayer#setDataSource(String) method expects a path to a file, which a Resource within your package is not. You can parse your String as a URI, and use an overload:

Uri uri = Uri.parse("android.resource://com.example.test/raw/paulemma.mp3");
mediaPlayer.setDataSource(this, uri);

Or, you can use the static MediaPlayer.create() method with a Resource id to create a prepared player:

mediaPlayer = MediaPlayer.create(this, R.raw.paulemma);

With the second method, you do not need to call setDataSource() or prepare().



Related Topics



Leave a reply



Submit