Easy Tutorial
❮ Js Call Apply Bind Android Tutorial Sensor1 ❯

4.2.2 Advanced Service

Category Android Basic Tutorial

Introduction to This Section

>

In the previous section, we learned about the lifecycle of Service and the two methods to start a Service. This section continues to delve into IntentService in Service, and demonstrates the implementation of foreground services and polling!


1. Usage of IntentService

After the last section, we already know how to define and start a Service. However, if we directly place a time-consuming thread in the onStart() method of Service, although it can be done, it is likely to cause an ANR exception (Application Not Responding). Android's official documentation on Service includes the following statement:

Direct Translation:

>

  1. Service is not a separate process; it runs in the same process as its application.

Therefore, Android provides us with an alternative to solve the above problem, which is the IntentService we are going to discuss next. IntentService is a class that inherits from Service and handles asynchronous requests. It has a worker thread to handle time-consuming operations, and the request Intents are queued.

Workflow:

>

The client starts IntentService by calling startService(Intent); We do not need to manually control IntentService, as it will stop automatically when the task is completed; IntentService can be started multiple times, and each time-consuming operation will be executed in the onHandleIntent callback method of IntentService in a queue manner, and only one worker thread will be executed at a time, finishing one before moving on to the next!

Next is the code demonstration. Most online examples compare Service with IntentService by defining a long sleep time to demonstrate the ANR exception of Service, and then introduce how good IntentService is! Here, we will not demonstrate Service. Online examples are mostly custom Services, and then Thread.sleep(20000) in the onStart() method to cause an ANR exception. If interested, you can write the code yourself. Here, we will only demonstrate the usage of IntentService!

TestService3.java

public class TestService3 extends IntentService {  
    private final String TAG = "hehe";  
    // Must implement the constructor of the parent class  
    public TestService3()  
    {  
        super("TestService3");  
    }  

    // Must override the core method  
    @Override  
    protected void onHandleIntent(Intent intent) {  
        // Intent is sent from Activity, carrying identification parameters, performing different tasks based on parameters  
        String action = intent.getExtras().getString("param");  
        if(action.equals("s1")) Log.i(TAG, "Starting service1");  
        else if(action.equals("s2")) Log.i(TAG, "Starting service2");  
        else if(action.equals("s3")) Log.i(TAG, "Starting service3");  

        // Let the service sleep for 2 seconds  
        try {  
            Thread.sleep(2000);  
        } catch(InterruptedException e) { e.printStackTrace(); }          
    }  

    // Override other methods to view the sequence of method calls  
    @Override  
    public IBinder onBind(Intent intent) {  
        Log.i(TAG, "onBind");  
        return super.onBind(intent);  
    }  

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

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

    @Override  
    public void setIntentRedelivery(boolean enabled) {  
        super.setIntentRedelivery(enabled);  
        Log.i(TAG, "setIntentRedelivery");  
    }  

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

}

Register Service in AndroidManifest.xml

<service android:name=".TestService3" android:exported="false">  
    &lt;intent-filter >  
        <action android:name="com.test.intentservice"/>  
    </intent-filter>  
</service>

Start the service three times in MainActivity:

public class MainActivity extends Activity {  

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

        Intent it1 = new Intent("com.test.intentservice");  
        Bundle b1 = new Bundle();  
        b1.putString("param", "s1");  
        it1.putExtras(b1);  

        Intent it2 = new Intent("com.test.intentservice");  
        Bundle b2 = new Bundle();  
        b2.putString("param", "s2");  
        it2.putExtras(b2);  

        Intent it3 = new Intent("com.test.intentservice");  
        Bundle b3 = new Bundle();  
        b3.putString("param", "s3");  
        it3.putExtras(b3);  

        // Start IntentService multiple times, each time a new worker thread is created  
        // but there is only one instance of IntentService  
        startService(it1);  
        startService(it2);  
        startService(it3);  
    }  
}

Summary:

>

When a background task needs to be divided into several sub-tasks and executed in order, i.e., asynchronous operations, if we still define a normal Service and then create threads in the onStart method and need to control the threads, it becomes very cumbersome. In this case, we should customize an IntentService and complete the related tasks in the onHandleIntent() method!


2. Communication Between Activity and Service

So far, we have been starting and stopping the Service through the Activity. Suppose we are starting a background download Service, and we want to know the progress of the download tasks in the Service! This requires communication between the Service and the Activity, and the medium for this communication is the onBind() method in the Service! Returning a custom Binder object!

The basic process is as follows:


3. Implementation of a Simple Foreground Service

By now, we know that Service usually runs in the background, but the system priority of Service is still relatively low. When the system memory is insufficient, it may recycle the Service running in the background. In this case, we can use a foreground service to make the Service slightly less likely to be killed by the system, although it may still be killed... A foreground service is a Notification displayed in the status bar.

The implementation is also very simple. The project I recently worked on just used this foreground service, so I extracted the core code and shared it:

In the custom Service class, override the onCreate(), and then customize the Notification according to your needs; after customization, call startForeground(1, notification object) to enable the foreground service! Core code as follows:

public void onCreate()
{
    super.onCreate();
    Notification.Builder localBuilder = new Notification.Builder(this);
    localBuilder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
    localBuilder.setAutoCancel(false);
    localBuilder.setSmallIcon(R.mipmap.ic_cow_icon);
    localBuilder.setTicker("Foreground Service Start");
    localBuilder.setContentTitle("Socket Server");
    localBuilder.setContentText("Running...");
    startForeground(1, localBuilder.build());
}
startForeground(1, localBuilder.getNotification());
}

Screenshot of the running effect:

WeChat Subscription

❮ Js Call Apply Bind Android Tutorial Sensor1 ❯