Lesson 126. Media. MediaPlayer - audio / video player, basic features

Lesson 126. Media. MediaPlayer – audio / video player, basic features


In this lesson:

– we use MediaPlayer

MediaPlayer is a class that will allow you to play audio / video files with the ability to pause and rewind to the desired position. MediaPlayer is able to work with different sources, it can be: file path (on SD or on the Internet), stream address, Uri or file from res / raw folder.

Let’s write a small audio player application and use all these features in it.

Let’s create a project:

Project name: P1261_MediaPlayer
Build Target: Android 2.3.3
Application name: MediaPlayer
Package name: ru.startandroid.develop.p1261mediaplayer
Create Activity: MainActivity

Add lines to strings.xml:

HTTP
Stream
SD
Uri
Raw
Pause
Resume
Stop
Loop
Back
Forw
Info

layout file main.xml:



	
		
		
		
		
		
	
	
		
		
		
		
		
	
	
		
		
		
	

This is how it looks on the screen

The top row buttons start playing tracks from different sources. The middle row buttons are pause, resume, stop and checkbox repeat the track. And in the bottom row of the rewind / forward button and output to the log of current information.

create a folder res / raw and put in it any filename called explosion.mp3. For example, you can download it here – http://dl.dropboxusercontent.com/u/6197740/explosion.mp3.

MainActivity.java:

package ru.startandroid.develop.p1261mediaplayer;

import java.io.IOException;

import android.app.Activity;
import android.content.ContentUris;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;

