Android Service fully resolves everything you need to know about the service (bottom)

Source: Internet
Author: User

Article reprinted to: http://blog.csdn.net/guolin_blog/article/details/9797169

This is written by Guo Lin .... is to write "the first line of code," The Great Man, Master is the master, and the master wrote the article compared to his own poor very much

The article is very well written ... Feel oneself also can not write so good introduction service article, hope more reprint, let more people see

In the previous article, we learned many important things about Android service, including the basic usage of service, communication between service and activity, how the service was destroyed, service-to-thread relationships, And how to create a foreground service. The above-mentioned points of knowledge basically cover the service technologies that may be used in most of the daily development work. There is, however, a more high-end usage of the service, which is not introduced, that is, the use of remote service. Using remote service can even enable Android cross-process communication, let's take a concrete look at the following.

If you have not read the previous article, it is recommended to read the Android service full resolution, about the service you need to know everything (above),

Http://www.cnblogs.com/yangfengwu/p/7802140.html

Because the code involved in this article was modified on the basis of the previous article.

As we know in the previous article, the service is actually running on the mainline thread, and if you are dealing with some time-consuming logic directly in the service, it will cause the program to be ANR.

Let's do an experiment to verify that, modify the Servicetest project created in the previous article, and let the thread sleep for 60 seconds in the MyService OnCreate () method, as follows:

