Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Saturday, March 1, 2014

Builder pattern in Java

I've always liked how nice the StringBuilder API is. But I have not found the perfect opportunity to use it until today when I wanted to create a clean API for a Request object for searching OnDemand videos. The server API has been defined to accept a bunch of parameters. And depending on what you want to search for, you may supply one or more of these parameters.

What I wanted to create was a request object that's immutable once it's created. I have plans to use this request as a key to retrieve cached response, so it would be messy if someone was allowed to modify the attributes of the original request. So I've decided to have no setter methods.

I could create a constructor with all the parameters, but that would mean that most of the time the developer may have to create a SearchRequest object with lots of nulls. It's also very easy to misplace the arguments. If argument 1 is the rating and argument 2 is the offset, and they're both integers, I can imagine someone accidentally putting the value for offset in the ratings position and the value for ratings in the offset position.

The Builder pattern can be helpful in my situation. So I've prototyped the class here. Let's take a look at how I use this class first. Here's an example of a SearchRequest that query for high rating sports TV shows and episodes.


Running this code generates the following print:
03-01 20:00:59.849    1321-1321/com.example.app I/System.out﹕ http://my.server.com/search.json?offset=0&max_result=100&rating=4&categories=SPORTS&types=TV_EPISODE,TV_SERIES

I've restricted the creation of the SearchRequest object directly by making the constructor private. Instead the developer need to create a new SearchRequestBuilder. The builder then has small methods that are clearly named to add attributes. Once you have composed the request you want, you call the toSearchRequest method and you get the SearchRequest object.

And here's the source code for SearchRequest. I've seen variations of this pattern, but I've implemented it to satisfy my own requirements. I'd love to hear how you've used this pattern in the course of your career and how it differs from my interpretation.

Thursday, February 27, 2014

Intro to SQLlite in Android


It has been a while since I've dealt with SQL. Recently we wanted to see if having an SQLlite database in Android would provide a performance boost. The idea is to prefetch the day's TV guide and load it into an SQL database during the night. And then when the user starts the app, we would first look at the database to see if we already have the data. If so we would load that instead of going through a network request. There may also be a performance boost if the query was written properly. Another benefit over network request is that the REST resource is in JSON format and needs to be parsed, whereas translating from a database row into a POJO potentially is faster. It also takes us later into using CusorAdapter and load data on demand. For those reason it's worth trying it out.

By the way, great site to practice your SQL is http://www.w3schools.com/sql/trysql.asp

The first thing I need to do is store all my TV Program POJO into the database. And the first step is to create a table. To create a table, I execute an SQL statement such as this:
CREATE TABLE program (id INTEGER PRIMARY KEY, name TEXT NOT NULL, start_time NUMERIC, end_time NUMERIC)

It reads that we're going to be creating a new table with 4 fields: an ID, name, start and stop time. This table will have the name program. Each row in this table must have at least an ID and a display name.

In Android, we do this by creating a class that extends SQLiteOpenHelper and overriding the method
public void onCreate(SQLiteDatabase db);

In that function we can execute the query
db.execSQL(createTableQueryStr);

The SQLiteOpenHelper is a class that manage database creation and help with version control.

When you extends SQLiteOpenHelper, you are also required to implement onUpgrade method. Here, we'll simply delete the table and erase all previous data. The query is:
DROP TABLE IF EXISTS program

The Program POJO actually has more data than the 4 things, but for simplicity of this blog, we'll pretend there's only 4 fields. But I want to mention that in reality, the POJO also includes a List of Strings that denotes which genre(s) the program belongs to. In order to include this information, I needed to create a 2nd table of genres. I decided to use Foreign key contraint to better insure data integrity. This way I don't accidentally add a Genre that doesn't belong to any program. The query for that table looks like this:
CREATE TABLE genre (program_id INTEGER, genre_name TEXT, FOREIGN KEY (program_id) REFERENCES program(id))

A database query always return a Cursor. It's the mechanism for which you retrieve the result. It doesn't load all the results in memory, only what the cursor is pointing at. This is good if you pass this cursor to your view so that you only need to get the data that is displayed in the UI, but it's not always possible depending on how the app is structured. So for convinence, I've created some method to translate between table row and POJO and vise versa.
Before you can insert, query, or delete anything in the database, you need to open it. This is usually done either than your app is created or when your Service is connected. Here I've created a ProgramsDataSource class that'll help me insert query and remove programs based on the start_time of the TV program.
Note the use of the insertWithOnConflict method where if a row already exist, I'll replace the values instead of throwing an exception.
The other thing to note is that if you need to use the DISTINCT function of SQL to query all unique names for example. Let's say I want to know programs of my entire TV Guide during prime time during the week, but I don't want to see the evening news show up 5 times, I would do a query with DISTINCT. To do that in SQLiteDatabase in Android, you use the overloaded method for query with the boolean as first argument.


