Android Basics - Service Basics

Android Basics - Service Basics

This blog is actually a reprinted version of the four major components of Android - Service background service, foreground service, IntentService, cross-process service, barrier-free service, and system service . The author has analyzed various scenarios based on Service in place, such as To be added later if necessary

The basic knowledge of Service in this blog includes: Service background service, foreground service, IntentService, cross-process service, system service

1.1 Service background service

There are two ways to start the Service background service, startSevice() and bindService(). bindService can return a proxy object, which can call methods in the Service and obtain the returned results. Activity has nothing to do with BroadCast, let alone interact with them

1.1.1 Non-interactive background services

When we start the service through startService, the started Service cannot be a non-interactive background service.
Its life cycle is onCreate, onStartCommond, and onDestroy:
When we start the Service for the first time, the onCreate() method will be called back when the Service is created for the first time. , and then call back the onStartCommand() method. When you startService() again, you can only execute onStartCommand() once. Once the service is started, you need to pass the stopService() or stopSelf() method to shut down the service. At this time, onDestroy will be called back. ()method

  • Creating a service class
    Creating a service is very simple, just inherit from Service and implement the onBind() method
public class BackGroupService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("Service","onBind");
        return null;
    }

    @Override
    public void onCreate() {
        Log.e("Service","onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("Service","onStartCommand");
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    Log.e("Service","doSomething");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e("Service","onDestroy");
        super.onDestroy();
    }
}
  • The configuration service
    Service is also one of the four major components, so it must be configured in the manifests
<service android:name=".Service.BackGroupService"/>
  • Start and stop services
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button bt_open, bt_close;
    private Intent intent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt_open = findViewById(R.id.open);
        bt_close = findViewById(R.id.stop);
        bt_open.setOnClickListener(this);
        bt_close.setOnClickListener(this);
        intent = new Intent(this,BackGroupService.class);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.open:
                startService(intent);
                break;
            case R.id.stop:
                stopService(intent);
                break;
            default:
                break;
        }
    }
}

When you turn on the service, there is another way to turn off the service. In the settings, go through the application -> find your own application -> stop
write picture description here

After running the program, we clicked start service, then clicked start service again, and then shut down the service after a while. We use Log information to verify the life cycle of a common Service: onCreate->onStartCommand->onStartCommand->onDestroy

05-09 09:19:33.774 3729-3729/com.example.cxy.testservice E/Service: onCreate
05-09 09:19:33.775 3729-3729/com.example.cxy.testservice E/Service: onStartCommand
05-09 09:19:33.778 3729-4309/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.054 3729-4223/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.215 3729-3935/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.244 3729-3946/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.363 3729-3948/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.378 3729-3729/com.example.cxy.testservice E/Service: onStartCommand
05-09 09:19:34.378 3729-4310/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.394 3729-4224/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.581 3729-3933/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.746 3729-3915/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.835 3729-3947/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.883 3729-3916/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.896 3729-3875/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:34.957 3729-3729/com.example.cxy.testservice E/Service: onDestroy
05-09 09:19:35.007 3729-3899/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:35.107 3729-4222/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:35.174 3729-3905/com.example.cxy.testservice E/Service: doSomething
05-09 09:19:35.324 3729-3934/com.example.cxy.testservice E/Service: doSomething

It can be seen that onCreate->onStartCommand will be called when the service is started for the first time, only onStartCommand will be called when the service is started again, and onDestroy will be called back when the service is closed.

Among them, you will find that even if our Service has been closed, the infinite loop operation performed by the child thread always exists, and the method to close the infinite loop of the child thread is to completely exit the application

1.1.2 Interactive background services

The interactive background service refers to the method that the foreground page can call the background service. The implementation steps of the interactive background service are the same as those of the non-interactive background service. The difference lies in the way of starting and obtaining the proxy object of the Service.

  • The difference between creating a service class
    and ordinary Service is that the Binder inheritance class is constructed as the proxy object of the Service. The instance of the proxy object is returned in onBind, and it is returned to the front desk for acquisition, that is, the front desk can obtain the method of the proxy object to execute the background service.
public class BackGroupService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("Service","onBind");
        return new MyBinder();
    }

    /**
     * 代理类
     */
    public class MyBinder extends Binder {
        public void showToast(){
            Log.e("Service","showToast");
        }
        public void showList(){
            Log.e("Service","showList");
        }
    }

    /**
     * 解除绑定服务时调用
     * @param intent
     * @return
     */
    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("Service","onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        Log.e("Service","onCreate");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.e("Service","onDestroy");
        super.onDestroy();
    }
}
  • configuration service
<service android:name=".Service.BackGroupService"/>
  • Binding and unbinding services
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button bt_open, bt_close;
    private Intent intent;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt_open = findViewById(R.id.open);
        bt_close = findViewById(R.id.stop);
        bt_open.setOnClickListener(this);
        bt_close.setOnClickListener(this);
        intent = new Intent(this,BackGroupService.class);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.open:
                bindService(intent,conn,BIND_AUTO_CREATE);
                break;
            case R.id.stop:
                unbindService(conn);
                break;
            default:
                break;
        }
    }

    ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 拿到后台服务代理对象
            BackGroupService.MyBinder myBinder = (BackGroupService.MyBinder) service;
            // 调用后台服务的方法
            myBinder.showToast();
            myBinder.showList();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
}

