Communication between Android service and Activity

Source: Internet
Author: User

Reprinted please indicate the address http://blog.csdn.net/xiaanming/article/details/9750689


In Android, activity is mainly responsible for displaying front-end pages, and service is mainly responsible for tasks that require long-term running. Therefore, in actual development, communication between activity and service is often encountered, we generally start the background service in the activity and start it through intent. In intent, we can pass data to the service. When the service executes some operations, we want to update the UI thread, what should we do? Next, I will introduce two methods to implement communication between the service and the activity.

  • Binder object

When the activity calls bindservice (intent service, serviceconnection Conn, int flags), we can get an object instance of a service, and then we can access the methods in the service, let's take a look at it through an example. A small example of simulated download will show you how to communicate through the binder.

First, create a project communication, and then create a service class.

Package COM. example. communication; import android. app. service; import android. content. intent; import android. OS. binder; import android. OS. ibinder; maximum value of the public class msgservice extends Service {/*** progress bar */public static final int max_progress = 100; /*** progress bar value */private int progress = 0;/*** adds the get () method, for the activity to call * @ return download progress */Public int getprogress () {return progress;}/*** to simulate the download task, which is updated every second */Public void startdownload () {New thread (New runnable () {@ overridepublic void run () {While (Progress <max_progress) {progress ++ = 5; try {thread. sleep (1000);} catch (interruptedexception e) {e. printstacktrace ();}}}}). start ();}/*** returns a binder object */@ overridepublic ibinder onbind (intent) {return New msgbinder ();} public class msgbinder extends binder {/*** get the instance of the current service * @ return */Public msgservice getservice () {return msgservice. this ;}}}

The above code is relatively simple, and the comments are more detailed. The most basic service application, I believe you can understand, we call the startdownload () method to simulate the download task, then update the progress every second, but this is in progress in the background and we cannot see it, so sometimes we need him to display the download progress on the foreground, so we will use the activity next.

Intent intent = new Intent("com.example.communication.MSG_ACTION");  bindService(intent, conn, Context.BIND_AUTO_CREATE);

Through the above Code, we have bound a service in the activity. We need a serviceconnection object, which is an interface. Here we use an anonymous internal class.