WebRep
currentVote
noRating
noWeight

Thursday, February 13, 2014

Quick & Dirty Tips: Splitting words

First thing to note is a StringTokenzier is depreciated.
StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.
Instead use String.split(String regex), which takes regular expression. So to use the method we have to look at how regular express can split words.

[^abc] Any character except a, b, or c (negation)
\s A whitespace character: [ \t\n\x0B\f\r]
\S A non-whitespace character: [^\s]

So to split words in a String, I use the following:

String line = "Lorem ipsum dolor sit amet, consectetur adipisicing elit...";
String[] words = line.split("\\s*[^a-zA-Z]+\\s*");


Links:

Tuesday, February 4, 2014

Creating a REST library using Retrofit & OkHttp

I've been tasked to modernize our application's networking layer. We have been writing our own network manager to deal with http 302 redirect and caching responses, but there are many opensource project that already does these things very well. I've looked into RoboSpice and Volley as the more popular choices for doing networking in Android. I found that they're a good candidate as an improved AsyncTask as well as providing caching. However both framework are closely related to the Activity context and doesn't work as well when put into a Service such as ones that I intent to make with a SyncAdapter. We needed a lower level framework. To figure out what fits our bill, we wrote down some of our requirements:

  1. It needs to support Https
  2. We want to translate server JSON into client POJO
  3. The framework needs to allow us to edit the header and post body for authentication
  4. We want the ability to pass arguments to methods and insert them as part of the URL or the query
  5. We want to save bandwidth with Gzip
  6. We want efficient communication with parallel requests
  7. we want Http caching that follows the server's http cache directive
  8. It needs to follow http 302 redirect
  9. It needs to work well with Android

I stumbled across Square's Retrofit and OkHttp. Here's how it fits.

Retrofit

Supports Https
In Retrofit's home page, their example uses https, so clearly it supports it.
RestAdapter restAdapter = new RestAdapter.Builder() .setServer("https://api.github.com") .build();

Converts JSON to POJO
Retrofit use GSON by default to convert Http bodies to and from JSON.

Edit request header and body
Retrofit allow header information to be set statically using annotation or at runtime using a RequestIntercepter.

Edit URL and query
Retrofit uses annotated method arguments to replace PATH or query placeholders. You can also change it at runtime using RequestIntercepter.

Working with Android
The generated implementation GET and POST can be made synchronously outside of UI thread, or asynchronously callback on the UI thread, or in background thread via Netflix's RxJava rx.Observable. So it's very flexible in what threading model we need. We can also put RoboSpice on top of Retrofit later if we want.

OkHttp

Supports GZIP
"Transparent GZIP shrinks download sizes."

Efficient Networking
  • "SPDY support allows all requests to the same host to share a socket."
  • "Connection pooling reduces request latency (if SPDY isn’t available)."
  • "it will silently recover from common connection problems"

Local Caching
OkHttp's HttpResponseCache allows you to set aside a specific amount of space in cache directory, very similar to Google's HttpResponseCache.


First create an OkHttpClient and set 10MB of space in the cache director for caching

Then in order to add some standard PATH and query parameters I create a RequestInterceptor

Then we can build the RestAdapter and set the OkHttpClient as the networking component and set the request interceptor so that every request will be modified to include those Path and query.
Note that for debugging purpose I've turned on debugging so I can see the actual request and response in the log.
Also note that the http scheme is set as part of the most.

Then with the RestAdapter, you call create with the Interface that you want to create. But before we do that, we need to define the Interface.

GET
Notice that synchronous call throws RetrofitError at runtime, so I've declared it in the interface explicitly here. The caller should try/catch the request in case an error occurred.


POST

So now, we can create POJO data for all the data that our server returns, create Interface files for all the APIs that the server has available, annotate the URL, the header, the post body, and the return type. And then I should have a brand new and robust REST library for my application!
For more information, visit the

Saturday, January 25, 2014

Learning about Android Loaders: AsyncTaskLoader

Android introduced Loaders in 3.0 to ease asynchronous tasks on Activity and Fragments. It monitor the source of the data and automatically deliver new result when content changes. It's primary usage is to work with a database utilizing the CursorLoader, but it can also be used to do other asynchronous tasks. I want to take a look at how Loaders could be used as a replacement for AsyncTask.