The difference between this and startService is that there is an additional ServiceConnection object, which is the callback of the background service proxy object after the user binds the background service. We can get the proxy object of the background service through this callback and call the background service definition. It also realizes the interaction between the background service and the foreground.
The service service is started with the bindService method, and the unbindService
BIND_AUTO_CREATE is used to indicate that the service is automatically created after the activity and the service are bound, which will make the onCreate and onBind methods of BackGroupService to be executed.

  • Running the code After
    running the program, we hit bind service, and then unbind the service after a while. We use the log information to verify the service life cycle: onCreate->onBind->onUnBind->onDestroy, we can also see that we call the methods showToast and showList of the background service, so the callback of onStartCommand is no longer executed
05-09 09:49:23.235 5594-5594/com.example.cxy.testservice E/Service: onCreate
05-09 09:49:23.236 5594-5594/com.example.cxy.testservice E/Service: onBind
05-09 09:49:23.241 5594-5594/com.example.cxy.testservice E/Service: showToast
05-09 09:49:23.241 5594-5594/com.example.cxy.testservice E/Service: showList
05-09 09:49:32.476 5594-5594/com.example.cxy.testservice E/Service: onUnbind
05-09 09:49:32.476 5594-5594/com.example.cxy.testservice E/Service: onDestroy

1.2 Background services for hybrid interactions

Maybe you will be confused, what is the relationship between startService and bindService? In fact, to put it simply, there is no relationship between the two. Similar to twins, there is only a pure blood relationship. So the question is, can these two startup methods be used at the same time? The answer is yes.
Combining the above two startup methods is a hybrid interactive background service, that is, you can run the background service alone, or you can run the background service. Provided method How can the service be destroyed in
this case? According to the mechanism of the Android system, as long as a service is started or bound, it will always be running. The service must be destroyed if the above two conditions are not satisfied at the same time. In this case, stopService must be called at the same time. () and unbindService() methods, the onDestroy() method will be executed

1.3 Front desk service

Since the priority of the background service is relatively low, it may be recycled when the system runs out of memory, so the foreground service is to make up for this shortcoming, and it can keep running without being recycled by the system. For example: ink weather forecast in the status bar
write picture description here

  • Creating a service class The creation of a
    foreground service is very simple. In fact, a Notification is created on the basis of the Service, and then the startForeground() method of the Service can be used to start the foreground service.
public class ForegroundService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void onCreate() {
        super.onCreate();
        showNotification();
    }

    /**
     * 启动前台通知
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    private void showNotification() {
        // 创建点击跳转Intent
        Intent intent = new Intent(this,MainActivity.class);
        // 创建跳转PendingIntent
        PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);
        // 创建通知详细信息并构建通知
        Notification notification = new Notification.Builder(this)
                .setContentTitle("2018年5月9日")
                .setContentText("今天天气晴朗,15到29度")
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
                .setContentIntent(pi)
                .build();
        // 获取通知服务
        NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        // 显示通知
        nm.notify(0,notification);
        // 启动为前台服务
        startForeground(0,notification);
    }
}
  • configuration service
<service android:name=".Service.ForegroundService"/>
  • Start foreground service
startService(new Intent(this, ForegroundService.class));
  • Running the code
    we can see that the status bar has indeed added our notification
    write picture description here

When we exit and kill the program, by setting->application->select the running application, we can find that our program is exited and killed, and the service is still in progress
write picture description here

1.4 IntentService

IntentService is specially used to solve the problem that time-consuming operations cannot be performed in Service. It is also very simple to create an IntentService. As long as you inherit IntentService and override the onHandlerIntent function, you can perform time-consuming operations in this function.

  • service class
public class TheIntentService extends IntentService {

    public TheIntentService() {
        super("TheIntentService"); // 调用父类的有参构造函数
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        // 在这里执行耗时操作
        Log.e("TheIntentService","onHandleIntent");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("TheIntentService","onDestroy");
    }
}

Here, a parameterless constructor is provided first, and the parameterized constructor of the parent class must be called inside it, and then the abstract method onHandleIntent() is implemented in the subclass, where some specific logic can be processed without using Worry about the ANR problem, because this method is already running in the subclass, the service should stop automatically after the operation ends, so we rewrite the onDestroy() method

  • Run the code
    Click to start the service, and the service will automatically stop after the service is executed.
05-09 11:50:50.326 7113-7308/com.example.cxy.testservice E/TheIntentService: onHandleIntent
05-09 11:50:50.329 7113-7113/com.example.cxy.testservice E/TheIntentService: onDestroy

1.5 AIDL cross-process service

1.6 System Services

The system service provides many convenient services, such as inquiring about Wi-Fi, network status, inquiring battery power, inquiring volume, inquiring package name, inquiring application information, etc. For details, you can query documents with confidence. Here are some common services.

  • Determine if Wifi is on
WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
boolean enabled = wm.isWifiEnabled();

permission required

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
  • Get system maximum volume
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
int max = am.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);
  • Get the current volume
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
int current = am.getStreamMaxVolume(AudioManager.STREAM_RING);
  • Determine if the network is connected
ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
boolean isAvailable = info.isAvailable();

permission required

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326359424&siteId=291194637