Android lesson 3: Services

The article does not point out the creation of activities, layout code and control binding. You can find relevant videos for basic learning first

Service Service

Some applications rarely interact with users. They only interact with users in the background. They only process some tasks in the background, and users can still run other applications during operation. The Android system realizes this requirement through services and broadcast receiver components.

1 overview of services

In order to handle this background process, Android introduces the concept of service. Service is an acquired operation component with a long life cycle in Android. It constantly provides any user interface. The most common example is the media player application, which can still play songs when it goes to the background.
Like other components, services run in the main thread. This means that if the service wants to perform CPU consuming or blocking operations, it should create a new thread to do these tasks in a new thread.

1.1 creating services

The creation process is similar to the creation activity. The process is as follows:

  • Write the corresponding component type
    Require to inherit Android app. Service or its subclasses, and override some of its methods. There are many important subclasses of services, which are commonly used as follows:

    • android.app.Service. The most basic service class
    • android.app.IntentService. A service class that handles asynchronous requests

    The code for creating a service class instance is as follows:

    public class MyService extends Service{
    	@Override
    	public IBinder onBind(Intent intent){
    		//TODO
    	}
    	@Override
    	public void onCreate(){
    		//TODO
    	}
    	@Override
    	public void onDestroy(){
    		//TODO
    	}
    	@Override
    	public int onStartCommand(Intent intent ,int flags,int starId){
    		//TODO
    	}
    	
    }
    
  • At androidmanifest Register in XML file

      <service
      	android:name=".MyService"
      	android:enabled="true"
      	android:exported="true"/>
    

    android:enabled="true" is to set whether the server can be instantiated by the system. True means yes, which is the default value
    android:exported="true" is to set whether the server can be started by other applications. True means yes. It is the default value
    Note: in order to ensure the security of the application, please do not use implicit intention to enable the service, because the service is a component that can run in the background for a long time. If android:exported = "true", and implicit intention is set, it may be unknowingly started and run by other malicious programs.

1.2 classification of services

The above describes how to create a service, but I need to use it after creation, but the service is divided into two types. Start type service and binding type service. The life cycles and usage methods of the two services are different. The usage methods of the two types of services are explained below.

2 start type service

2.1 overview of startup services

When the application component (activity or service) starts the service by calling startService (), the service is in the start state. Once the service is started, the component that starts it can no longer manage and control the service. The starting component and the service are loosely coupled. Therefore, starting a type service usually performs a single operation and does not return the result to the caller.

2.2 start service life cycle

Start the service life cycle as shown in the figure. (note that the service life cycle is started, and the binding service is different. Don't confuse it.).

The startup service life cycle is shown in the figure above and can be analyzed from two aspects: two nested loops and three methods

Two nested loops

  • Whole life cycle
    The entire life cycle of the service occurs between the onCreate() call and the onDestroy() call.

    The startup component (activity or service) can start the service by calling the startservice () method and passing the intention object. The system will find the service according to the intention. (the starting process is the same as the way we mentioned before, but the method is different).

    Then the system will call the onCreate() method of the service, and then call the onStratCommand() method of the service.

    The startup component data can be passed to the service through the Intent parameter of the onStartCommand() method. (it can be understood here that the start activity before the class passes data, but the open service does not need to obtain the Intent object like the activity, but is directly used through the parameters in onStartCommand).

    After the service starts running, until other components (activities or services) call the stopService() method, or the current service calls the stopSelf () method, the service destruction will call onDestory (), which can release some resources in this method.

  • Effective life cycle
    The valid life cycle of the service occurs between the onStartCommand() call and the onDestory() call. When the component is started multiple times, onStartCommand() will be called repeatedly.

Three methods

  • onCreate: when the service is first created, the system calls the secondary method, which is called before calling the onStarCommand () or onBind () method (the onBind method is the binding type service). After the service runs, it is no longer called.

  • onStartCommand: when the startup component requests to start the service by calling startService(), if it is the first time to start, call onCreate() and then call this method. If it is not the first time, the system will call this method directly.

  • onDestroy: the system will call this method when the service is not in use and is about to be destroyed. The service should implement this method to clean up the occupied resources.

2.3 examples

1. Create service
Create a Service class MyService, which needs to inherit the Service parent class.

public class MyService extends Service {
    private static String TAG="Myservice";
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.v(TAG,"Called onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.v(TAG,"Called onStartCommand....statId="+startId);
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.v(TAG,"Called onDestroy");
        super.onDestroy();
    }
}

2. Registration services
Mentioned above in Android manifest The registration code in XML. The writing position should be juxtaposed with < / activity / >. Here's another show.

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"></service>

</application>

3. Start service

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Bind button control
        Button btnStart=findViewById(R.id.button_start);
        Button btnStop =findViewById(R.id.button_stop);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Start service via Intent
                Intent intent =new Intent(MainActivity.this,MyService.class);
                startService(intent);
            }
        });
        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Stop service via Intent
                Intent intent =new Intent(MainActivity.this,MyService.class);
                stopService(intent);
            }
        });
    }
}