public class MyService extends Service {        ...        @Override      void onCreate () {          super.oncreate ();          LOG.D (TAG, "onCreate () executed");          try {thread.sleep (60000catch       

After re-running, click on the Start Service button or the BIND service button, the program will block and can not do anything else, after a period of time will pop up the ANR prompt box, as shown in.

As we mentioned before, you should open threads in the service to perform time-consuming tasks, so that you can effectively avoid the emergence of ANR.

So the topic of this article is to introduce the use of remote service, if you convert MyService to a remote service, will there be a case of ANR? Let's try it out.

Converting a normal service to a remote service is simply a matter of specifying the Android:process property of the service when it is registered: remote is ready, and the code is as follows:

<?xml version= "1.0" encoding= "Utf-8"?> <manifest  xmlns:android= "http://schemas.android.com/apk/res/ Android "      package=" com.example.servicetest "      android:versioncode=" 1 "      android:versionname = "1.0" > ...            <service          android:name= "Com.example.servicetest.MyService"      

Now rerun the program and click on the Start Service button and you will see that the console immediately prints the OnCreate () executed information, and the main interface is not blocked or ANR. After about a minute, you'll see Onstartcommand () executed printed out.

Why does converting myservice to remote service not cause program ANR? This is because, after using the remote service, MyService is already running in another process, so it only blocks the main thread in the process and does not affect the current application.

To confirm that MyService is now running in another process, we add a row of logs to the Mainactivity OnCreate () method and MyService's OnCreate () method to print out the respective process ID. As shown below:

LOG.D ("TAG", "Process ID is" + process.mypid ());  

Rerun the program again, then click the Start Service button to print the results as shown:

Can see, not only the process ID is different, even the application package name is not the same, the MyService printed in the log, the package name followed by: remote identification.

Now that the remote service is so good, we'll turn all the service into a remote service and save the thread. In fact, remote service is not easy to use, even can be said to be more difficult. In general, if you can not use remote service, try not to use it.

Let's take a look at its drawbacks, first myservice the OnCreate () method to get rid of the thread sleep code, then rerun the program, and click the Bind Service button, you will find the program crashes! Why does clicking on the Start Service button program not crash, and clicking on the Bind service button will crash? This is due to the connection of Mainactivity and MyService in the Click event of the Bind service button, but currently MyService is already a remote service, Activity and service run in two different processes, and you can no longer use the traditional form of association, and the program crashes.

So how do you get activity to associate with a remote service? This will use Aidl for cross-process communication (IPC).

Aidl (Android Interface definition Language) is the meaning of the Android Interface Definition language, which can be used to communicate across processes between a service and multiple application components. This enables multiple applications to share the same service functionality.

Let's take a closer look at how Aidl's usage is going to be. You first need to create a new Aidl file that defines how the activity needs to communicate with the service. Create a new Myaidlservice.aidl file with the code as follows:

Package com.example.servicetest;  Interface Myaidlservice {      int plus (int b);      String toUpperCase (String str);  }    

When you click Save, a corresponding Java file is generated in the Gen directory, as shown in:

Then modify the code in the MyService to implement the Myaidlservice interface that we just defined, as follows:

public class MyService extends Service {... @Override public ibinder onbind (Intent Intent) {return Mbinder; } myaidlservice.stub Mbinder = new Stub () {@O Verride public string toUpperCase (String str) throws RemoteException { if (str! = nullreturn< Span style= "COLOR: #000000" > Str.touppercase (); } return nullint Plus (int A, int< Span style= "COLOR: #000000" > b) throws RemoteException {return a + b; } }; }  

First, the myaidlservice.stub is implemented, and the two methods of toUpperCase () and plus () are rewritten. The effect of these two methods is to convert all of a string into uppercase and add two incoming integers. The implementation of the myaidlservice.stub is then returned in the Onbind () method. Why do you write this here? Because the stub is actually a subclass of binder, the implementation of the stub can be returned directly in the Onbind () method.

Next, modify the code in Mainactivity as follows:

public class Mainactivity extends Activity implements Onclicklistener {private Button startservice;        Private Button StopService;        Private Button Bindservice;            Private Button Unbindservice;        Private Myaidlservice Myaidlservice; Private Serviceconnection connection =NewServiceconnection () {@Override publicvoid onservicedisconnected (componentname name) {} @Override public void onserviceconnected (Compone Ntname name, IBinder service) {myaidlservice = MyAIDLService.Stub.asInterface (service); try {int result = Myaidlservice.plus (3, 5 result); LOG.D ("TAG", "Upperstr is" + UPPERSTR);} catch (remoteexception e) {e.printstacktrace ();}}; ...... } 

We just modified the code in the Serviceconnection. As you can see, the MyAIDLService.Stub.asInterface () method is used first to transfer the incoming IBinder object to the Myaidlservice object. You can then invoke all the interfaces defined in the Myaidlservice.aidl file. Here we call the plus () method, pass in 3 and 5 as arguments, then call the toUpperCase () method, pass in the Hello World string as the argument, and finally print the return result of the calling method.

Now rerun the program and click on the Bind service button to see the print log as follows:

Thus, we have indeed successfully implemented cross-process communication, and in one process access to a method in another process.

But you can also see that the current cross-process communication does not actually have any real effect, because it is just a method of invoking the service of the same application in one activity. The real significance of the step-by-step communication is to allow one application to access the service in another application to realize the functionality of the shared service. So here's a natural way to learn how to invoke MyService in other applications.

As we have already learned in the previous article, if you want to associate activity with a service, you need to call the Bindservice () method and pass intent as a parameter, specifying the service to bind in the intent, the sample code is as follows:

New Intent (This, MyService.  Class);  Bindservice (bindintent, Connection, bind_auto_create);    

Here, when building intent, you use Myservice.class to specify which service to bind to, but when you bind the service in another application, you do not myservice the class, you must use implicit intent. Now modify the code in Androidmanifest.xml and add an action to MyService as follows:

<?XML version= "1.0" encoding= "Utf-8"?><ManifestXmlns:android= "Http://schemas.android.com/apk/res/android"Package= "Com.example.servicetest"Android:versioncode= "1"Android:versionname= "1.0">......<ServiceAndroid:name= "Com.example.servicetest.MyService"  android:process< Span style= "COLOR: #0000ff" >= ": Remote" > <intent-filter> <action android:name= " Com.example.servicetest.MyAIDLService "/> </< Span style= "COLOR: #800000" >intent-filter> </< Span style= "COLOR: #800000" >service> </manifest>        

This means that MyService can respond to intent with com.example.servicetest.MyAIDLService action.

Now run the program again, so that the remote service side of the work is all done.

Then create a new Android project named Clienttest, and we'll try to call the MyService method remotely in this program.

Activity in Clienttest is not difficult if you want to connect with MyService, The first thing you need to do is copy the Myaidlservice.aidl file from the Servicetest project, and note that the original package path is copied together, and the structure of the completed project is as shown here:

Then open or create a new activity_main.xml, and add a BIND service button to the layout file:

<LinearLayoutXmlns:android= "Http://schemas.android.com/apk/res/android"Android:layout_width= "match_parent"  Android:layout_height=" match_parent " Android:orientation=" Vertical "> <button android:id= "@+id/bind_service"  Android:layout_width= "match_parent"  Android:layout_height=" wrap_content " Android:text= "Bind Service" /> </linearlayout>  

Next open or create a new mainactivity, in which the associated code is joined and MyService, as follows:

PublicClass MainactivityExtendsActivity {PrivateMyaidlservice Myaidlservice;Private Serviceconnection connection =NewServiceconnection () {@OverridePublicvoidonservicedisconnected (componentname name) {} @OverridePublicvoidonserviceconnected (componentname name, IBinder service) {Myaidlservice =MyAIDLService.Stub.asInterface (service);Try{int result = Myaidlservice.plus (50, 50); String upperstr = Myaidlservice.touppercase ("comes from Clienttest"); LOG.D ("TAG", "result is" +result); LOG.D ("TAG", "Upperstr is" +UPPERSTR); }Catch (remoteexception e) {e.printstacktrace ();}} }; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate ( Savedinstancestate); Setcontentview (R.layout.activity_main); Button Bindservice = (Button) Findviewbyid (R.id.bind_service); Bindservice.setonclicklistener (new Onclicklistener () { @Override public void OnClick (View v) {Intent Intent = new Intent ("Com.example.servicetest.MyAIDLService" Span style= "color: #000000"); Bindservice (Intent, connection, bind_auto_create); } }); } } 

This part of the code is bound to be very familiar with you? Yes, this is almost identical to the code in Servicetest's mainactivity, but we used the implicit intent when the activity and service were connected. The intent action is specified as a com.example.servicetest.MyAIDLService.

After the current activity and MyService have been associated, we are still calling the plus () and toUpperCase () methods, and the remote MyService will process the incoming parameters and return the results, and then print the results.

In this case, the code in the Clienttest is complete, now run the project, then click the Bind Service button, and then go to the remote MyService to establish an association, observe the print information in Logcat as follows:

Needless to say, as everyone has seen, our cross-process communication capabilities have been perfectly implemented.

One thing to note, however, is that because this is a data transfer between different processes, Android's format support for this kind of data is very limited and basically only passes Java's basic data type, string, list, or map. So what if I want to pass a custom class? This must allow the class to implement the Parcelable interface, and to define a aidl file with the same name for the class. This part of the content is not complex, and service relationship is not very small, so it is no longer explained in detail, interested friends can check the relevant information on their own.

Well, combining the top and bottom two, that's all you need to know about the service.

Android Service full resolution, everything you need to know about the service (bottom)

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.