Changing data source for audio playback using exis

2019-03-27 09:19发布

问题:

I'm trying to use the same media player but change the data source. Here is what I'm trying to do: 

    private MediaPlayer mMediaPlayer;

    public void pickFile1() {
       initMediaPlayer("myfile1.mp3");
    }

    public void pickFile2() {
       initMediaPlayer("myfile2.mp3");
    }

    private void initMediaPlayer(String mediafile) {
    // Setup media player, but don't start until user clicks button!
    try {
        if (mMediaPlayer == null) {
            mMediaPlayer = new MediaPlayer();
        } else {
            mMediaPlayer.reset();   // so can change data source etc.
        }
        mMediaPlayer.setOnErrorListener(this);
        AssetFileDescriptor afd = getAssets().openFd(mediafile); 
        mMediaPlayer.setDataSource(afd.getFileDescriptor());
    }
    catch (IllegalStateException e) {
        Log.d(TAG, "IllegalStateException: " + e.getMessage());
    }
    catch (IOException e) {
        Log.d(TAG, "IOException: " + e.getMessage());
    }
    catch (IllegalArgumentException e) {
        Log.d(TAG, "IllegalArgumentException: " + e.getMessage());
    }
    catch (SecurityException e) {
        Log.d(TAG, "SecurityException: " + e.getMessage());
    }

    mMediaPlayer.setOnPreparedListener(this);
    mMediaPlayer.prepareAsync(); // prepare async to not block main thread
    mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);  // Keep playing when screen goes off!
}

I just call this when I want to change to a new mediafile. It doesn't appear to be changing the data source successfully though. First question: is it possible to do it this way, or do I have to release the media player and create a new one for each new file? If it is possible, then why isn't my code working right?

Edit: well, releasing and recreating the media player isn't doing it either! It just keeps playing the same song!?!? How is that even possible? New idea -- create a different media player for each track, is that really what I have to do here? Is this a bug in Android perhaps?

回答1:

Make sure to stop and reset mediaplayer before changing datasource. On more important thing when you stop it calls

onCompletion

.. So do check what you are doing in this method. Then call

mplayer.setDataSource(audioPath);
mplayer.setOnPreparedListener(this);
mplayer.prepareAsync();


回答2:

I've actually had this same problem with assets today, and I know the fix.

The problem is that the assets are stored as one big chunk of data rather than actually as a bunch of individual files on a real file system somewhere. So, when you get an assetfiledescriptor, it points both to a file, but also has an offset and a length. If you just point mediaplayer at the assetfiledescriptor itself, it always plays the first media file in your assets folder (or something).

If you do this: mMediaPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(),afd.getLength());

then it plays the right file.



回答3:

You declare private String mediafile="my.mp3"; then you use AssetFileDescriptor afd = getAssets().openFd(mediafile); but at no point (from the code you posted) do you change the value of mediafile.
I would recommend putting mediafile = theNextFile; onthe line before afd = getAssets().openFd(mediafile); where theNextFile would likely refer to a file on the sd card that the user chose before clicking said button.
I'm not sure how to manage getting the file names from sd card, but I'd think using a startActivityForResult would be one way to do it.



回答4:

Well, I never did get a really good answer for this. I think it might be something funny that happens in the emulator. What I have done that is working great for me, is to download the files to the external SD card and play them from there. That changes the code slightly to this:

String path = getExternalFilesDir(null).toString() + "/";
mMediaPlayer.setDataSource(path + mediafile);

the rest remains the same.