3. Binding type service

3.1 binding service overview

When an application component (activity or service) binds to a service by calling bindService (), the service is in the "bound" state. Bound services provide a C/S (client / server) interface through which components can interact with services, send requests, return data, etc., and even realize cross process operation through inter process communication (IPC). Compared with the startup type service, the binding type service is highly coupled, etc. Multiple components can be bound to the service at any time. After all the orders are unbound, the service will be destroyed.

3.2 binding service life cycle


The life cycle of binding service is shown in the figure, which can be analyzed from two different angles. That is, two nested loops and four methods.

Two nested loops

  • Whole life cycle
    The whole service life cycle occurs between onCreat() and onDestroy() calls. The client creates the service by calling the bindService() method, then the system calls the onCreate() method of the service, and then calls the onBind() method. After all the bindings are unbound, the system will call the onUnbind() method, and then call the ondestroy () method to release resources.

  • Effective life cycle
    The valid life cycle of the service occurs from the beginning of onBind() to the end of onUnbind().

Four methods

  • onCreate(): when the binding is successful, the method is called and the method is called before calling onBind(). After the service runs, this method will not be called again.

  • onBind(): This is a crucial way to bind services. After binding the service successfully, the system will call this method. This method must return an IBiner interface type object for communication between the client object and the server

  • onUnbind(): all clients unbind by calling unbindService(). The system calls this method.

  • onDestroy(): the client terminate the help lock and invokes the method after calling the onUnbind() method. The service should implement this method to clean up the occupied resources.

3.3 examples

1. Create service

public class BinderService extends Service {
    private static String TAG="BinderService";
    //Binder object
    private final IBinder mBinder =new LoaclBinder();
    public class LoaclBinder extends Binder{
        BinderService getService(){
            return  BinderService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.v(TAG,"Called onCreate");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.v(TAG,"Called onBind");
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.v(TAG,"Called onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        Log.v(TAG,"Called onDestroy");
        super.onDestroy();
    }

    public Date getDate(){
        Date date =new Date();
        return date;
    }
}

2. Registration services
It can be compared with the registration code of the previous startup type service, which will not be repeated here.

3. Client code

public class MainActivity extends AppCompatActivity {
    //Bound services
    BinderService mService;
    //Binding status
    boolean mBound=false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btnCall=findViewById(R.id.button_call);
        btnCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mBound){
                    //Calling methods in BinderService
                    Date date= mService.getDate();
                    Toast.makeText(MainActivity.this, "Date:"+date.toString(), Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        //Bind BinderService
        Intent intent =new Intent(this,BinderService.class);
        bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //Unbind BinderService
        if(mBound){
            unbindService(mConnection);
            mBound=false;
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //Cast type ibinder - > binderservice
            BinderService.LoaclBinder binder =(BinderService.LoaclBinder)iBinder;
            mService=binder.getService();
            mBound=true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBound=false;
        }
    };
}

4 IntentService

Since the service is in progress in the main thread, it should generate a new thread to perform CPU consuming or blocking operations in the new thread. Developers can implement multithreading in services, but this will increase the difficulty of programming. Therefore, Google provides a special service class IntentService

4.1 IntentService advantages

  • Create a default worker thread to pass all intentions to onStartCommand() after the main thread execution.
  • Create a work queue to pass the intention to the onHandleIntent () method one by one, so that you don't have to worry about multithreading.
  • After all start requests are processed, the service is automatically stopped without calling back the stopSelf () method.
  • Provides the default implementation of onBind(), which returns null
  • Provides a default implementation of onStartCommand(), which sends intentions to the work queue and onHandleIntent in turn

4.1 IntentService instance

public class MyIntentService extends IntentService{
	private static String TAG="MyIntentService";
	public MyIntentService{
		super("MyIntentService");
	}
	@override
	protected void onHandleIntent(Intent intent){
		Log.v(TAG,"call onHandleIntent...");
		synchronized(this){
			try{
				wait(5*1000);
			}catch(Exception e){
			}
		}
	}
}

The above MyIntentService service inherits IntentService and only needs to rewrite the constructor and onHandleIntent methods. Since IntentService creates a default worker thread, the current thread is not the main thread, so waiting for 5 seconds will not block the main thread and ANR problems will not occur. In addition, IntentService does not need to call the stopSelf () method to stop the service. It automatically stops the service after processing all start requests.

The article does not point out the creation of activities, layout code and control binding. You can find relevant videos for basic learning first
The article will continue to update...

Keywords: Java Android Apache

Added by Bailz on Fri, 21 Jan 2022 11:09:05 +0200