I. Introduction to Service

A Service is one of the four components of the Android system (Activity, Service, BroadcastReceiver, and ContentProvider). It has the same level as an Activity, but it cannot run on its own and can only run in the background. And can interact with other components. Services can be used in a variety of applications, such as multimedia playback when the user starts another Activity and the application continues to play in the background, such as detecting changes in files on the SD card, or recording changes in the location of your geographic information in the background, etc. The service is always hidden in the background.

There are two ways to start a Service: context.startService() and context.bindService().

Service startup process

Context.startservice () starts the process:

context.startService() -> onCreate() -> onStart() -> Service running -> context.stopService() -> onDestroy() -> Service stop

If the Service is not already running, Android calls onCreate() and then onStart();

If the Service is already running, only onStart() is called, so the onStart method of a Service may be called multiple times.

If stopService is onDestroy, if the caller exits without calling stopService, the Service will continue to run in the background, and the caller can stop the Service through stopService after it is started.

So the life cycle of calling startService is onCreate –> onStart –> onDestroy

Context.bindservice () starts the process:

context.bindService() -> onCreate() -> onBind() -> Service running -> onUnbind() -> onDestroy() -> Service stop

OnBind () returns the client an instance of the IBind interface, which allows the client to call back on methods of the Service, such as getting an instance of the Service, its running status, or other operations. Srevice will call onUnbind->onDestroy to exit the Context.

So the life cycle of calling bindService is: onCreate –> onBind –> onUnbind –> onDestory.

OnStart, onBind, onUnbind, onDestory, onCreate, onBind, onUnbind, onDestory, onCreate, onBind, onDestory, onCreate, onBind, onDestory, onCreate, onBind, onDestory

Service life cycle

The life cycle of a Service is not as complex as that of an Activity; it only inherits onCreate(), onStart(), and onDestroy()

When we first start the Service, we call onCreate() and onStart(). When a Service is stopped, the onDestroy() method is executed.

Note here that if the Service is already started, when we start the Service again, the onCreate() method will not be executed, but the onStart() method will be executed directly.

It can stop itself with either the service.stopSelf () method or the service.stopSelfResult () method. It can stop the Service by calling the stopService() method once, no matter how many times the start Service method is called.

Service example

Below I made a simple music playing application, using startService and bindService respectively to start the local service.

Activity

