Article Contents:

1, define,

What is an IntentService?

Official documents:

IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through Context.startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, And stops themselves when it runs out of work. This “Work queue processor” pattern is commonly used to offload tasks from an application’s main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, And stop the service as appropriate. All requests are handled on a single worker thread — they may take as long as it is handled necessary (and will not block the application’s main loop), but only one request will be processed at a time.

From my understanding:

IntentService is a base class of Services that can handle asynchronous requests as needed. The client calls context. startService(Intent) to send a request. IntentService starts as needed, uses a worker thread to handle each Intent in turn, and stops itself when the work fails. This “work queue processing” mode is typically used to lighten the workload on the main thread of an application. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive Intents, start the worker thread, and stop the service as needed. All requests are processed on a worker thread – they may take as long as they want (and do not block the application’s main loop), but only one request can be processed at a time.

IntentService can handle asynchronous requests. The worker thread in IntentService processes each Intent in turn, and only one request at a time. 3, implement onHandleIntent(Intent) to receive the Intent task.

2. IntentService features

(1) With its own working thread, time-consuming operations can be directly executed without ANR problems. (2) Force tasks to be executed in sequence. (3) The IntentService is automatically closed after the task is completed.

3. IntentService usage scenario

IntentService is suitable for handling short-term, lightweight, time-consuming background tasks and tasks that need to be executed sequentially. For example, a task can be completed after uploading a few images in the background, and it needs to be uploaded in order. As a counterexample, things like background music playback are not short-term, lightweight background tasks and are not suitable for IntentService.

4. Example (Kotlin)

4.1 create IntentService

4.1.1 Interpretation of Demo:

Override onHandleIntent(…) Function to start the task according to the incoming Intent action. 2. Provide startActionFoo() and startActionBaz() interfaces for external start tasks. Create handleActionFoo() and handleActionBaz() to handle the task. A 30-second delay was added to both methods to test IntentService’s asynchronous processing capabilities.

4.1.2 Interpretation of work process:

After an external call to startActionFoo() or startActionBaz(), MyIntentService is launched and onHandleIntent(…) is called. OnHandleIntent determines which method to handle first based on the timing of the call. In this example, startActionFoo() is executed first and then startActionBaz() is executed.

 1private const val ACTION_FOO = "blog.intentservice.action.FOO"

2private const val ACTION_BAZ = "blog.intentservice.action.BAZ"

3private const val EXTRA_PARAM = "blog.intentservice.extra.PARAM"

4private const val TAG = "MyIntentService"

