About using Android Service for the first time

First, understand what is service?

My personal understanding of service is that it is an activity without an interface. It runs some events in the background of your mobile phone that do not need to be displayed to the user. For example: you have clearly exited the app, but some apps will still pop up some information for you; this is actually The activity is logged out, but the app service is not destroyed;

This is just the author’s simple understanding, because he is not specialized in app development, but is forced to do so;-_-//

Without further ado, let’s talk about the main film:

Two forms of service:

Direct enable and bind enable

Previous case:

The first thing to configure in AndroidManifest.xml

 <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ServiceDemo"
        tools:targetApi="31" >
        <activity android:name=".MainActivity"
            android:theme="@style/AppTheme"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <service android:name=".MyService"/>
    </application>

Then make a small demo:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@ + id/button_1"
        android:layout_width="170dp"
        android:layout_height="70dp"
        android:text="Enable service"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />
    <Button
        android:id="@ + id/button_2"
        android:layout_width="170dp"
        android:layout_height="70dp"
        android:text="Stop service"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@ + id/button_1"
        android:layout_marginTop="20dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private Button startService, stopService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        uiInit();
        clickInit();
    }

    private void uiInit(){
        startService = findViewById(R.id.button_1);
        stopService = findViewById(R.id.button_2);
    }

    private void clickInit(){
        startService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "onClick: startClick is Click");
                Intent startIntent = new Intent(MainActivity.this, MyService.class);
                startService(startIntent);
            }
        });
        stopService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "onClick: stopClick is click");
                Intent stopIntent = new Intent(MainActivity.this, MyService.class);
                stopService(stopIntent);
            }
        });
    }
}

Don’t ask why the onclick interface is not used, it’s just lazy to ask^_^||

/**
 * @Author zihaoWang
 * @Data 2023/11/11 14:47
 * @Other Write a comment, write a comment!!!
 * be sure to write a comment and type log!!!
 */
public class MyService extends Service {

    private static final String TAG = "MyService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: onCreate executed");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: is executed");
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: is executed");
    }
}

At this time, you can use the log method to see the characteristics of the service operation. When you open the app for the first time and click to start the service, there will be two logs:

One is onCreate: it will be called when the service is used for the first time.

The other is onStartCommand: it will be called every time the button to start the service is clicked;

Remember: the button to stop the service can only be clicked once, otherwise an error will occur. You can try it;

Isn’t it very simple === But the simpler the thing, there will be problems. It cannot communicate. If you want to communicate, you need to use the binding service

If you want to use the binding service, you definitely want to communicate, so first make some preparations and write a demo.

Don’t touch the previous .xml, just modify MyService and MainActivity.

/**
 * @Author zihaoWang
 * @Data 2023/11/11 14:47
 * @Other Write a comment, write a comment!!!
 * be sure to write a comment and type log!!!
 */
public class MyService extends Service {

    private OtherThing thing = new OtherThing();

    class OtherThing extends Binder{
        public void start(){
            Log.d(TAG, "start: start something executed");
        }
        public int getThing(){
            Log.d(TAG, "getThing: get something executed");
            return 0;
        }
    }


    private static final String TAG = "MyService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: onCreate executed");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: is executed");
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return thing;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: is executed");
    }
}

Note the return in onBind;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private MyService.OtherThing otherThing;

    private Button startService, stopService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        uiInit();
        clickInit();
    }

    private ServiceConnection connection = new ServiceConnection() {

        //Method to handle successful binding
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            if (iBinder instanceof MyService.OtherThing){
                Log.d(TAG, "onServiceConnected: is bind");
                otherThing = (MyService.OtherThing) iBinder;
                otherThing.start();
                otherThing.getThing();
            }
        }

        //Method to handle binding failure
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d(TAG, "onServiceDisconnected: is not bind");
        }
    };

    private void uiInit(){
        startService = findViewById(R.id.button_1);
        stopService = findViewById(R.id.button_2);
    }

    private void clickInit(){
        startService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "onClick: startClick is Click");
                Intent bindIntent = new Intent(MainActivity.this, MyService.class);
                bindService(bindIntent, connection, BIND_AUTO_CREATE);//Start binding
            }
        });
        stopService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "onClick: stopClick is click");
                unbindService(connection);
            }
        });
    }
}

Then start running:

Click to start the service and there will be three logs:

Then there will be no log if you keep clicking to start the service.

When stopping service:

Similarly, you can only click once when the service is stopped;