The issue with AsyncTask is well known. If you rotate the device, you have to cancel the AsyncTask or the app will crash. Loaders handles rotation better, it automatically reconnect to the last loader’s cursor when being recreated after a configuration change avoiding the need to re-query their data.

There is an instance of LoaderManager in every Activity and Fragment. You simply call getLoaderManager(). Note that if you're using the support library, you will call getSupportLoaderManager() instead.

To do the actual task, create a class that extends the AsyncTaskLoader and implement the loadInBackground method. The return type will be whatever data you want to send back to the main app. In my example, the work is just to sleep for some time. And my return value is just how many milliseconds I slept.

To trigger the work, the first thing to do is to implement the LoaderCallbacks interface in your Activity or Fragment. You can then call initLoader in the Activity's onCreate method. In my test app, I'm actually going to start the task after clicking a button, so I call initLoader() and forceLoad(). The onCreateLoader method will then be triggered. Notice that it uses an integer ID to identify the Loader. I'm not sure, but my guess is that typically you only have one Loader to handle all the asynchronously tasks for an Activity or Fragment.

Finally, to get feedback on the UI, the onLoadFinished method will be called in the UI thread where you can show the result. In my example, I'm simply making a Toast message, but you could imagine where we can update a table with rows of values or show a text.

Note that while AsyncTask has onProgressUpdate(Integer progress) to show how much data has been fetched, a Loader doesn't have this capability out of the box.

I still have a lot to learn about Loaders after this short prototype. So far, it seems like a lot of work to avoid canceling and restarting tasks. If data fetch performance is a concern, which is always the case to a certain degree, then I would consider using AsyncTaskLoader instead of AsyncTask. But there are alternate solutions, such as RoboSpice, that maybe a better solution. My guess is that Loaders are much more effective when dealing with database, which I intent to try out soon.

Tuesday, January 14, 2014

Java's CountDownLatch

In our Android phone TV application, we need a few server resources before meaningful data can be fetched. For example, we need to know the template for the playback URL so that when user select a channel, we can construct a full URL to play from the channel ID, the device dimension, etc. We also need to fetch another table that tells us which settings to use when the app is connected to a WiFi spot versus when it's on a cellular signal. We need these and a few other essential resources before the app can start.

All of these resources are asynchronous fetches from the server. And we don't want to navigate to the home page until all resources have been retrieved. A handy class to help track that we've got all those resources is the CountDownLatch. It blocks the calling thread until the count reaches zero. You create the latch, fire off your asynchronous tasks in separate threads. Then when each of the task is finished, you decrement the count by calling countDown().

To block the calling thread, you call the await() method. One mistake I made the first time was call wait() instead of await(), so make sure you call the right method. If you call wait, you'll get an IllegalMonitorException.

Warning: NEVER block the UI/main thread!


It's obvious, but still worth noting. You should not use this on the main thread. Instead I would use this to patch several tasks and make it act like a single operation, then notify the UI that all tasks are done via a handler or broadcast receiver.

To see how it all works, I wrote a simple function and run it to see how it looks:

Sample code



Sample output


01-07 10:50:53.758    7809-7809/com.mobitv.refapp I/System.out﹕ DEMO - execWorkerTasksBlocking <<
01-07 10:50:54.018    7809-8129/com.mobitv.refapp I/System.out﹕ DEMO - Completed: task A
01-07 10:50:54.118    7809-8129/com.mobitv.refapp I/System.out﹕ DEMO - Completed: task C
01-07 10:50:54.269    7809-8130/com.mobitv.refapp I/System.out﹕ DEMO - Completed: task B
01-07 10:50:54.369    7809-8130/com.mobitv.refapp I/System.out﹕ DEMO - Completed: task E
01-07 10:50:54.879    7809-8129/com.mobitv.refapp I/System.out﹕ DEMO - Completed: task D
01-07 10:50:54.879    7809-7809/com.mobitv.refapp I/System.out﹕ DEMO - execWorkerTasksBlocking >>

Sunday, January 5, 2014

Android's IntentService

When I ask my colleagues about IntentService as a way to execute asynchronous tasks, most seems to be unaware of it existence. Perhaps it is because it doesn't interact with the UI/main thread like AsyncTask does, so it's use is limited to background processes that doesn't require UI feedback, and so there are less scenarios where it is appropriate. IntentService is just one of many ways Android provide asynchronous operations. Others include
  • runOnUIThread
  • Executor
  • Handler
  • AsyncTask
  • Service
  • Loader

