Android Service Service Explanation

1. Introduction to Service

Service is one of the four major components in the android system (Activity, Service, BroadcastReceiver, ContentProvider). It is at the same level as Activity, but it cannot run by itself but 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 must continue to play in the background, such as detecting changes in files on the SD card, or recording changes in your geographic information location in the background, etc. etc. In short, the service is always hidden in the background.

There are two ways to start the Service:

context.startService() 和 context.bindService()

2. Service startup process

context.startService() starts the process:

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

If the Service is not running yet, Android first calls onCreate(), and then calls 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 will directly onDestroy, if the caller exits directly without calling stopService, the Service will always run in the background, and the caller of the Service can close the Service through stopService after restarting.

So 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's methods, such as getting the Service instance, running status or other operations. At this time, the caller (Context, such as Activity) will be bound to the Service. If the Context exits, the Service will call onUnbind->onDestroy to exit accordingly.

So the life cycle of calling bindService is: onCreate --> onBind (only once, cannot be bound multiple times) --> onUnbind --> onDestory.

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

img

f56be70f3463daa659b1a5df2a571618.png

3. Service life cycle

The life cycle of Service is not as complicated as Activity. It only inherits three methods: onCreate(), onStart(), and onDestroy().

When we start the Service for the first time, we call the onCreate() and onStart() methods successively; when we stop the Service, the onDestroy() method is executed.

It should be noted here that if the Service has 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 through the Service.stopSelf() method or Service.stopSelfResult() method, as long as the stopService() method is called once, the service can be stopped, no matter how many times the start service method is called.

4. Service Example

Below I made a simple music playback application, using startService and bindService to start local services.

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();  // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数  
            } 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 analysis

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

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

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

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

startService(intent);

3. In the Service, the startService(intent) started by the Activity will be processed; the service will call the service startup process in turn: onCreate --> onStart (can be called multiple times) --> onDestroy

onCreate(), create mediaPlayer

onStart(), obtain the Bundle bundle = intent.getExtras();, extract int op = bundle.getInt(“op”);, and then perform the corresponding music playback operation

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

4. In Activity, close and exit in the onClick() function have different execution meanings:

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

exit: first call stopService(intent); to close the service service, in the Service will call onDestroy() in 3 to stop and release the music resources, and then execute this.finish(); close the Activity window

6. Expand knowledge (process and statement cycle)

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

1 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 necessary to interact with users. c. There is a service that is calling the callback function of the life cycle (such as onCreate(), onStar(), onDestroy()). d. It has a broadcast receiving object that is running the onReceive() method. Only a few foreground processes can be running at any given time, and destroying them is a last resort for the system when there is not enough memory for the system to continue running. Usually, at this point, the device has reached a memory paged state, so some foreground processes are killed to ensure that it can respond to user needs.

2 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 still available to the user (onPause() method has been called). This may happen, for example: the activity in the foreground is a dialog box that allows the previous activity to be visible, that is, the current activity is semi-transparent, You can see the interface of the previous activity, which is a service for available activities.

3 A service process is a service started by calling the startService() method and does not belong to the first two situations. Although the service processes are not directly seen by the user, they are indeed what the user cares about, such as playing music in the background or downloading data from the network. Therefore, the system ensures their operation and will not terminate them until it cannot ensure that all foreground visible programs are running normally.

4 A background process is a non-currently running activity (the activity's onStop() method 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 stopped termination. Usually, there are many background processes running, so they maintain an LRU recently used program list to ensure that frequently running activities are the last to be terminated. If an activity implements lifecycle methods correctly and saves its current state, killing these processes will not affect the user experience.

5 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 this memory to balance the system's resources across the system, between the process cache and the base core cache. Android takes the activity or service with the highest priority in the process as the priority of this process. For example, if a process has a service and a visible activity, then the process will be defined as a visible process, not a service process.

In addition, if other processes depend on a certain process, the priority of the dependent process will increase. If a process serves another process, then the process providing the service will not be inferior to 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 to a component of process B, then process A has at least the same priority as process B, or higher. .

Because a process running a service has a higher priority than a process running a background activity, an activity would prepare a long-running operation to start a service rather than start a thread—especially if this operation might drag down the activity. For example, while playing music in the background, sending a photo to the server through the camera, starting a service will ensure that this operation runs at least under the priority of the service process. No matter what happens to this activity, the broadcast receiver should be used as an empty service instead of Simply put time-consuming operations in a separate thread.

Finally, I would like to share with you a set of "Advanced Information on Eight Modules of Android" written by a senior architect of Ali, to help you organize the messy, scattered, and fragmented knowledge systematically, so that you can systematically and efficiently master all aspects of Android development. Knowledge points.

Due to the large content of the article and the limited space, the information has been organized into PDF documents. If you need the complete document of "Advanced Materials on Eight Modules of Android", you can add WeChat to get it for free!

PS: (There are also small benefits for using the ChatGPT robot at the end of the article!! Don’t miss it)

"Android Eight Modules Advanced Notes"

Insert image description here

Compared with the fragmented content we usually read, the knowledge points in this note are more systematic, easier to understand and remember, and are strictly arranged according to the knowledge system.

1. Source code analysis collection

Insert image description here

2. Collection of open source frameworks

Insert image description here

At the same time, a WeChat group chat robot based on chatGPT has been built here to answer difficult technical questions for everyone 24 hours a day .

picture

Guess you like

Origin blog.csdn.net/huahaiyi/article/details/132081635