Serviceconnection conn = new serviceconnection () {@ overridepublic void onservicedisconnected (componentname name) {}@ overridepublic void onserviceconnected (componentname name, ibinder Service) {// return a msgservice object msgservice = (msgservice. msgbinder) Service ). getservice ();}};

In the onserviceconnected (componentname, ibinder Service) callback method, a binder object in msgservice is returned. We can get a msgservice object through the getservice () method, then you can call some methods in msgservice. the activity code is as follows:

Package COM. example. communication; import android. app. activity; import android. content. componentname; import android. content. context; import android. content. intent; import android. content. serviceconnection; import android. OS. bundle; import android. OS. ibinder; import android. view. view; import android. view. view. onclicklistener; import android. widget. button; import android. widget. progressbar; public class mainactivity extends activity {private msgservice; private int progress = 0; private progressbar mprogressbar; @ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); // bind serviceintent intent = new intent ("com. example. communication. msg_action "); bindservice (intent, Conn, context. bind_auto_create); mprogressbar = (progressbar) findviewbyid (R. id. progressbar1); button mbutton = (button) findviewbyid (R. id. button1); mbutton. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// start to download msgservice. startdownload (); // listener progress listenprogress () ;}});}/*** listener progress. The getprogress () method of msgservice is called every second to obtain the progress, update UI */Public void listenprogress () {New thread (New runnable () {@ overridepublic void run () {While (Progress <msgservice. max_progress) {progress = msgservice. getprogress (); mprogressbar. setprogress (Progress); try {thread. sleep (1000);} catch (interruptedexception e) {e. printstacktrace ();}}}}). start ();} serviceconnection conn = new serviceconnection () {@ overridepublic void onservicedisconnected (componentname) {}@ overridepublic void onserviceconnected (componentname name, ibinder Service) {// return a msgservice object msgservice = (msgservice. msgbinder) Service ). getservice () ;};@ overrideprotected void ondestroy () {unbindservice (conn); super. ondestroy ();}}

In fact, I still have some doubts about the above Code, that is, the method for listening for progress changes. I update the UI directly in the thread, not to say that I cannot update the UI operation in other threads, maybe progressbar is special. I didn't study its source code either. If you know it, please let me know. Thank you!

The above code completes the UI update operation on the service, but you find that no. Every time we call getprogress () to obtain the progress value, then call the getprogress () method every second. Do you think it is passive? Can there be a way when the progress of the service changes active notification activity, the answer is yes, we can use the callback interface to achieve active service notification, do not understand the callback method can look at the http://blog.csdn.net/xiaanming/article/details/8703708

Create a callback Interface

public interface OnProgressListener {void onProgress(int progress);}

The msgservice code has some minor changes. To make it easier for everyone to understand, I still paste all the code.

Package COM. example. communication; import android. app. service; import android. content. intent; import android. OS. binder; import android. OS. ibinder; maximum value of the public class msgservice extends Service {/*** progress bar */public static final int max_progress = 100; /*** progress bar value */private int progress = 0;/*** callback interface for updating progress */private onprogresslistener; /*** registers the callback Interface Method for external calls * @ Param onprogresslistener */PU BLIC void setonprogresslistener (onprogresslistener) {This. onprogresslistener = onprogresslistener;}/*** added the get () method for the activity to call the * @ return download progress */Public int getprogress () {return progress ;} /*** simulate download task, updated every second */Public void startdownload () {New thread (New runnable () {@ overridepublic void run () {While (Progress <max_progress) {progress + = 5; // notify the caller if (onprogresslistener! = NULL) {onprogresslistener. onprogress (Progress);} Try {thread. sleep (1000);} catch (interruptedexception e) {e. printstacktrace ();}}}}). start ();}/*** returns a binder object */@ overridepublic ibinder onbind (intent) {return New msgbinder ();} public class msgbinder extends binder {/*** get the instance of the current service * @ return */Public msgservice getservice () {return msgservice. this ;}}}

The code in the activity is as follows:

Package COM. example. communication; import android. app. activity; import android. content. componentname; import android. content. context; import android. content. intent; import android. content. serviceconnection; import android. OS. bundle; import android. OS. ibinder; import android. view. view; import android. view. view. onclicklistener; import android. widget. button; import android. widget. progressbar; public class mainactivity extends activity {private msgservice; private progressbar mprogressbar; @ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); // bind serviceintent intent = new intent ("com. example. communication. msg_action "); bindservice (intent, Conn, context. bind_auto_create); mprogressbar = (progressbar) findviewbyid (R. id. progressbar1); button mbutton = (button) findviewbyid (R. id. button1); mbutton. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// start to download msgservice. startdownload () ;}}) ;}serviceconnection conn = new serviceconnection () {@ overridepublic void onservicedisconnected (componentname) {}@ overridepublic void onserviceconnected (componentname name, ibinder Service) {// return a msgservice object msgservice = (msgservice. msgbinder) Service ). getservice (); // registers the callback interface to receive changes in the download progress of msgservice. setonprogresslistener (New onprogresslistener () {@ overridepublic void onprogress (INT progress) {mprogressbar. setprogress (Progress) ;}}) ;};@ overrideprotected void ondestroy () {unbindservice (conn); super. ondestroy ();}}

Is it more convenient to use the callback interface? When the progress changes, the Service actively notifies the activity, and the activity can update the UI operation.

  • Broadcast

When our progress changes, we send a broadcast, register the broadcast receiver in the activity, and update the progressbar after receiving the broadcast. The Code is as follows:

Package COM. example. communication; import android. app. activity; import android. content. broadcastreceiver; import android. content. context; import android. content. intent; import android. content. intentfilter; import android. OS. bundle; import android. view. view; import android. view. view. onclicklistener; import android. widget. button; import android. widget. progressbar; public class mainactivity extends activity {private progressbar mprogressbar; private intent mintent; private msgreceiver; @ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); // dynamically register the broadcast receiver msgreceiver = new msgreceiver (); intentfilter = new intentfilter (); intentfilter. addaction ("com. example. communication. receiver "); registerreceiver (msgreceiver, intentfilter); mprogressbar = (progressbar) findviewbyid (R. id. progressbar1); button mbutton = (button) findviewbyid (R. id. button1); mbutton. setonclicklistener (New onclicklistener () {@ overridepublic void onclick (view v) {// start the service mintent = new intent ("com. example. communication. msg_action "); startservice (mintent) ;}}) ;}@ overrideprotected void ondestroy () {// stop service stopservice (mintent); // cancel broadcast unregisterreceiver (msgreceiver ); super. ondestroy ();}/*** broadcast receiver * @ author Len **/public class msgreceiver extends broadcastreceiver {@ overridepublic void onreceive (context, intent) {// get progress, update uiint progress = intent. getintextra ("progress", 0); mprogressbar. setprogress (Progress );}}}


Package COM. example. communication; import android. app. service; import android. content. intent; import android. OS. ibinder; maximum value of the public class msgservice extends Service {/*** progress bar */public static final int max_progress = 100; /*** progress bar value */private int progress = 0; private intent = new intent ("com. example. communication. receiver ");/*** simulate download task, updated every second */Public void startdownload () {New thread (New runnable () {@ overridepublic void run () {While (Progress <max_progress) {progress + = 5; // send the action as COM. example. communication. the broadcast intent of the receiver. putextra ("progress", progress); sendbroadcast (intent); try {thread. sleep (1000);} catch (interruptedexception e) {e. printstacktrace ();}}}}). start () ;}@ overridepublic int onstartcommand (intent, int flags, int startid) {startdownload (); return Super. onstartcommand (intent, flags, startid) ;}@ overridepublic ibinder onbind (intent) {return NULL ;}}

Summary:

  1. Activity calls the bindservice (intent service, serviceconnection Conn, int flags) method to obtain a reference to the service object. In this way, the activity can directly call the method in the service. If you want to actively notify the activity, we can use the callback Method
  2. The Service sends messages to the activity. You can use broadcast. Of course, the activity must register the corresponding receiver. For example, it is better to use this method to send the same message to multiple activities.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.