Notification usage description 3: Service Update Progress notification & listening to service progress in Activity

Source: Internet
Author: User

The last time we talked about how to implement an updatable progress notification, we started a thread to simulate a download task, and then sent a progress message to the UI thread Message Queue according to the task progress, the UI thread updates the UI of the notification based on the progress message. However, in practical applications, we generally run background tasks that are time-consuming, such as upload and download, in the form of services, and update progress notifications are also handled by background services. However, sometimes, in addition to displaying progress information in the notification, we also need to display the current progress in the activity. Many download systems have such functions, for example, Android built-in Browser Download System and QQ Browser Download System. How can this function be implemented? There are many implementation methods. Let's first introduce one of them today: actively listen to the progress of the Service in the activity.

The specific idea is to bind the activity to the background service, operate the background service through the intermediate object binder instance, obtain the progress information and service status, and stop the service when necessary.

If you are not familiar with the service life cycle, you can check the relevant information. If you have time, I may also summarize some service-related knowledge.

To make the process clearer, let's take a look at the following before coding:

 

The entire process is shown in. After we click the start button, the download task starts to run and the colleague updates the progress of the notification. The current activity also obtains the progress information from the background service and is displayed below the button; after clicking the notification, we will jump to the download management page. Here, we can also get the progress from the background service, and perform operations such as canceling tasks.

After learning about the entire process, let's analyze the specific code implementation.

The first is the layout file/RES/Main. xml:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="start"android:onClick="start"/><TextViewandroid:id="@+id/text"android:layout_width="fill_parent"android:layout_height="wrap_content"android:gravity="center"/></LinearLayout>

The button is used to start the service, and textview is used to display the progress information.

Then let's take a look at the mainactivity. Java code:

Package COM. scott. notification; 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. handler; import android. OS. ibinder; import android. OS. message; import android. view. view; import android. widget. textview; public class mainactivity extends activity {Private downloadservice. downloadbinder binder; private textview text; private Boolean binded; private handler = new handler () {public void handlemessage (Android. OS. message MSG) {int progress = MSG. arg1; text. settext ("downloading... "+ progress +" % ") ;};}; private serviceconnection conn = new serviceconnection () {@ overridepublic void onserviceconnected (componentname, ibinder Service) {Binde R = (downloadservice. downloadbinder) service; binded = true; // start to download the binder. start (); // listener progress information listenprogress () ;}@ overridepublic void onservicedisconnected (componentname name) {}}; @ overridepublic void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); text = (textview) findviewbyid (R. id. text) ;}@ overrideprotected void ondestroy () {super. ondestroy (); If (Binded) {unbindservice (conn) ;}} public void start (view) {If (binded) {binder. start (); listenprogress (); return;} intent = new intent (this, downloadservice. class); startservice (intent); // if you call startservice first, the service will not be destroyed after multiple service binding objects call unbindservice (intent, Conn, context. bind_auto_create);}/*** listener progress */private void listenprogress () {New thread () {public void run () {While (! Binder. iscancelled () & binder. getprogress () <= 100) {int progress = binder. getprogress (); message MSG = handler. obtainmessage (); MSG. arg1 = progress; handler. sendmessage (MSG); If (Progress = 100) {break;} Try {thread. sleep (200);} catch (interruptedexception e) {e. printstacktrace ();}}};}. start ();}}

We can see that after you click the start button, bindservice is used to bind the service and the obtained downloadservice is used. the downloadbinder instance starts the service, and enables a thread in the activity to listen to the progress of the service, timely display to the bottom of the button.

The downloadservice. Java code of the service class is as follows:

Package COM. scott. notification; import android. app. notification; import android. app. icationicationmanager; import android. app. pendingintent; import android. app. service; import android. content. context; import android. content. intent; import android. OS. binder; import android. OS. handler; import android. OS. ibinder; import android. OS. message; import android. widget. remoteviews; public class downloadservice extends Serv Ice {Private Static final int yy_id = 0; private Boolean canceled; private int progress; private context mcontext = This; private icationicationmanager micationicationmanager; private notification mnotification; private downloadbinder binder = new downloadbinder (); Private handler = new handler () {public void handlemessage (Android. OS. message MSG) {Switch (MSG. what) {Case 1: int rate = MSG. arg1; if (Rate <100) {// Update Progress remoteviews contentview = mnotification. contentview; contentview. settextviewtext (R. id. rate, rate + "%"); contentview. setprogressbar (R. id. progress, 100, rate, false);} else {// After downloading, change the notification form to mnotification. flags = notification. flag_auto_cancel; mnotification. contentview = NULL; intent = new intent (mcontext, filemgractivity. class); // indicates that intent has been completed. putextra ("completed", "yes"); // update Parameter. Note that flags must use flag_update_currentpendingintent contentintent = pendingintent. getactivity (mcontext, 0, intent, pendingintent. flag_update_current); mnotification. setlatesteventinfo (mcontext, "download completed", "file downloaded", contentintent); stopself (); // stop the service itself} // do not forget to notify you, otherwise, micationicationmanager will not be updated. Y (yy_id, mnotification); break; Case 0: // cancel notification to micationicationmanager. cancel (policy_id); break ;};};@ overridepublic Void oncreate () {super. oncreate (); mnotificationmanager = (notificationmanager) getsystemservice (Android. content. context. notification_service) ;}@ overridepublic ibinder onbind (intent) {// return the User-Defined downloadbinder instance return binder ;}@ overridepublic void ondestroy () {super. ondestroy (); canceled = true; // cancel download thread}/*** create notification */private void setupnotification () {int icon = R. drawable. down; charsequence TiC Kertext = "Start download"; long when = system. currenttimemillis (); mnotification = new notification (icon, tickertext, when); // put mnotification in the "running" column. flags = notification. flag_ongoing_event; remoteviews contentview = new remoteviews (mcontext. getpackagename (), R. layout. download_icationication_layout); contentview. settextviewtext (R. id. filename, "angrybird.apk"); // specifies the mnotification for the personalized view. contentview = contentview; Intent intent = new intent (this, filemgractivity. class); pendingintent contentintent = pendingintent. getactivity (mcontext, 0, intent, pendingintent. flag_update_current); // specifies the content intent mnotification. contentintent = contentintent; micationicationmanager. Y (policy_id, mnotification);}/*** download module */private void startdownload () {canceled = false; int rate = 0; while (! Canceled & rate <100) {try {// simulate the download progress thread. sleep (500); rate = rate + 5;} catch (interruptedexception e) {e. printstacktrace ();} message MSG = handler. obtainmessage (); MSG. what = 1; MSG. arg1 = rate; handler. sendmessage (MSG); this. progress = rate;} If (canceled) {message MSG = handler. obtainmessage (); MSG. what = 0; handler. sendmessage (MSG );}} /*** downloadbinder defines some practical methods ** @ author user **/public class downloadbinder extends binder {/*** start download */Public void start () {// return the progress to 0 progress = 0; // create a notification setupnotification (); New thread () {public void run () {// download startdownload ();};}. start ();}/*** get progress ** @ return */Public int getprogress () {return progress;}/*** cancel download */Public void cancel () {canceled = true;}/*** canceled? ** @ return */Public Boolean iscancelled () {return canceled ;}}}

We can see that there is a downloadbinder class in the service, which inherits from the binder and defines a series of methods to get the service status and operate on the current service, what we get in mainactivity just now is the instance of this class. Finally, do not forget to configure the service in androidmanifest. xml. For details about the layout file/RES/layout/download_notification_layout.xml of the Progress notification, you do not need to post it here. For details about how to use notification, refer to the specific code of the layout of the Progress notification in step 2.

Next we will introduce filemgractivity, which is the page to jump to after clicking the notification. The layout file/RES/filemgr. XML is as follows:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"><ProgressBar   android:id="@+id/progress"    style="?android:attr/progressBarStyleHorizontal"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:max="100"    android:progress="0"/><Buttonandroid:id="@+id/cancel"android:layout_width="fill_parent"android:layout_height="wrap_content"android:text="cancel"android:onClick="cancel"/></LinearLayout>

Let's take a look at the specific code of filemgractivity. Java:

Package COM. scott. notification; 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. handler; import android. OS. ibinder; import android. OS. message; import android. view. view; import android. widget. button; import android. widget. progressbar; public class Filemgractivity extends activity {private downloadservice. downloadbinder binder; private progressbar; private button cancel; private Boolean binded; private handler = new handler () {public void handlemessage (Android. OS. message MSG) {int progress = MSG. arg1; progressbar. setprogress (Progress); If (Progress = 100) {cancel. setenabled (false) ;};}; private serviceconnection conn = new Ser Viceconnection () {@ overridepublic void onserviceconnected (componentname, ibinder Service) {binder = (downloadservice. downloadbinder) service; // listener progress information listenprogress () ;}@ overridepublic void onservicedisconnected (componentname name) {}}; @ override public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. filemgr); progressbar = (progressbar) Fi Ndviewbyid (R. id. progress); cancel = (button) findviewbyid (R. id. cancel); If ("yes ". equals (getintent (). getstringextra ("completed") {// if it has been completed, you do not need to bind the service progressbar. setprogress (100); cancel. setenabled (false);} else {// bind Service intent = new intent (this, downloadservice. class); bindservice (intent, Conn, context. bind_auto_create); binded = true; }}@ override protected void ondestroy (){ Super. ondestroy (); // if it is bound, unbind if (binded) {unbindservice (conn) ;}} public void cancel (view) {// cancel downloading the binder. cancel ();}/*** listener progress information */private void listenprogress () {New thread () {public void run () {While (! Binder. iscancelled () & binder. getprogress () <= 100) {int progress = binder. getprogress (); message MSG = handler. obtainmessage (); MSG. arg1 = progress; handler. sendmessage (MSG); try {thread. sleep (200);} catch (interruptedexception e) {e. printstacktrace ();}}};}. start ();}}

We found that it is similar to the mainactivity implementation method. Well, they all communicate with the service through the binder object obtained after binding with the service, they actively greet the service to obtain information and control the service.

The two activities and a service seem to have a complex relationship between men and women. Both men like a woman at the same time and try to get love from that woman through their own means. Both men are very active, the woman seems passive.

The above is all of today's content. Maybe my friends may have questions. Can I ask the service to actively inform the activity of the current progress? The answer is yes. Next time, I will share with you how to turn the service into an active party and let a woman foot on two ships.

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.