Service vs IntentService


The first question that most developer ask is what's the difference between a normal Android Service and an IntentService. Most folks understand that a Service is an application component that can perform long running tasks in the background without UI feedback. If you read the Class Overview of IntentService, you would read that
"IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand."
The first time I read this quote, I interpreted to mean that Service extends IntentService. But the opposite is true.
public abstract class IntentService extends Service
IntentService does a little bit more than what Service does for you.
  • While a regular Service runs in the caller's thread, which in most cases is the main thread, IntentService always run on a background thread.
  • IntentService uses a message queue to process requests, so only one intent is handled at any time. 
    • if you need parallel tasks such as downloading multiple images at the same time, IntentService may not be a good choice. 
    • If one of the tasks is stuck, then all the pending tasks in the queue will not execute. 
  • Calling stopService is optional; The IntentService will stop itself once there's no more work on the queue. 
  • A broadcast receiver is needed if you want to provide UI feedback.

Implementing an IntentSevice


There are only a few things you have to do:
  1. Declare a few constants for communication between application and IntentService.
  2. Create a class that extends IntentService; Implements onHandleIntent method.
  3. Create a BroadcastReciever; Implement onReceive method.
  4. Trigger the IntentService by calling startService, with input arguments wrapped in an Intent.

Example:



Handling device rotation


In order to handle configuration change properly, when the device is rotated for example, the broadcast receiver should be bind and unbinded along with the lifecycle of the Activity or Fragment


Sample output


Note that the requests are handled serially such that if startService was called by mistake more than once with the same Intent, the work will be done twice, so it's important to either prevent that from happening in the calling side or write the IntentService such that it recognize a duplicate request. This can be accomplished by a runtime cache or input and output. So if the service receive the Intent and it already cached the result, then just broadcast the result again. Finally, if you call stopService all the pending tasks will be lost, which maybe what you want.


Calling startService just once


12-13 15:44:11.300 19913-19913/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:44:11.370 19913-19913/com.mobitv.demo I/System.out﹕ MyBackgroundService.onCreate
12-13 15:44:11.380 19913-20063/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Find price for GOOG
12-13 15:44:13.242 19913-20063/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Found price: $1200.45
12-13 15:44:13.252 19913-19913/com.mobitv.demo I/System.out﹕ MyBkgSvcResponseReciever.onRecieve
12-13 15:44:13.272 19913-19913/com.mobitv.demo I/System.out﹕ MyBackgroundService.onDestory


Calling startService many times in rapid succession.


12-13 15:46:28.568 20388-20388/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:46:28.628 20388-20388/com.mobitv.demo I/System.out﹕ MyBackgroundService.onCreate
12-13 15:46:28.638 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Find price for GOOG
12-13 15:46:28.688 20388-20388/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:46:28.838 20388-20388/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:46:28.989 20388-20388/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:46:29.129 20388-20388/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:46:30.520 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Found price: $1200.45
12-13 15:46:30.530 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Find price for GOOG
12-13 15:46:30.550 20388-20388/com.mobitv.demo I/System.out﹕ MyBkgSvcResponseReciever.onRecieve
12-13 15:46:32.422 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Found price: $1200.45
12-13 15:46:32.422 20388-20388/com.mobitv.demo I/System.out﹕ MyBkgSvcResponseReciever.onRecieve
12-13 15:46:32.442 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Find price for GOOG
12-13 15:46:34.324 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Found price: $1200.45
12-13 15:46:34.324 20388-20388/com.mobitv.demo I/System.out﹕ MyBkgSvcResponseReciever.onRecieve
12-13 15:46:34.354 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Find price for GOOG
12-13 15:46:36.246 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Found price: $1200.45
12-13 15:46:36.256 20388-20388/com.mobitv.demo I/System.out﹕ MyBkgSvcResponseReciever.onRecieve
12-13 15:46:36.286 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Find price for GOOG
12-13 15:46:38.168 20388-20494/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Found price: $1200.45
12-13 15:46:38.168 20388-20388/com.mobitv.demo I/System.out﹕ MyBkgSvcResponseReciever.onRecieve
12-13 15:46:38.248 20388-20388/com.mobitv.demo I/System.out﹕ MyBackgroundService.onDestory


Calling startService many times in rapid succession, then calling stopService once.


