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 and 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 needs to continue playing in the background, such as detecting changes in files on the SD card, or recording changes in your geographical information location in the background, etc. etc. In short, services are 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. The caller of the Service can close the Service through stopService after starting it again.

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), and 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.

What needs to be noted here is that if the Service has been 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 active 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 the user (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 semi-transparent. 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 an activity that is not currently running (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 visible program in the foreground, they will be termination. Usually, there are many background processes running, so they maintain an LRU recently used program list to ensure that frequently running activities can be terminated last. If an activity correctly implements the lifecycle methods 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, and the only reason to retain 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 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, a process that owns a service and a visible activity is 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 will prepare a long-running operation to start a service rather than start a thread - especially since this operation may slow down the activity. For example, while playing music in the background and sending a photo to the server through the camera, starting a service will ensure that this operation at least runs under the priority of the service process. No matter what happens in 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 Materials on the Eight Modules of Android" written by Alibaba's senior architects to help you systematically organize messy, scattered, and fragmented knowledge, 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

추천

출처blog.csdn.net/huahaiyi/article/details/132081635