Android Service explanation

1, Service Introduction

Service is one of the four components in the android system (Activity, service, BroadcastReceiver and ContentProvider). It is similar to the level of Activity, but it cannot run by itself, can only run in the background, and can interact with other components. Service can be used in many applications. For example, when playing multimedia, the user starts other activities. At this time, the program should continue to play in the background, such as detecting the changes of files on the SD card, or recording the changes of your geographic information location in the background. In short, the service is always hidden in the background.

There are two ways to start a Service:

context.startService() and context.bindService()

2, Service startup process

context.startService() starts the process:

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

If Service is not yet running, android first calls onCreate() and then calls onStart();

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

If the stopService will be onDestroy directly, if the caller exits directly without calling stopService, the Service will always run in the background. After the caller of the Service starts again, he can close the Service through stopService.

Therefore, the life cycle of calling startService is: oncreate -- > OnStart (can be called multiple times) - > ondestroy

context.bindService() starts the process:

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

onBind() will return an IBind interface instance to the client. IBind allows the client to call back the Service methods, such as getting the Service instance, running status or other operations. At this time, the caller (Context, such as Activity) will be bound with the Service. When the Context exits, Srevice will call onunbind - > ondestroy to exit accordingly.

Therefore, the life cycle of calling bindService is: oncreate -- > onbind (binding only once, not multiple times) - > onunbind -- > ondestory.

During the opening and closing process of a Service, only onStart can be called multiple times (through multiple startService calls), and other onCreate, onBind, onUnbind and onDestory can only be called once in a life cycle.

 


3, Service Lifecycle

The life cycle of Service is not as complex as that of Activity. It only inherits onCreate(), onStart(), and onDestroy()

When we first started the Service, we called onCreate() and onStart (two). When the service is stopped, the onDestroy() method is executed.

It should be noted here that if the Service has been started, when we start the Service again, we will not execute the onCreate() method, but directly execute the onStart() method.

It can stop itself through the Service.stopSelf() method or Service.stopSelfResult() method. It can stop the service as long as it calls the stopService() method once, no matter how many times it calls the start service method.

4, Service example

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

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);  
        }  
    }  
}  

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();  // After calling stop, if you need to play again through start, you need to call the prepare function before.  
            } catch (IOException ex) {  
                ex.printStackTrace();  
            }  
        }  
    }  
}  

AndroidManifest.xml

Register activity

1.<activity  
2. android:name=".service.PlayMusicService"  
3.android:label="@string/app_name" />  

Register service

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

5, Code parsing

1. In Activity, in PlayMusicService, the onClick() method of OnClickListener interface is rewritten to control the playing of music, and various music operations are passed to the service through Intent

Then construct an Intent, intent = new Intent("com.homer.service.musicService");

Among them, com.home.service.musicservice is the definition of service in AndroidManifest.xml, that is, "register service" above

2. In the Activity, the control of music playback, after binding the digital op with the Bundle, through the startService(intent); Send out after service
Bundle bundle = new Bundle();
bundle.putInt("op", op);
intent.putExtras(bundle);

startService(intent);

3. In service, the startService(intent) started by Activity will be processed; Service, call the startup process of the service successively: oncreate -- > OnStart (can be called multiple times) - > ondestroy

onCreate(), create mediaPlayer

onStart(), by obtaining Bundle bundle = intent.getExtras();, Extract int op = bundle.getInt("op");, Then perform the corresponding music playback operation

onDestroy(), stop and release mediaPlayer music resources. If this method is called when executing context.stopService()

4. In Activity, close and exit in onClick() function are execution, meaning is different:

close: only this.finish() is executed; After the Activity form is closed, the service is not closed, and the music will continue to play in the background

exit: stopService(intent) is called first; After the service is closed, onDestroy() in 3 will be called in the service to stop and release music resources, and then this.finish() will be executed; This Activity form was closed

6, Expand knowledge (process and statement cycle)

The Android operating system tries to keep the application process as long as possible, but when the available memory is very low, it will eventually remove some processes. How to determine which programs can run and which are to be destroyed? Android allows each process to run on the basis of an important level. Processes with low important level are most likely to be eliminated. There are five levels in total. The following list is arranged according to importance:

A foreground process displays what the user needs to process and display at this time. If any of the following conditions is true, the process is considered to be running in the foreground.
a is interacting with the user.
b it controls a basic service that must interact with users.
c has a service that is calling the callback function of the life cycle (such as onCreate(), onStar(), onDestroy())
d it has a broadcast receive object running the onReceive() method.
Only a few foreground processes can run at any given time. Destroying them is the last choice of the system - when there is not enough memory, the system continues to run. Usually, at this point, the device has reached the memory paging state, so kill some foreground processes to ensure that they can respond to the needs of users.

An available process does not have any foreground components, but it can still affect the user interface. When the following two situations occur, the process can be called an available process.
It is a non foreground activity, but it is still available to users (the onPause() method has been called). This may 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 the interface of the previous activity can be seen. It is a service serving the available activities.

3 a service process is a service started by calling the startService() method, and it does not belong to the first two cases. Although the service process is not directly seen by users, they are really concerned by users, such as playing music in the background or downloading data from the network. Therefore, the system guarantees their operation and will not terminate them until all foreground visible programs cannot be guaranteed to run normally.

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

An empty thread does not run any available application groups. The only reason to keep them is to set up a caching mechanism to speed up the startup time of components. The system often kills these memory to balance the resources of the whole system and the resources between the process cache and the basic core cache.
Android takes the activity or service with the highest priority in the process as the priority of 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 will increase the priority. If one process serves another process, the process providing the service will not be lower than the process receiving the service. For example, if A content provider of process A serves A client of process B, or A service of process A is bound by A component of process B, process A has at least the same priority as process B, or higher.

Because the priority of a process running a service is higher than that of a process running a background activity, an activity will prepare a long-running operation to start a service instead of starting a thread - especially this operation may drag down the activity. For example, while playing music in the background, sending a photo to the server through the camera and starting a service will ensure that the operation runs at least under the priority of the service process. No matter what happens to the activity, the broadcast receiver should be an empty service instead of simply putting the time-consuming operation in a thread.

Note: the source of this article is from 51CTO blogger itcast0

Posted by sureshmaharana on Fri, 26 Nov 2021 00:46:16 -0800