5class MyIntentService : IntentService("MyIntentService") {

6    override fun onHandleIntent(intent: Intent?). {

7        when(intent? .action) {

8            ACTION_FOO -> {

9                val param = intent.getStringExtra(EXTRA_PARAM)

10                handleActionFoo(param)

11            }

12            ACTION_BAZ -> {

13                val param = intent.getStringExtra(EXTRA_PARAM)

14                handleActionBaz(param)

15            }

16        }

17    }

18    override fun onCreate(a) {

19        super.onCreate()

20        Log.i(TAG, "onCreate")

21    }

22    override fun onStartCommand(intent: Intent? , flags:Int, startId: Int)Int {

23        Log.i(TAG, "onStartCommand")

24        return super.onStartCommand(intent, flags, startId)

25    }

26    override fun onStart(intent: Intent? , startId:Int) {

27        Log.i(TAG, "onStart")

28        super.onStart(intent, startId)

29    }

30    override fun onDestroy(a) {

31        Log.i(TAG, "onDestroy")

32        super.onDestroy()

33    }

34    / * *

35* Handle the Foo event

36* /


37    private fun handleActionFoo(param: String) {

38        Log.i(TAG, "handleActionFoo")

39        Thread.sleep(30 * 1000// Delay execution for 30 seconds

40        Log.i(TAG, "handleActionFoo end")

41    }

42    / * *

43* Handle Baz events

44* /


45    private fun handleActionBaz(param: String) {

46        Log.i(TAG, "handleActionBaz")

47        Thread.sleep(30 * 1000// Delay execution for 30 seconds

48        Log.i(TAG, "handleActionBaz end")

49    }

50    companion object {

51        var intent: Intent? = null

52        / * *

53* Provides external start startActionFoo event handling

54* /


55        @JvmStatic

56        fun startActionFoo(context: Context, param: String) {

57            intent = Intent(context, MyIntentService::class.java).apply {

58                action = ACTION_FOO

59                putExtra(EXTRA_PARAM, param)

60            }

61            context.startService(intent)

62        }

63        / * *

64* Provides start startActionBaz event handling to the outside world

65* /


66        @JvmStatic

67        fun startActionBaz(context: Context, param: String) {

68            intent = Intent(context, MyIntentService::class.java).apply {

69                action = ACTION_BAZ

70                putExtra(EXTRA_PARAM, param)

71            }

72            context.startService(intent)

73        }

74        / * *

75* Provide stopService externally

76* /


77        fun stopSelfService(context: Context) {

78            if(intent ! =null) {

79                context.stopService(intent)

80            }

81        }

82    }

83}

Copy the code

Finally, don’t forget to register IntentService in androidmanifest.xml

<service 
    android:name="blog.intentservice.MyIntentService"
    android:exported="false" />
Copy the code

4.2 Starting IntentService on the Client

Start the startActionFoo() and startActionBaz() tasks on the client.

1    class TestIntentServiceActivity : AppCompatActivity() {

2        override fun onCreate(savedInstanceState: Bundle?). {

3            super.onCreate(savedInstanceState)

4            setContentView(R.layout.activity_test_intent_service)

5            MyIntentService.startActionFoo(this."task_foo")

6            MyIntentService.startActionBaz(this."task_baz")

7        }

8    }

Copy the code

4.3 Workflow analysis

4.3.1 IntentService Life Cycle

The figure shows the life cycle diagram of a Service. You might wonder why you use a Service lifecycle diagram instead of an IntentService lifecycle diagram. The simple reason is that an IntentService inherits from a Service, so its lifecycle is essentially the same as the Service lifecycle. However, since onBind() returns null by default in IntentService, the Call to bindService content is not needed. For IntentService, we only care about the left side of Call to startService.

4.3.2 Example workflow

Take a look at the complete workflow in this example.

OnCreate – > onStartCommand – > onStart – > handleActionFoo – > onStartCommand – > onStart – > handleActionBaz – > onDestroy

You can identify features in IntentService that execute tasks sequentially and have features that can execute time-consuming tasks. ANR is guaranteed if you use Service to delay execution by 20 seconds.

4.4 Analysis of Special Scenarios

If you force StopService before the handleActionFoo task ends, the current IntentService is destroyed, but its worker thread continues execution. Log printing sequence:

OnCreate -> onStartCommand -> onStart -> handleActionFoo -> onDestroy -> handleActionFoo end

If stopService is forced before the handleActionFoo task ends and handleActionBaz task starts, the two tasks will execute in different worker threads. However, since it is on a different worker thread, there is no way to determine which task completes first.

IntentService source code analysis

Look at the question with a doubt (1) How to implement the worker thread? (2) How to execute tasks in sequence? (3) How to realize the automatic judgment of Service closing time?

5.1 IntentService source

IntentService is a Service that has the same life cycle as a Service. IntentService has a worker thread that executes the task using onHandleIntent.

Note: It is not recommended to start an IntentService with bindService() because onBind() always returns null in IntentService.

  1    public abstract class IntentService extends Service {

2    private volatile Looper mServiceLooper;

3    private volatile ServiceHandler mServiceHandler;

4    private String mName;

5    private boolean mRedelivery;

6    private final class ServiceHandler extends Handler {

7        public ServiceHandler(Looper looper) {

8            super(looper);

9        }

10        @Override

11        public void handleMessage(Message msg) {

12            onHandleIntent((Intent)msg.obj);

13            stopSelf(msg.arg1);

14        }

15    }

16    / * *

17     * Creates an IntentService.  Invoked by your subclass's constructor.

18     *

19     * @param name Used to name the worker thread, important only for debugging.

20* /


21    public IntentService(String name) {

22        super(a);

23        mName = name;

24    }

25    / * *

26     * Sets intent redelivery preferences.  Usually called from the constructor

27     * with your preferred semantics.

28     *

29     * <p>If enabled is true,

30     * {@link #onStartCommand(Intent, int, int)} will return

31     * {@link Service#START_REDELIVER_INTENT}, so if this process dies before

32     * {@link #onHandleIntent(Intent)} returns, the process will be restarted

33     * and the intent redelivered.  If multiple Intents have been sent, only

34     * the most recent one is guaranteed to be redelivered.

35     *

36     * <p>If enabled is false (the default),

37     * {@link #onStartCommand(Intent, int, int)} will return

38     * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent

39     * dies along with it.

40* /


41    public void setIntentRedelivery(boolean enabled) {

42        mRedelivery = enabled;

43    }

44    @Override

45    public void onCreate(a) {

46        // TODO: It would be nice to have an option to hold a partial wakelock

47        // during processing, and to have a static startService(Context, Intent)

48        // method that would launch the service & hand off a wakelock.

49        super.onCreate();

50        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");

51        thread.start();

52        mServiceLooper = thread.getLooper();

53        mServiceHandler = new ServiceHandler(mServiceLooper);

54    }

55    @Override

56    public void onStart(@Nullable Intent intent, int startId) {

57        Message msg = mServiceHandler.obtainMessage();

58        msg.arg1 = startId;

59        msg.obj = intent;

60        mServiceHandler.sendMessage(msg);

61    }

62    / * *

63     * You should not override this method for your IntentService. Instead,

64     * override {@link #onHandleIntent}, which the system calls when the IntentService

65     * receives a start request.

66     * @see android.app.Service#onStartCommand

67* /


68    @Override

69    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {

70        onStart(intent, startId);

71        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;

72    }

73    @Override

74    public void onDestroy(a) {

75        mServiceLooper.quit();

76    }

77    / * *

78     * Unless you provide binding for your service, you don't need to implement this

79     * method, because the default implementation returns null.

80     * @see android.app.Service#onBind

81* /


82    @Override

83    @Nullable

84    public IBinder onBind(Intent intent) {

85        return null;

86    }

87    / * *

88     * This method is invoked on the worker thread with a request to process.

89     * Only one Intent is processed at a time, but the processing happens on a

90     * worker thread that runs independently from other application logic.

91     * So, if this code takes a long time, it will hold up other requests to

92     * the same IntentService, but it will not hold up anything else.

93     * When all requests have been handled, the IntentService stops itself,

94     * so you should not call {@link #stopSelf}.

95     *

96     * @param intent The value passed to {@link

97     *               android.content.Context#startService(Intent)}.

98     *               This may be null if the service is being restarted after

99     *               its process has gone away; see

100     *               {@link android.app.Service#onStartCommand}

101     *               for details.

102* /


103    @WorkerThread

104    protected abstract void onHandleIntent(@Nullable Intent intent);

105}

Copy the code

5.2 How to implement IntentService worker thread?

IntentService creates a HandlerThread in onCreate(), which completes the entire worker thread.

1    @Override

2public void onCreate(a) {

3    super.onCreate();

4    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");

5    thread.start();

6.

7}

Copy the code

5.3 How can I Perform tasks in sequence?

IntentService contains an inner class of ServiceHandler, which is essentially a Handler. We then get the Looper of the HandlerThread in onCreate, associated with the HandlerThread. OnStart (…) is called when the task to be executed is added to IntentService. Function, which then sends the task message to ServiceHandler, forming a message queue, thus ensuring that the tasks are executed in sequence.

 1@Override

2public void onCreate(a) {

3    super.onCreate();

4.

5    mServiceLooper = thread.getLooper();

6    mServiceHandler = new ServiceHandler(mServiceLooper);

7}

8

9private final class ServiceHandler extends Handler {

10    public ServiceHandler(Looper looper) {

11        super(looper);

12    }

13    @Override

14    public void handleMessage(Message msg) {

15        onHandleIntent((Intent)msg.obj);

16        stopSelf(msg.arg1);

17    }

18}

19

20@Override

21public void onStart(@Nullable Intent intent, int startId) {

22    Message msg = mServiceHandler.obtainMessage();

23    msg.arg1 = startId;

24    msg.obj = intent;

25    mServiceHandler.sendMessage(msg);

26}

Copy the code

5.4 How Do I Determine the Time when IntentService Is Automatically Shut down?

In ServiceHandler, stopSelf(…) is actively called every time a task is executed. If the message queue is empty, the execution will continue. If the message queue is empty, the execution will continue.

 1private final class ServiceHandler extends Handler {

2    public ServiceHandler(Looper looper) {

3        super(looper);

4    }

5    @Override

6    public void handleMessage(Message msg) {

7        onHandleIntent((Intent)msg.obj);

8        stopSelf(msg.arg1);

9    }

10}

Copy the code

The above are my views on IntentService, if you have any incorrect understanding, please correct me, learn together and make progress together. Thanks for reading, and I hope you found this article useful.



My name is Lin Chunfeng. I love reading. I am engaged in front-end development in a first-line large factory. Technology: Algorithms, Android Advanced Advanced, Java, Kotlin, Flutter growth management: Personal growth, self-improvement, reading notes, work awareness

Welcome to follow my official number: OAOAAce