lostInTransit
lostInTransit

Reputation: 70997

Android - find whether audio is currently playing and stop it

I am using a MediaPlayer instance in order to stream audio files from an Internet location. The audio player is in a separate activity. The user can select from a list of audio files and come to this activity to play the audio.

Now the user might go back to the previous activity (with the list) and select another audio file. In this case, I want to stop any other audio that is playing and start playing the new audio which was selected.

Is there any way I can know whether an audio file is playing without having to hold on to the MediaPlayer object?

Thanks.

Edit

I did find out how to know whether an audio is playing. We can do it by using an object of AudioManager and calling isAudioPlaying(). This will return a true if any audio is playing.

Now the other question, how do I stop an audio currently playing? I do not have an instance of the MediaPlayer object which was created to start the audio (coz the user has already left the activity once and has come back with a new object of the activity and thus a new instance of the MediaPlayer)

Upvotes: 8

Views: 13992

Answers (6)

Aaraf Rao
Aaraf Rao

Reputation: 19

Just give AudioManager.STREAM_RING as parameter

public static boolean isStreamActive(int audioStream) {
Class<?> audioSystemClazz = null;
Boolean res = false;
try {
    audioSystemClazz = Class.forName("android.media.AudioSystem");
    if (null != audioSystemClazz) {
        // isStreamActive
        Method method = audioSystemClazz.getDeclaredMethod("isStreamActive", new Class<?>[] { int.class,
                int.class });
        if (null != method) {
            res = (Boolean) method.invoke(null, audioStream, 0);
        }
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (IllegalArgumentException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

return res;

}

Upvotes: 0

ultraon
ultraon

Reputation: 2400

I found way to check whether audio stream (AudioManager.STREAM_RING, AudioManager.STREAM_NOTIFICATION and etc.) is currently busy using reflection:

/**
 * Unhide android api: check is stream is active now (AudioManager.STREAM_RING, AudioManager.STREAM_NOTIFICATION...),
 * uses reflection
 * @param audioStream
 * @return
 */
public static boolean isStreamActive(int audioStream) {
    Class<?> audioSystemClazz = null;
    Boolean res = false;
    try {
        audioSystemClazz = Class.forName("android.media.AudioSystem");
        if (null != audioSystemClazz) {
            // isStreamActive
            Method method = audioSystemClazz.getDeclaredMethod("isStreamActive", new Class<?>[] { int.class,
                    int.class });
            if (null != method) {
                res = (Boolean) method.invoke(null, audioStream, 0);
            }
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

    return res;
}

Upvotes: 5

Android Girl
Android Girl

Reputation: 2086

Try this...

if (mp1 != null && mp1.isPlaying()) {
               mp1.stop();
           }

Where mp1 is the MediaPlayer

Upvotes: 1

John Michelau
John Michelau

Reputation: 1301

@lostintransit "Would it be better to use a service, a static variable or a singleton class? What would be the better design option?"

I think a service is what you want. The built-in media player and Pandora's app both use a service to ensure the music isn't tied to the Activity lifecycle.

If I'm understanding why you'd use a singleton or static I don't think it will accomplish what you want. The singleton/static will only be enforced within a single process in Linux. If you launch your Activity, then close it, then launch it again, they will run in different processes.

Upvotes: 2

gregm
gregm

Reputation: 12149

Here's some handy code to sleep until audio is done playing:

   AudioManager manager = (AudioManager)this.getSystemService(Context.AUDIO_SERVICE);
   while(manager.isMusicActive())
    {
        Log.d("music", "music is active");
        try
        {
            Thread.sleep(500);
        }
        catch (InterruptedException e)
        {
            Log.e("music", "interrupted waiting for music to stop");
        }
        Log.d("music", "done playing music");
    }

Upvotes: 2

jargonjustin
jargonjustin

Reputation: 2217

You'll need to call stop() on the MediaPlayer instance. To make this work in your application, you'll either need to:

  • Call stop() within the audio playing activity (in onDestroy()), for example
  • Create a Service to play audio, and communicate with it from both activities

Using a Service will allow your code to continue running outside of the Activity life-cycle, and is the only way to persist a MediaPlayer object like you need to in this case.

Alternatively, you may be able to create a custom subclass of Application and store the MediaPlayer there, but using a Service is considered better practice.

Upvotes: 10

Related Questions