Multimedia Player
brief introduction
Android's Multimedia Framework Pack supports playback of many common media types, allowing you to easily integrate audio, video and images into your applications.You can play audio or video media files that are stored in the resource files of your application.The application's resource files can be stand-alone files in the file system, or they can be obtained through a network connection - a stream of data, all of which use the MediaPlayer APIS.
**Note: ** You can only play audio data on standard output devices.Currently, the standard output device is a speaker or headset for a mobile device.You cannot play the sound file during the talk audio call.
Use MediaPlayer
One of the most important progressive aspects of the media framework is the MediaPlayer class, which can be accessed, decoded, and played with a small amount of settings.It supports a variety of media sources, such as:
- Local Resources
- Internal URI s, such as those you get from ContentResolver.
- External URI (Streaming Media)
Permission Add
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
To play local video files, you need to create a raw folder under res to save the video files
public void playFromRes(View view){ MediaPlayer mp=MediaPlayer.create(this,R.raw.a1); mp.start(); }
Play system video files
public void playFromSys(View view){ MediaPlayer mp=new MediaPlayer(); String path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)+"/2.mp4"; try { mp.setDataSource(this, Uri.parse(path));//Setting up data streams mp.prepare();//Synchronous execution mp.start(); } catch (IOException e) { e.printStackTrace(); } }
Play network video files
public void playFromNet(View view){ String path="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"; MediaPlayer mp=new MediaPlayer(); try { mp.setDataSource(this,Uri.parse(path)); mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); } }); } catch (IOException e) { e.printStackTrace(); } }
Note: The prepare() call can be time consuming, as it may require acquiring open decoded media data and will take a long time to execute, then you cannot call it from your application's UI thread, otherwise it will cause the UI to hang.
Use Asynchronous Preparation
prepareAsync()
onPrepared() of MediaPlayer.OnPreparedListener
Management Status
MediaPlayer has an internal state because a specific operation is only valid in a specific state.If you perform an operation in the wrong state, the system may throw an exception or cause an unexpected behavior.
This state transition diagram clearly describes the states of MediaPlayer and lists the calling sequence of the main methods. Each method can only be used in certain states. IllegalStateException exceptions can be raised if the state of MediaPlayer is incorrect when used.
Idle status:
The MediaPlayer object is idle when a MediaPlayer object is created using the new() method or its reset() method is called.An important difference between the two methods is that if getDuration() and other methods are called in this state (equivalent to the incorrect timing of the call), OnErrorListener.onError() is triggered when the reset() method enters the idle state, and MediaPlayer enters the Error state; if a newly created MediaPlayer object is created, onError() is not triggered, nor is it entered the Error state.State.
End status:
The release() method allows you to enter the End state. As long as the MediaPlayer object is no longer used, it should be released by the release() method as soon as possible to release the related hardware and software component resources, some of which are only one (equivalent to a critical resource).If the MediaPlayer object enters the End state, it will not enter any other state.
Initialized status:
This state is relatively simple. MediaPlayer calls the setDataSource() method and enters the Initialized state, indicating that the file to be played is set at this time.
Prepared status:
After initialization, you also need to call prepare() or prepareAsync() methods, either synchronous or asynchronous, to indicate that MediaPlayer has no errors so far and can play files.
Preparing status:
This state is understandable, primarily in conjunction with prepareAsync(), which triggers OnPreparedListener.onPrepared() to enter the Prepared state if the asynchronous preparation is complete.
Started status:
Obviously, once MediaPlayer is ready, it can call the start () method so that MediaPlayer is in the Started state, indicating that MediaPlayer is playing the file.You can use isPlaying() to test if the MediaPlayer is in the Started state.Similarly, MediaPlayer can stay in Started state if it calls the seekTo() or start() method in this state.
Paused status:
MediaPlayer calls pause() method in Started state to pause MediaPlayer and enter Paused state. MediaPlayer calls start() again after pausing to continue playing MediaPlayer, go to Started state, and call seekTo() method when pausing state, which does not change state.
Stop status:
stop() can be called to stop MediaPlayer in either Started or Paused state, and MediaPlayer in Stop state needs to restart to its previous prepareAsync() and prepare() state in order to play back.
PlaybackCompleted status:
When the file has finished playing normally without setting up a loop, it enters the state and triggers the onCompletion() method of OnCompletionListener.You can call the start() method to play the file from scratch, stop() to stop the MediaPlayer, or seekTo() to relocate the playback location.
Error status:
If for some reason a MediaPlayer error occurs, it triggers the OnErrorListener.onError() event, at which point the MediaPlayer enters the Error state. It is important to catch and properly handle these errors, which can help us release related hardware and software resources in a timely manner and also improve the user experience.setOnErrorListener(android.media.MediaPlayer.OnErrorListener) allows you to set up the listener.If the MediaPlayer enters the Error state, it can be restored by calling reset(), which returns the MediaPlayer to the Idle state.
Refer to the blog for details: http://blog.sina.com.cn/s/blog_63f5ae1a0100zajv.html
Release MediaPlayer
MediaPlayer can consume a lot of system resources, so you should always take some extra steps to ensure that you don't hang too long on a MediaPlayer instance.When you are finished with MediaPlayer, you should always call release() to ensure that any system resources assigned to MediaPlayer are properly released.
Use Services to Control MediaPlayer
Simply put, it's background playback.Implement a MediaPlayer instance through a Service.
musicService
package com.example.mediaplay; import android.annotation.SuppressLint; import android.app.Service; import android.content.Context; import android.content.Intent; import android.media.MediaPlayer; import android.net.wifi.WifiManager; import android.os.Environment; import android.os.IBinder; import android.os.PowerManager; import java.io.IOException; public class MusicService extends Service implements MediaPlayer.OnPreparedListener { public static final String ACTION_PLAY="com.example.ACTION_PLAY"; public static final String ACTION_PAUSE="com.example.ACTION_PAUSE"; public static final String ACTION_EXIT="com.example.ACTION_EXIT"; private MediaPlayer mediaPlayer; private WifiManager.WifiLock lock; public MusicService() { } @Override public void onCreate() { super.onCreate(); mediaPlayer=new MediaPlayer(); mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK); //Keep wifi out of hibernation @SuppressLint("WifiManagerLeak") WifiManager wifiManager= (WifiManager) getSystemService(Context.WIFI_SERVICE); WifiManager.WifiLock lock=wifiManager.createWifiLock("mylock"); lock.acquire(); mediaPlayer.setOnPreparedListener(this); } @Override public void onDestroy() { super.onDestroy(); lock.release(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { String action=intent.getAction(); if (ACTION_PLAY.equals(action)){ mediaPlayer.reset(); try { mediaPlayer.setDataSource(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)+"/2.mp4"); mediaPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); } }else if (ACTION_PAUSE.equals(action)){ if (mediaPlayer.isPlaying())mediaPlayer.pause(); }else if (ACTION_EXIT.equals(action)){ if (mediaPlayer.isPlaying())mediaPlayer.stop(); mediaPlayer.release(); } return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onPrepared(MediaPlayer mp) { mp.start(); } }
Main End
public void play(View view){ Intent intent=new Intent(this,MusicService.class); intent.setAction(MusicService.ACTION_PLAY); startService(intent); } public void pause(View view){ Intent intent=new Intent(this,MusicService.class); intent.setAction(MusicService.ACTION_PAUSE); startService(intent); } public void exit(View view){ Intent intent=new Intent(this,MusicService.class); intent.setAction(MusicService.ACTION_EXIT); startService(intent); }
Inventory File
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK"/> <service android:name=".MusicService" android:enabled="true" android:exported="true" android:process=":music"> <intent-filter> <action android:name="com.example.ACTION_PLAY"/> <action android:name="com.example.ACTION_PAUSE"/> <action android:name="com.example.ACTION_EXIT"/> </intent-filter> </service>
Front Office Service
Adding methods to Service
private void notification() { Notification.Builder builder=new Notification.Builder(this); builder.setTicker("My first music player"); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentTitle("My Music Player"); builder.setContentInfo("Playing"); PendingIntent pi=PendingIntent.getActivity(this,0,new Intent(this,Main3Activity.class),PendingIntent.FLAG_UPDATE_CURRENT); builder.setContentIntent(pi); NotificationManager nm= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); Notification notification=builder.build(); startForeground(0,notification); nm.notify(0,notification); }
Handle Audio Focus
Call requestAudioFcus() from AudioManager;
The parameter focusChange tells you how the audio focus has changed:
AUDIOFOCUS_GAIN: You have gained audio focus
AUDIOFOCUS_LOSS: You have lost audio focus for a long time. You must stop all audio playback because it is anticipated that you may not be able to get audio focus for a long time, so this is a good place to clean up your resources. For example, you must release MediaPlayer.
AUDIOFOCUS_LOSS_TRANSIENT: You have temporarily lost focus on audio and will soon regain it. You must stop all audio playback, but you can keep your resources because you may regain focus soon.
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: You temporarily lost the audio focus, but you are allowed to continue playing at low volume instead of stopping completely.
Add AudioManager.OnAudioFocusChangeListener interface
Override onAudioFocusChange method
@Override public void onAudioFocusChange(int focusChange) { switch (focusChange){ case AudioManager.AUDIOFOCUS_GAIN: //To get focus initMediaPlayer(); mediaPlayer.setVolume(1.0f,1.0f); break; case AudioManager.AUDIOFOCUS_LOSS: //Long Lost Focus if (mediaPlayer!=null){ if (mediaPlayer.isPlaying())mediaPlayer.stop(); mediaPlayer.release(); } break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: //Lose focus, but get it soon if (mediaPlayer!=null){ if (mediaPlayer.isPlaying())mediaPlayer.stop(); } break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: //Allow low volume playback if (mediaPlayer.isPlaying())mediaPlayer.setVolume(0.1f,0.1f); break; } }
And get focus in the onCreate method
//Get Audio Focus AudioManager am= (AudioManager) getSystemService(AUDIO_SERVICE); am.requestAudioFocus(this,AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN);
Encapsulate as a method call
mediaPlayer=new MediaPlayer(); mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK); //Keep WIFI working WifiManager wifiManager= (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE); lock= wifiManager.createWifiLock("mylock"); lock.acquire(); mediaPlayer.setOnPreparedListener(this); notification();
Processing AUDIO_BECOMING_NOISY intent
Many good audio playback applications automatically stop playing when the sound changes to noise (output through an external speaker) at that time.For example, this may occur when the user suddenly disconnects the headset while listening to music with the headset.
Create a broadcast receiver
package com.example.mediaplay; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class MusicIntentReceiver extends BroadcastReceiver { private static final String action="android.media.AUDIO_BECOMING_NOISY"; public MusicIntentReceiver(){ } @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(action)){ Intent intent1=new Intent(MusicService.ACTION_STOP); context.startService(intent1); } } }
Register action in usicService
public static final String ACTION_STOP="com.example.ACTION_STOP"; //Add under onStartCommand method else if (ACTION_STOP.equals(action)){ if (mediaPlayer.isPlaying())mediaPlayer.stop(); }
Inventory File
<receiver android:name=".MusicIntentReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.media.AUDIO_BECOMING_NOISY"/> </intent-filter> </receiver> //In Service <action android:name="com.example.ACTION_STOP" />
Get media from ContentResolver
Another useful feature of media playback applications is the ability to retrieve music that the user has stored on the device.You can do this by querying the media from ContentResolver:
The database file in the diagram is the database that stores pictures and media in the simulator.
public void queryMusic(View view){ ContentResolver cr=getContentResolver(); Cursor c=cr.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,null,null,null,null); if (c!=null){ while (c.moveToNext()){ String url=c.getString(c.getColumnIndex(MediaStore.Audio.Media.DATA)); String displayName=c.getString(c.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)); String artist=c.getString(c.getColumnIndex(MediaStore.Audio.Media.ARTIST)); String time=c.getString(c.getColumnIndex(MediaStore.Audio.Media.DURATION)); System.out.println("Route:"+url); System.out.println("Song title:"+displayName); System.out.println("Singer:"+artist); System.out.println("Time:"+time); System.out.println("------------------"); } } }