12-13 15:47:19.849 20807-20807/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:47:19.909 20807-20807/com.mobitv.demo I/System.out﹕ MyBackgroundService.onCreate
12-13 15:47:19.919 20807-20952/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Find price for GOOG
12-13 15:47:20.009 20807-20807/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:47:20.209 20807-20807/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:47:20.409 20807-20807/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:47:20.590 20807-20807/com.mobitv.demo I/System.out﹕ Button.setOnClickListener calls startService
12-13 15:47:20.940 20807-20807/com.mobitv.demo I/System.out﹕ MyBackgroundService.onDestory
12-13 15:47:21.791 20807-20952/com.mobitv.demo I/System.out﹕ MyBackgroundService.onHandleIntent; Found price: $1200.45
12-13 15:47:21.801 20807-20807/com.mobitv.demo I/System.out﹕ MyBkgSvcResponseReciever.onRecieve



Example Use in projects

To see how others have used IntentService, I went on Github and did a search and found a few examples of open source project that uses IntentService as a background task.
  1. RingerMuteService uses IntentService to change the volume level of the device
  2. VBox's EventIntentService polls VirtualBox for events and publish them in a local broadcaster
  3. WidgetCreatorService uses IntentService to create app shortcut on the device home page
  4. WotdWidget updates data in an Android widget.
  5. UploadToJBossServerService upload file to a JBoss Server.

Thursday, December 12, 2013

Android's SyncAdapter pattern

This is an article I wrote for MobiTV,Inc. While looking to understand this Google framework, I found dozens and dozens of articles on the internet, but it was still difficult to comprehend. The best articles talks about how we would implement the entire pattern, but I really only wanted to use the SyncAdapter, without utilizing the ContentProvider or the Authenticator piece. I don't yet consider myself an expert in Android development, so comments and corrections are more than welcomed.

The grand idea:

Wouldn’t it be great if your application could startup instantly without any network latency? Well, that’s the idea behind SyncAdapter. It allows Android to synchronize data between a remote resource and your local copy on a daily basis, or more frequently if required, so that when your application starts, it would already have all the data it requires locally. Theoretically, it could allow your application to should run even when the device is disconnected from the network. 

How it's envisioned

When the application is first launched, it ask the user to create or login to an account. That account information is saved in Android's Account settings. During the night, the phone is left idle with full battery and charger attached with good wifi network. The Android "Sync Manager" retrieves all the Accounts in the phone, and serially it starts its SyncAdapter service. Your app's SyncAdapter service starts and begin to download the next day's guide program and newly added TV shows information. Those information are saved by the ContentProvider backed by an SQLite database. Your service is stopped once everything is done. The user wakes up the next day, takes her phone on the train and starts the app. The app first ask the ContentProvider (via ContentResolver) for cached data. It retrieves all the data from the local database and returns them to the app. Your user is happy because the app started quickly.
On the next night, the same thing happens, but this time there's a network outage for several hours. Android's "Sync Manager" realizes the network issue and exponentially back off retries until it establishes good connection. By the following morning, one of the retry worked and our user takes her phone on the train again. And again the app starts immediately because all the data has been cached. Your user is again happy, not knowing the drama that unfolded during the night.

The components:

The SyncAdapter pattern requires three pieces to be present, but only the SyncAdapter needs to have useful code. It needs the SyncAdapter, a ContentProvider, and a Authenticator. Lets take a look at each of these components.


SyncAdapter

Your SyncAdapter is a class that extends AbstractThreadedSyncAdapter and implements the onPerformSync function. The function is responsible for calling any methods that you wish to perform the fetching and persisting of remote resources. In a way, it's like a Runnable that you would implement, except it's a Runnable that Android's "Sync Manager" understands. This method will be called at the proper time when the OS deems appropriate. This typically means every 24 hours since the SyncAdapter was initially setup. But it can also be delayed if another application is busy doing their synchronization. It may also be delayed if network is spotty or if it's roaming etc.   

Service

A SyncAdapter class needs a service host. Any Service will do.  There are two things this service needs in order to work with the SyncAdapter
1/ Implements the onBind method to return the SyncAdapter's binder


2/ Declare the service as receiving SyncAdapter intent

notice that the meta-data element references res/xml/syncadapter.xml file which we will go over in the Account section.

ContentProvider