public class PlayMusicService extends Activity implements OnClickListener { private Button playBtn; private Button stopBtn; private Button pauseBtn; private Button exitBtn; private Button closeBtn; private Intent intent; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.music_service); playBtn = (Button) findViewById(R.id.play); stopBtn = (Button) findViewById(R.id.stop); pauseBtn = (Button) findViewById(R.id.pause); exitBtn = (Button) findViewById(R.id.exit); closeBtn = (Button) findViewById(R.id.close); playBtn.setOnClickListener(this); stopBtn.setOnClickListener(this); pauseBtn.setOnClickListener(this); exitBtn.setOnClickListener(this); closeBtn.setOnClickListener(this); } @Override public void onClick(View v) { int op = -1; intent = new Intent("com.homer.service.musicService"); switch (v.getId()) { case R.id.play: // play music op = 1; break; case R.id.stop: // stop music op = 2; break; case R.id.pause: // pause music op = 3; break; case R.id.close: // close activity this.finish(); break; case R.id.exit: // stopService op = 4; stopService(intent); this.finish(); break; } Bundle bundle = new Bundle(); bundle.putInt("op", op); intent.putExtras(bundle); startService(intent); // startService } @Override public void onDestroy(){ super.onDestroy(); if(intent ! = null){ stopService(intent); }}}Copy the code

Service

public class MusicService extends Service { private static final String TAG = "MyService"; private MediaPlayer mediaPlayer; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { Log.v(TAG, "onCreate"); Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show(); if (mediaPlayer == null) { mediaPlayer = MediaPlayer.create(this, R.raw.tmp); mediaPlayer.setLooping(false); } } @Override public void onDestroy() { Log.v(TAG, "onDestroy"); Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT); if (mediaPlayer ! = null) { mediaPlayer.stop(); mediaPlayer.release(); } } @Override public void onStart(Intent intent, int startId) { Log.v(TAG, "onStart"); if (intent ! = null) { Bundle bundle = intent.getExtras(); if (bundle ! = null) { int op = bundle.getInt("op"); switch (op) { case 1: play(); break; case 2: stop(); break; case 3: pause(); break; } } } } public void play() { if (! mediaPlayer.isPlaying()) { mediaPlayer.start(); } } public void pause() { if (mediaPlayer ! = null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } public void stop() { if (mediaPlayer ! = null) { mediaPlayer.stop(); try { mediaPlayer.prepare(); } catch (IOException ex) {ex.printStackTrace();} catch (IOException ex) {ex.printStackTrace(); }}}}Copy the code

AndroidManifest.xml

Register the activity

<activity  
    android:name=".service.PlayMusicService"  
    android:label="@string/app_name" />  
Copy the code

Registration service

<service  
    android:name=".service.MusicService"  
    android:enabled="true" >  
    <intent-filter>  
        <action android:name="com.homer.service.musicService" />  
    </intent-filter>  
</service>  
Copy the code

Five, code parsing

1. In the Activity, the PlayMusicService overrides the OnClickListener interface onClick() method to control the playback of music

Then, by constructing an Intent and Intent = new Intent (” com. Homer. Service. MusicService “);

Among them, the com. Homer. Service. MusicService is AndroidManifest. XML definition of the service, as the “registration service”

2, In the Activity, the control of music playback, using the Bundle to bind the digital OP, through startService(intent); Bundle = new Bundle(); bundle.putInt(“op”, op); intent.putExtras(bundle);

startService(intent);

StartService (Intent), where the Activity is started. Service, which calls the startup process of the service in turn: onCreate –> onStart(can be called multiple times) –> onDestroy

OnCreate () creates the mediaPlayer

Intent.getextras (); intent.getextras (); Int op = bundle.getint (“op”); And then performs the music playback operation in response

OnDestroy (), stops and releases mediaPlayer music resources if called when context.stopService() is executed

4, In the Activity, the onClick() function close and exit are executed differently:

Close: just execute this.finish(); After closing the Activity form, the service is not closed and the music will continue to play in the background

Exit: stopService(intent) is called first; If the service is closed, onDestroy() in 3 is called to stop and release the music resource before this.Finish () is executed. The Activity form is closed

6. Knowledge expansion (process and declaration cycle)

The Android operating system tries to hold on to application processes for as long as possible, but eventually removes some processes when available memory is low. How to determine which applications will work and which will be destroyed. Android makes each process run on a critical level basis, with low-critical processes most likely to be eliminated. There are five levels, and the following is a list of them in order of importance:

A foreground process displays what the user needs to process and display at this time. The process is considered to be running in the foreground if any of the following conditions are true. A Is interacting with the user. B It controls a basic service that is required to interact with the user. C has a service that is calling life-cycle callback functions (such as onCreate(), onStar(), onDestroy()) d it has a broadcast receive object that is running onReceive(). Only a few foreground processes can run at any given time, and destroying them is a last resort when the system runs out of memory. Usually, at this point, the device has reached a paging state, so some foreground processes are killed to ensure that they can respond to user demands.

A usable process does not have any foreground components, but it can still affect the user’s interface. The process is called available when two things happen. It is a non-foreground activity, but is still available to the user (onPause() has been called). This can happen, for example: The foreground activity is a dialog box that allows the previous activity to be visible. That is, the current activity is translucent and can see the interface of the previous activity. It is a service for available activities.

3 A service process is a service started by calling the startService() method and does not fall into the first two cases. Although server processes are not directly visible to the user, they are of interest to the user, such as playing music in the background or downloading data from the network. So the system keeps them running until it can’t guarantee that all foreground visible programs are running properly.

A background process is an activity that is not currently running (its onStop() method has already been called). They have no direct impact on the user experience and will be terminated when there is not enough memory to run the foreground visible program. Usually, background processes have many running programs, so they maintain a list of recent LRU applications to ensure that frequently running activities are the last to be terminated. If an activity implements the lifecycle methods correctly and saves its current state, killing these processes will not affect the user experience.

An empty thread is not running any available application groups, and the only reason it keeps them is to set up a caching mechanism to speed up component startup time. The system often kills this memory to balance the system’s overall system resources between the process cache and the basic core cache. Android prioritizes the activity or service that has the highest priority in the process. For example, if a process has a service and a visible activity, the process will be defined as a visible process, not a service process.

In addition, if other processes depend on a process, the dependent process takes precedence. If a process serves another process, the process providing the service is no inferior to the process receiving the service. For example, if A content provider of process A serves A client of process B, or if A service of process A is bound to A component of process B, then process A has at least the same or higher priority as process B.

Because a process running a service takes precedence over a process running a background activity, an activity prepares a long-running operation to start a service rather than starting a thread — especially if that operation might drag down the activity. Such as background music at the same time, through the camera to the server to send a photo, to start a service will ensure the operation running at least under the priority of the service process, no matter what happened in this activity, the broadcast receiver should serve as an empty rather than simply put time-consuming operations in a thread alone.