public class MainActivity extends Activity implements OnPreparedListener,
    OnCompletionListener {

  final String LOG_TAG = "myLogs";

  final String DATA_HTTP = "http://dl.dropboxusercontent.com/u/6197740/explosion.mp3";
  final String DATA_STREAM = "http://online.radiorecord.ru:8101/rr_128";
  final String DATA_SD = Environment
      .getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC)
      + "/music.mp3";
  final Uri DATA_URI = ContentUris
      .withAppendedId(
          android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
          13359);

  MediaPlayer mediaPlayer;
  AudioManager am;
  CheckBox chbLoop;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    am = (AudioManager) getSystemService(AUDIO_SERVICE);
    chbLoop = (CheckBox) findViewById(R.id.chbLoop);
    chbLoop.setOnCheckedChangeListener(new OnCheckedChangeListener() {
      @Override
      public void onCheckedChanged(CompoundButton buttonView,
          boolean isChecked) {
        if (mediaPlayer != null)
          mediaPlayer.setLooping(isChecked);
      }
    });
  }

  public void onClickStart(View view) {
    releaseMP();

    try {
      switch (view.getId()) {
      case R.id.btnStartHttp:
        Log.d(LOG_TAG, "start HTTP");
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setDataSource(DATA_HTTP);
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        Log.d(LOG_TAG, "prepareAsync");
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.prepareAsync();
        break;
      case R.id.btnStartStream:
        Log.d(LOG_TAG, "start Stream");
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setDataSource(DATA_STREAM);
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        Log.d(LOG_TAG, "prepareAsync");
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.prepareAsync();
        break;
      case R.id.btnStartSD:
        Log.d(LOG_TAG, "start SD");
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setDataSource(DATA_SD);
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mediaPlayer.prepare();
        mediaPlayer.start();
        break;
      case R.id.btnStartUri:
        Log.d(LOG_TAG, "start Uri");
        mediaPlayer = new MediaPlayer();
        mediaPlayer.setDataSource(this, DATA_URI);
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mediaPlayer.prepare();
        mediaPlayer.start();
        break;
      case R.id.btnStartRaw:
        Log.d(LOG_TAG, "start Raw");
        mediaPlayer = MediaPlayer.create(this, R.raw.explosion);
        mediaPlayer.start();
        break;

      }

    } catch (IOException e) {
      e.printStackTrace();
    }
    if (mediaPlayer == null)
      return;

    mediaPlayer.setLooping(chbLoop.isChecked());
    mediaPlayer.setOnCompletionListener(this);
  }

  private void releaseMP() {
    if (mediaPlayer != null) {
      try {
        mediaPlayer.release();
        mediaPlayer = null;
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  public void onClick(View view) {
    if (mediaPlayer == null)
      return;
    switch (view.getId()) {
    case R.id.btnPause:
      if (mediaPlayer.isPlaying())
        mediaPlayer.pause();
      break;
    case R.id.btnResume:
      if (!mediaPlayer.isPlaying())
        mediaPlayer.start();
      break;
    case R.id.btnStop:
      mediaPlayer.stop();
      break;
    case R.id.btnBackward:
      mediaPlayer.seekTo(mediaPlayer.getCurrentPosition() - 3000);
      break;
    case R.id.btnForward:
      mediaPlayer.seekTo(mediaPlayer.getCurrentPosition() + 3000);
      break;
    case R.id.btnInfo:
      Log.d(LOG_TAG, "Playing " + mediaPlayer.isPlaying());
      Log.d(LOG_TAG, "Time " + mediaPlayer.getCurrentPosition() + "https://startandroid.ru/"
          + mediaPlayer.getDuration());
      Log.d(LOG_TAG, "Looping " + mediaPlayer.isLooping());
      Log.d(LOG_TAG,
          "Volume " + am.getStreamVolume(AudioManager.STREAM_MUSIC));
      break;

    }
  }

  @Override
  public void onPrepared(MediaPlayer mp) {
    Log.d(LOG_TAG, "onPrepared");
    mp.start();
  }

  @Override
  public void onCompletion(MediaPlayer mp) {
    Log.d(LOG_TAG, "onCompletion");
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    releaseMP();
  }
}

Let’s see. We first create path constants that the player will use. This is a file on the Internet (DATA_HTTP), a stream on the Internet (DATA_STREAM), a file on a flash drive (DATA_SD) and Uri on a melody from the system (DATA_URI). For SD and Uri, specify your values ​​so that such files exist. (Upon receiving the Uri, there is an auxiliary code at the end of the lesson)

IN onCreate we get AudioManager, find a checkbox on the screen and configure it to turn on / off repeat mode for the player.

onClickStart is a method for handling the clicks on the top row buttons. First, we release the resources of the current player. Then, depending on the button pressed, playback starts. What methods are used for this?

setDataSource – Specifies the data source for playback

setAudioStreamType – Specifies the audio stream that will be used for playback. There are several of them: STREAM_MUSIC, STREAM_NOTIFICATION, etc. You can see more about them in the AudioManager Docks. I assume they are designed to be able to set different volume levels, such as games, calls, and messages. You can also skip this method if you do not need to explicitly specify a thread. As far as I understand, STREAM_MUSIC is the default.

The following is the prepare or prepareAsync method (paired with OnPreparedListener). These methods prepare the player for playback. And, as the name implies, prepareAsync does this asynchronously, and when it does, will notify the listener of the setOnPreparedListener method. And the prepare method works synchronously. Accordingly, if we want to listen to a file from the Internet, we use prepareAsync, otherwise our application will hang because the main stream that serves the UI is blocked.

Well, the start method starts playing.

In the case of the raw file, we use the create method. The prepare method will already be executed in it and we only have to start.

We then turn the setLooping on / off depending on the current checkbox value. And we hang the listener (setOnCompletionListener), who will receive a message when playback is over.

In the method releaseMP we follow the release method. It releases the player’s resources, it is recommended to call when you are finished using the player. Moreover, help recommends using the professional method of this method and at onPause / onStop, unless there is an urgent need to hold the object.

In the method onClick we handle pressing the player’s control buttons. What methods are used here?

pause – pauses playback

start – resumes playback

stop – stops playback

seekTo – Go to a specific track position (in milliseconds)

getCurrentPosition – get current position (in milliseconds)

getDuration – the total duration of the track

isLooping – whether repeat mode is enabled

getStreamVolume – get the volume level of the specified stream

The following are the methods

onPrepared – OnPreparedListener listener method. Called when the player is ready to play.

onCompletion – OnCompletionListener listener method. Called when content is reached.

In the method onDestroy be sure to release player resources.

Manifesto Adds Internet Rights – android.permission.INTERNET.

We save everything, launch the application. The design of the received player, of course, not very much :), but now we are interested in functionality.

Once again I will list possible actions. By pressing the top buttons, we start playing from different sources. The middle row buttons allow us to pause, resume / pause playback, and enable repeat mode. The bottom row buttons rewind / fast forward for 3 sec (3000 ms) and output the log to the log.

I will turn on the file playback from the SD and display the info in the log (Info button).

start SD
Playing true
Time 4702/170588
Looping false
Volume 10

Playback is in progress, the current position is 4 seconds out of 170, repeat mode is off, volume is 10.

I will decrease the volume (with the buttons of the device or the emulator), I will activate the repeat mode (checkbox Loop), I will pause (the Pause button) and again I will output the info in the log:

Playing false
Time 46237/170588
Looping true
Volume 6

We see that the playback has stopped, the current position is already 46 seconds, the repeat mode is on, and the volume is reduced to 6.

I will now turn on Streaming Play (Stream button). We look at the log:

08: 49: 13.799: D / myLogs (18805): start Stream
08: 49: 13.809: D / myLogs (18805): prepareAsync
08: 49: 27.589: D / myLogs (18805): onPrepared

Note how long it takes from start (prepareAsync) to finish (onPrepared) player training – 14 seconds. If we used the prepare method and not prepareAsync, our application would not be available all the time.

Let’s talk about some other methods that I did not use in the example, but which are worth knowing about.

Reset method – resets the player to its original state, after that it is necessary to call setDataSource and prepare again. Similar to onRelease, but allows you to continue working with the same object. But after onRelease we need to create a new MediaPlayer object.

The setOnBufferingUpdateListener method sets the listener to buffer the playback stream. The idea is that the listener will receive a percentage of buffering, but it somehow works amazingly for me – it shows either 0 or 100.

The setOnErrorListener method sets the listener to receive errors. This is especially useful with prepareAsync methods. If errors occur during this method, they can only be caught in this way.

The setWakeMode method allows you to set a standard (PowerManager.WakeLock) lock for playback time by specifying the lock type. Don’t forget to add WAKE_LOCK permissions to the manifest.

About the video. The setDisplay method lets you tell the player where to display the images. You place the SurfaceView component (Advanced tab) on the screen, call its getHolder method and pass the resulting object to setDisplay. The player outputs an image to this component.

You can use the getVideoHeight and getVideoWidth methods to find out the size of the playable image.

The MediaPlayer class helper has a good chart of player states. It seems confusing, but if you sit and disassemble, you can understand everything. The scheme is useful, I advise to avoid.

Here you can see which formats are supported by the system.

Help also kindly provide us with a code that will allow you to view existing media files on the system:

ContentResolver contentResolver = getContentResolver();
    Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    Cursor cursor = contentResolver.query(uri, null, null, null, null);
    if (cursor == null) {
      // query failed, handle error.
    } else if (!cursor.moveToFirst()) {
      // no media on the device
    } else {
      int titleColumn = cursor
          .getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
      int idColumn = cursor
          .getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
      do {
        long thisId = cursor.getLong(idColumn);
        String thisTitle = cursor.getString(titleColumn);
        // ...process entry...
      } while (cursor.moveToNext());
    }

In the next lesson:

– we work with SoundPool




Discuss in the forum [87 replies]

Leave a Comment