A ContentProvider is typically a thin layer on top of an SQLite database. This is where your application may store the remote resources and provide quick access to data. Here at MobiTV, it’s unlikely that we would encourage other applications to use our unprotected guide data, user’s personalized recommendation, etc, so our  ContentProvider maybe just a stub.
ContentProvider.java:
“A content provider is only required if you need to share data between multiple applications. For example, the contacts data is used by multiple applications and must be stored in a content provider. If you don't need to share data amongst multiple applications you can use a database directly via android.database.sqlite.SQLiteDatabase.”
While we may not make use of a ContentProvider, it is still required by the SyncAdapter. So we create a StubContentProvider which extends ContentProvider and implement all methods to return etiher false, 0, or null.

Account

While much of the data you wish to synchronize are public data, some will be specific to your user. In that case, the SyncAdapter would need to access the user’s account and password. Secondly, the Account screen is where Android user expect to find the sync settings for their personal information.
For example, this is what you see if you install the Evernote application.
Of course you may not want to always fetch protected data. Perhaps all we want is to make sure that we update EPG program data nightly. These data are publicly accessible and doesn't require username and password. In that case we can programmatically create an account and hide the account from the user. You can do that by setting the android:userVisible flag to false in the syncadapter.xml file; I've found from experience that it may also require that you don't put any android:accountPreferences, icon, or label in the authenticator.xml file. If you don't already have a xml folder under the res directory, you need to create the folder and add this xml file. You can call it whatever you want, as long as it matches what is declared in the meta-data field of your SyncAdapter Service. This xml file needs just one root element <sync-adapter> and there you can specify

AccountManager

To create an account for the user, whether from within your application or via the Accounts screen in Android's Setting, you will need to write a few lines of code to let The AccountManager know what kind of account you want to create.

Note that authToken here is passed in as a String. You will have to write an Activity to allow the user to provide their user name and password, then use that information to retrieve the auth token in your own code.

To retrieve the account later, you simply call getAccountsByType and pass in the account type string that you created the account with previously

Authenticator

Your Authenticator is a class that extends AbstractAccountAuthenticator. This is where you will connect your code to retrieve auth token etc. Of course if you're only interested in publicly accessible data, then you can just implement empty functions that return null. You will probably still need to pass in a dummy username when you create an Account in the AccountManager.
However, If you actually want to implement real authentication, there are several methods that you need to implement, but the most important ones are addAccount and getAuthToken
Example:

Service

The host for the Authenticator is similar to the host SyncAdapter. It has to be a Service and the following requirements
1/ Implements the onBind method to return the Authenticator's binder

2/ Declare the service as receiving AccountAuthenticator intent


Connections

The SyncAdapter/Service, Authenticator/service, and ContentProviders are connected together by using the same contentAuthority and accountType. Here are some notes about them.
android:contentAuthority
A provider usually has a single authority, which serves as its Android-internal name. To avoid conflicts with other providers, you should use Internet domain ownership (in reverse) as the basis of your provider authority. Because this recommendation is also true for Android package names, you can define your provider authority as an extension of the name of the package containing the provider. For example, if your Android package name iscom.example.<appname>, you should give your provider the authority com.example.<appname>.provider.
The String must match in the following places:
  • AccountManager
    • addAccountExplicitly
    • getAccountsByType
    • etc
  • syncadapter.xml
  • AndroidManifest.xml
android:accountType
accountType is used to identify the type of account data to sync. The String must match in the following places:
  • AccountManager
    • addAccountExplicitly
    • getAccountsByType
    • etc
  • syncadapter.xml
  • authenticator.xml
    • Authenticator class will need to use the accountType in when sending KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, but the type will be an attribute in the Account being passed in.
    • Authenticator class will also utilize accountType when AccountManager.getAuthToken is called.

Recipe

  1. 1 Service class + 1 SynAdapter class
  2. 1 Service class + 1 Authenticator class
  3. 1 Content Provider class
  4. XML resources
    1. 1 syncadapter.xml
    2. 1 authenticator.xml
    3. 1 account_preferences.xml (optional)
  5. 1 AndroidManifest.xml

Simplified AndriodManifest.xml








Design considerations

Worst case scenario
What Happens the first time the application is launched? The SyncAdapter never had a chance to start so there are no persisted data the app can rely on. Furthermore, if you only get data from the SyncAdapter, you have to wait for the Service to start, which slows down your application boot time. You'll need a mechanism for both the app to get data on demand as well as allowing the SyncAdapter to use those code to retrieve and persist those data.
Diamonds are forever, Services are not
Services are not supposed to stay alive forever. In the case of SyncAdapter Service, it should startup on its own by the "Sync Manager", perform its sync, and then the Service would be stopped. So it's important that the SyncAdapter doesn't rely on configuration setup that isn't known to the SyncAdapter.

References