Use the mediaplayer of the service
If you want to play the media in the background, even if the application is not on the screen, that is, when the user interacts with other applications, the media file can still be played, you must start a service and control the mediaplayer instance in the service. You should pay attention to this situation, because both the user and the system want to run the background service applications to interact with the system's free time. If the application cannot meet this expectation, the user may have a bad experience. This section describes the main problems and provides solutions to them.
Asynchronous Operation
First of all, by default, the activity and all work in the service are executed in a single thread. If you run an activity and service in the same application, by default, they all use the same thread (main thread ). Therefore, the Service must quickly process input requests, and do not process long-time computing when responding to requests. If there is heavy work or blocking calls, you must adopt an Asynchronous Method: You can use another thread to execute your processing, or you can use a lot of convenient asynchronous processing provided by the framework.
For example, when using mediaplayer in the main thread, you should call the prepareasync () method instead of prepare (). To enable playback processing when preparation is complete, you must implement mediaplayer. onprepare listener, 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, 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
During synchronization, errors usually send an exception signal or error code. However, when using asynchronous resources, ensure that the application obtains the correct error notification. In the mediaplayer scenario, you can implement the mediaplayer. onerror listener and set it to the mediaplayer instance:
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!
}
}
It is important to remember that when an error occurs, the mediaplayer changes to the error state. Before you can use it again, you must reset it.
Use wake lock)
When you design an application for playing media in the background, the device may enter sleep state when the service is still running. Because the Android system will try to save power when the device is sleeping, the system will try to turn off all unwanted phone functions, including CPU and WiFi hardware. However, if your service is playing or streaming music, it is necessary to prevent the system from interfering with your playing action.
To ensure that your service can continue running under these conditions, you must use "Wake locks ". A wake-up lock is a method of sending a signal to the system the functions that are being used by the application, requiring the system to retain the validity of these functions even when the system is idle.
Note: You should try to use wake locks as few as possible and hold them only when needed, because they will directly reduce the battery time.
To ensure that the CPU continues to run during mediaplayer playback, call the setwakemode () method during mediaplayer initialization. Once you call this method, the mediaplayer object holds this specific lock during playback and needs to release the lock upon suspension or termination:
Mmediaplayer = new mediaplayer ();
//... Other initialization here...
Mmediaplayer. setwakemode (getapplicationcontext (), powermanager. partial_wake_lock );
However, the wake-up lock obtained in this example only ensures that the CPU remains in the working state. If the stream media being played is network-based and you are using the Wi-Fi function, you must also hold the wifilock. This lock must be obtained and released manually. Therefore, when using a remote URL to prepare mediaplayer, you should create and obtain a Wi-Fi lock. For example:
Wifilock = (wifimanager) getsystemservice (context. wifi_service ))
. Createwifilock (wifimanager. wifi_mode_full, "mylock ");
Wifilock. Acquire ();
When the service suspends or stops media playback, or when the network is not needed, you should release the lock:
Wifilock. Release ();