390 likes | 552 Views
Chapter 8 Building and Consuming Services. Lecturer: Prof.Luqun Li ( liluqun@gmail.com ) Teaching Assistants: Fengyou Sun, Haijun Yang, Ting Sun. 1. HTTP Services. 2. Android Services. Contents. Consuming HTTP Services. Android applications pull information from various sources
E N D
Chapter 8 Building and Consuming Services Lecturer: Prof.Luqun Li (liluqun@gmail.com) Teaching Assistants: Fengyou Sun, Haijun Yang, Ting Sun
1 HTTP Services 2 Android Services Contents
Consuming HTTP Services • Android applications pull information from various sources • A common integration strategy is to use HTTP • The Apache HttpClient is a comprehensive HTTP client, HTTP GET and POST
HttpClient for HTTP GET Requests • Pattern for using HttpClient: • 1. Create an HttpClient (or get an existing reference). • 2. Instantiate a new HTTP method, such as PostMethod or GetMethod . • 3. Set HTTP parameter names/values. • 4. Execute the HTTP call using the HttpClient. • 5. Process the HTTP response.
Limitations of HttpGet • Pass name/value parameters as part of the request by appending name/value pairs to the URL: • HttpGet request = new HttpGet("http://somehost/WS2/Upload.aspx?one=valueGoesHere"); • client.execute(request); • Length of a URL should be kept below 2,048 characters,use HTTP POST instead.
HttpClient for HTTP POST Requests • Making an HTTP POST call is very similar to making an HTTP GET call.
Multipart Example • To do multipart POST calls, you need to get three additional Apache open source projects: Apache Commons IO, Mime4j, and HttpMime. • Commons IO:http://commons.apache.org/io/ • Mime4j: http://james.apache.org/mime4j/ • HttpMime: http://hc.apache.org/downloads.cgi (inside of HttpClient)
Dealing with Exceptions • transport exceptions • detecting transport issues and retrying requests by HttpClient • protocol exceptions • flushed out during development • Timeouts • you’ll have to deal with
Effective approach • A simple and effective approach to dealing with both types of timeouts—connection timeouts and socket timeouts—is to wrap the execute() method of your HTTP request with a try / catch and then retry if a failure occurs.
Addressing Multithreading Issues • Create one HttpClient for the entire application and all HTTP communication • Pay attention to multithreading issues when making simultaneous requests through the same HttpClient • HttpClient provides facilities that make this easy—create the DefaultHttpClient using a ThreadSafeClientConnManager
Singleton pattern • A singleton class to service all your HTTP requests with only one HttpClient • ClientConnectionManager responsible for managing HTTP connections for the HttpClient • ThreadSafeClientConnManager to avoid overlap
1 HTTP Services 2 Android Services Contents
Android Services • Android supports two types of services: • Local services, simply support the application that is hosting the service • Remote services, accessible from other applications on the device, defined to clients using Android Interface Definition Language (AIDL).
Understanding Local Services • Started via Context.startService() • Stoped viaContext.stopService() or called stopSelf() by itself • Note that when Context.startService() is called and the service has not already been created, the system will instantiate the service and call the service’s onStartCommand() method.
Status Notifications • To create a notification, you must use two classes: Notification and NotificationManager. • Notification, to define the properties of your status notification • NotificationManager, an Android system service that executes and manages all status notifications • getSystemService() , to retrieve a reference to the NotificationManager • notify() , to notify the user
To create a status notification • 1. • Get a reference to the NotificationManager: • String ns = Context.NOTIFICATION_SERVICE; • NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
To create a status notification • 2. • Instantiate the Notification: • int icon = R.drawable.notification_icon; • CharSequence tickerText = "Hello"; • long when = System.currentTimeMillis(); • Notification notification = new Notification(icon, tickerText, when);
To create a status notification • 3. • Define the notification's message and PendingIntent: • Context context = getApplicationContext(); • CharSequence contentTitle = "My notification"; • CharSequence contentText = "Hello World!"; • Intent notificationIntent = new Intent(this, MyClass.class); • PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); • notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
To create a status notification • 4. • Pass the Notification to the NotificationManager: • private static final int HELLO_ID = 1; mNotificationManager.notify(HELLO_ID, notification);
Understanding AIDL Services • To build a service via remote procedure call (RPC) • An interface definition language (IDL) to define the interface that will be exposed to clients • Android Interface Definition Language (AIDL)
To build a remote service • 1. Write an AIDL file that defines your interface to clients. The AIDL file uses Java syntax and has an .aidl extension. Use the same package name inside your AIDL file as t he package for your Android project. • 2. Add the AIDL file to your Eclipse project under the src directory. The Android Eclipse plug-in will call t he AIDL compiler to generate a Java interface from the AIDL file (the AIDL compiler is called as part of the build process). • 3. Implement a service, and re turn the interface from the onBind() method. • 4. Add the service configuration to your AndroidManifest.xml file.
Defining a Service Interface in AIDL • package com.androidbook.services.stockquoteservice; • interface IStockQuoteService • { • double getQuote(String ticker); • } • When you create the AIDL file, the Android Eclipse plug-in runs the AIDL compiler to process your AIDL file • The compiler generates a Java interface suitable for RPC communication in your AIDL file— com.androidbook.services.stockquoteservice
Generated classes • The interface we defined in the AIDL file is implemented as an interface in the generated code (that is, there is an interface named IStockQuoteService). • A static final abstract class named Stub extends android.os.Binder and implements IStockQuoteService. Note that the class is an abstract class. • An inner class named Proxy implements the IStockQuoteService that proxies the Stub class. • The AIDL file must reside in the package where the generated files are supposed to be (as specified in the AIDL file’s package declaration).
Implementing an AIDL Interface • The inner class • Extending the Stub class called StockQuoteServiceImpl • Serving as the remote-service implementation • Returned from the onBind() method • A service declaration in the AndroidManifest.xml file
Calling Service from a Client • Copy the AIDL file from the service project to the client’s • The AIDL file serves as a contract between the client and the service
ServiceConnection • private ServiceConnection serConn = new ServiceConnection() { • @Override • publicvoid onServiceConnected(ComponentName name, IBinder service) • { • Log.v(TAG, "onServiceConnected() called"); • stockService = IStockQuoteService.Stub.asInterface(service); • callService(); • } • @Override • publicvoid onServiceDisconnected(ComponentName name) { • Log.v(TAG, "onServiceDisconnected() called"); • stockService = null; • } • };
ServiceConnection • When we call the bindService() method, we pass in the reference to this member. When the connection to the service is established, the onServiceConnected() callback is invoked, and we then obtain a reference to the IStockQuoteService using the Stub and enable the Call Service button.
ServiceConnection • Please notice the onServiceDisconnected() callback. This does not get invoked when we unbind from the service. It is only invoked if the service crashes. If it does, we should not think that we’re still connected, and we might need to reinvoke the bindService() call.
Local service versus an AIDL service • A local service does not support onBind(), returning null • Accessible only to the components of the host application • You call local services by calling startService().
Local service versus an AIDL service • The service implements the AIDL contract, and clients bind to the AIDL definition. • The service implements the contract by returning an implementation of the AIDL interface from the onBind() method. • Clients bind to an AIDL service by calling bindService() , and they disconnect from the service by calling unbindService() .
Passing Complex Types to Services • AIDL’s support for nonprimitive types: • AIDL supports String and CharSequence. AIDL allows you to pass other AIDL interfaces, but you need to have an import statement for each AIDL interface you reference (even if the referenced AIDL interface is in the same package). • AIDL allows you to pass complex types that implement the android.os.Parcelable interface. You need to have an import statement in your AIDL file for these types. • AIDL supports java.util.List and java.util.Map , with a few restrictions. The allowable data type s for the items in the collection include Java primitive, String, CharSequence, and android.os.Parcelable . You do not need import statements for List or Map , but you do need them for the Parcelables. • Nonprimitive types, other than String, require a direct ional indicator. Directional indicators include in, out , and inout . in means the value is set by the client; out means the value is set by the service; and inout means both the client and service set the value.
Directional indicator • Nonprimitive types, other than String, require a directional indicator. Directional indicators include in, out , and inout . in means the value is set by the client; out means the value is set by the service; and inout means both the client and service set the value.
Parcelable • 1. Implement the Parcelable interface. • implement writeToParcel() and readFromParcel(). • Note that the order in which you write properties must be the same as the order in which you read them. • 2. Add a static final property to the class with the name CREATOR . • The property needs to implement the android.os.Parcelable.Creator<T> interface. • 3. Provide a constructor for the Parcelable that knows how to create the object from the Parcel. • 4. Define a Parcelable class in an .aidl file that matches the .java file containing the complex type . • The AIDL compiler will look for this file when compiling your AIDL files.
Implementing the Parcelable Interface • Person.java • Person.aidl • package com.androidbook.services.stock2; • parcelable Person;
Passing Parcelables to Services • package com.androidbook.services.stock2; • import com.androidbook.services.stock2.Person; • interface IStockQuoteService • { • String getQuote(in String ticker,in Person requester); • } • Note that we have directional indicators on the parameters because the parameters include nonprimitive types and that we have an import statement for the Person class.
Service implementation • StockQuoteService2.java • StockQuoteService2 Layout • AndroidManifest.xml
To implement a client • Copy the Person.java and Person.aidl files to the client project • modify main.xml and MainActivity.java
Summary • We talked about consuming external HTTP services using the Apache HttpClient. • With regard to using the HttpClient, we showed you how to do HTTP GET calls and HTTP POST calls. • We also showed you how to do multipart POSTs. • We then moved on to the formal Android Services topics.
Interview Questions • 1. Why is it bad practice to call a web service from the main UI thread? • 2. Can you bind to a local service? • 3. What is one reason for giving a notification to the NotificationManager from a service? • 4. What are ThreadGroups good for? • 5. Can a Parcelable be used to send data to an activity? Why or why not?