Release mediaplayer
Mediaplayer may consume a large amount of system resources. therefore, you should always take some extra measures to ensure that a mediaplayer instance will not be suspended for too long. when you use mediaplayer, you should always call release () to ensure that any system resources allocated to the mediaplayer are correctly released. for example, if you are using mediaplayer and your activity receives a call to onstop (), you must release mediaplayer, because maintaining the mediaplayer when your activtiy does not interact with the user will make the user feel a little slow (unless you play the media in the background ). when your activityis resumed or restarted, you naturally need to create a new mediaplayer and re-prepare it before resuming playback.
The following describes how to release mediaplayer:
mediaPlayer.release();mediaPlayer = null;
For example, if you forget to release the mediaplayer when activitystopped, and the activity restarts, a new mediaplayer is created. as you know, when a user changes the screen direction (or changes the device configuration in another way), the system restarts the activity (default ), so when you rotate the device back and forth, you may have consumed all the system resources, because each time you change the direction, you have created a new mediaplayer but never released it.
You may be interested in playing media in the background when no activity is available. Please refer to the next chapter.
Use a service with mediaplayer
If you want your media to be played in the background when your applications do not appear on the screen, that is, you want to continue playing the video when the user interacts with other applications-you must start a service and use it to control the mediaplayer instance. however, you should be careful when using this method, because both the user and the system have expectations about how to interact with the remaining system when an application runs a background service. if your application cannot meet these expectations, the user experience may be bad. this section describes the main issues you should pay attention to and provides suggestions on how to meet the requirements.
Asynchronous Operation
First, like activity, by default, all services are completed in a separate thread-in fact, if you run an activity and a service from the same application, by default, they use the same thread ("main thread "). therefore, the service needs to quickly process the incoming intent and never perform computing on them for a long time. if you want to execute some heavy work and blocking calls, you must execute them asynchronously: You can implement them in another thread, or use some asynchronous processing tools of the framework.
For example, when using a mediaplayer in the main thread, you should call prepareasync () instead of prepare () and implement a mediaplayer. onpreparedlistener to listen for "prepare" completion notification and start playing. For example:
public class MyService extends Service implements MediaPlayer.OnPreparedListener { private static final ACTION_PLAY = "com.example.action.PLAY"; MediaPlayer mMediaPlayer = null; public int onStartCommand(Intent intent, int flags, int startId) { ... if (intent.getAction().equals(ACTION_PLAY)) { mMediaPlayer = ... // initialize it here mMediaPlayer.setOnPreparedListener(this); mMediaPlayer.prepareAsync(); // prepare async to not block main thread } } /** Called when MediaPlayer is ready */ public void onPrepared(MediaPlayer player) { player.start(); }}
Handle asynchronous errors
Errors are usually notified by exceptions or error codes during asynchronous operations. However, whenever you use Asynchronous resources, you should ensure that your application can be correctly notified of errors. when using mediaplayer, You can implement a mediaplayer. onerrorlistener and set it to your mediaplayer instance for this purpose.
public class MyService extends Service implements MediaPlayer.OnErrorListener { MediaPlayer mMediaPlayer; public void initMediaPlayer() { // ...initialize the MediaPlayer here... mMediaPlayer.setOnErrorListener(this); } @Override public boolean onError(MediaPlayer mp, int what, int extra) { // ... react appropriately ... // The MediaPlayer has moved to the Error state, must be reset! }}
One thing is important: When an error occurs, the mediaplayer changes to the error state. You must reset it before you use it again.
Use wake-up lock
When the app is designed to play media in the background, the device may sleep when your service is running. because the Android system will try to save power during sleep, the system will try to disable any unnecessary features of the phone, including CPU and WiFi. however, if your service is playing or receiving music, you want to prevent the system from interfering with your playing work.
To ensure that your service continues to run under the above circumstances, you must use "wakelocks ". A wakelock is a way to notify the system to retain the features used by your applications when the mobile phone is idle.
Note: You should always use wakelocks conservatively and hold it only when real evidence is needed, because they significantly reduce the battery life of the device.
When playing a video on your mediaplayer, you must keep the CPU running continuously and call setwakemode () When initializing the mediaplayer (). once you do this, the mediaplayer will hold a specific lock during playback and release it when paused or stopped:
mMediaPlayer = new MediaPlayer();// ... other initialization here ...mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
However, the requested wakelock in this example can only ensure that the CPU remains awake. if you are using Wi-Fi to stream media data from a network string, you may also want to hold the wifilock. you must manually request and release it. therefore, when you use a remote URL to prepare mediaplayer, you should create and request wi-filock. for example:
WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)) .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");wifiLock.acquire();
When you pause or stop your media or you do not need the network, you should release the lock:
wifiLock.release();
Run as front-end service
Services is generally used to execute background tasks, such as obtaining emails, synchronizing data, downloading content, and other tasks. in these cases, the user does not pay too much attention to service execution, and may not be able to notice their interruptions or re-run with this document.
But now, let's consider using the service to play music. obviously, the user will pay attention to this service and some interruptions will seriously affect the user experience. in addition, this service is intended for users to interact with it during its execution. in this case, this service should be run as a "foregroundservice. A front-end is highly important-the system will never kill it because it is directly related to users. when running on the frontend, the service must also provide a notification in the status notification bar to ensure that users can see that the service is running and allow them to open an activity to interact with the service.
To get your service to the frontend, you must create a notification for the status bar and call startforeground (). For example:
String songName;// assign the song name to songNamePendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0, new Intent(getApplicationContext(), MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);Notification notification = new Notification();notification.tickerText = text;notification.icon = R.drawable.play0;notification.flags |= Notification.FLAG_ONGOING_EVENT;notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample", "Playing: " + songName, pi);startForeground(NOTIFICATION_ID, notification);
When your service is running on the frontend, the notification you configured appears in the notification area of the device. if you select this notification, the system will call the pendingintent you provided. in the above example, it opens an activity (mainactivity ).
Figure 1 shows how your notifications are displayed to users:
Figure 1. Notifications of the front-end service. The status bar notification is displayed on the left, and the view opened by the notification is displayed on the right.
You should keep the "front-end service" status only when you need to pay attention to the Service Execution. Once this situation changes, you should call stopforeground () release the foreground status:
stopForeground(true);