Wednesday, April 23, 2014

Gradle Android : Multiple project setup

For a Multi-project setup, the Android documentation for gradle states :
"A multi-project setup usually works by having all the projects as sub folders of a given root project."

MyProject/
 + app/
 + libraries/
    + lib1/

But I have a different situation where my library project and the actual project is not under the same root.

So, my library project is inside its own directory. Then I have my main project in some other directory wanting to refer to this library project. I had a hard time to figure this out with gradle. So, hopefully this helps someone.

So basically, the structure is as follows:

~/Dev/Libraries
    |---- foolib-root
                |---- foolib
                           |---- build.gradle
                           |---- src
                           |---- libs
                |---- build.gradle
                |---- settings.gradle


~/Dev/Projects
    |---- project1-root
                |---- project1
                           |---- build.gradle
                           |---- src
                           |---- libs
                |---- build.gradle
                |---- settings.gradle


Just, FYI, the build.gradle inside foolib-root/foolib contains:

apply plugin: 'android-library'

indicating that it is a library module.

Now, the task is to refer to library project foolib from project1.

I have found there are 2 things you need to do to achieve this:

1. The settings.gradle in project1-root must define the library project in its scope and provide a path for it. You can do this by having the following line in it:

 project(':foolib').projectDir = new File(settingsDir, '../Libraries/foolib-root/foolib')

2. Add this library project into the dependencies of project1 by adding the following to its build.gradle:

dependencies {
    compile project(':foolib')
    ......
}

This did the trick for me. Not sure if this is a right way to do it. But serves my purpose.

Friday, April 11, 2014

Debugging Cursor Values


Many times, you will have to query content providers. For that you'll either use a content resolver or use the CursorLoader class. In both cases you get back a Cursor object back.

For quick debugging, you'd want to examine the contents of the cursor. For quick debugging purpose, it is painful to extract all the columns coz you need to know the column data types and names etc...

Cursor cursor = getContentResolver().query(<uri and other params>);
if (cursor != null) {
    while (cursor.moveToNext()){
          intValue = cursor.getInt(cursor.getColumnIndex(<Column name from provider contract>));
          stringValue = cursor.getString(cursor.getColumnIndex(<Column name from provider contract>));
          longValue = cursor.getLong(cursor.getColumnIndex(<Column name from provider contract>));
          //..... and so on for all the columns you need to debug
    }
}

I came across this simple method in the DatabaseUtils class which, for some reason, I never noticed :) It has there been since Api level 1 :O

Super useful for quick and dirty debugging.

public static String dumpCurrentRowToString (Cursor cursor)


So now the code becomes:

while (cursor.moveToNext())
{
       Log.d(TAG,  DatabaseUtils.dumpCurrentRowToString(cursor));
}

Makes debugging life so easy!

Wednesday, May 1, 2013

Google Glass : My answers to FAQs


Random person: Is that...
Me: Yes. it is Google Glass
Random person: Is it...
Me: Yes. It is awesome!



I have been getting a lot of (stares) and questions about the Google glass. There are a lot of people writing about it too. Here, I try to answer the most common questions/remarks I have gotten so far.
I'll keep updating it as I get more questions. (Let me know if I'm missing any info).


The way I did is, I put on my glass and standing in front of the “Mirror”, did a self interview re-asking myself all those questions. Here it is:


Note: I have not been paid by Google or anyone to do this. All the opinions expressed in this article are my own.


Level: extreme newbie / curious


What is Google Glass ?
It is a wearable computer - a computer that you can wear! :)
Other examples of wearable computers: smart watch(pebble, sony smartwatch, calculator watches), health sensors (jawbone up), you get the idea...
So basically, it is a seems-to-be-futuristic-but-its-already-here-and-the-world-is-moving-too-fast-and-i’m-getting-old device.


How to use it ? What are the ways to interact ?
- It has a small screen (in the a small glasslike looking plastic piece) on which content is projected.
- There is a camera for photo/video capture.
- There is a trackpad on the side which understands swipes.
- There is a microphone and a small speaker.

Update : Google just released this short video of how to use glass:





How does data work ? Do I need to put a SIM in it ?
- It connects to your phone via bluetooth and uses data from your phone plan.
- It can also connect to wifi.


- What is really the use of it ? (posting pictures/videos on social networks don't count)
- Is it really useful ? Or just another gimmick ?
Here is Google's marketing page that tells you what it can do : http://www.google.com/glass/start/what-it-does/
In my words, you can do the following things:
- Use it as a camera (pictures, videos)
- Send messages via email or text (google voice)
- Get turn by turn directions (navigation) - when connected to your phone
- Hangout (video conferencing) with friends on Google+
- Get notified of new important emails, calendar invites
- Access to quick information when needed information (via Google Now) : nearby restaurants, weather, flight info, birthdays - most of the things Google Now does on your android device.
- Moreover, it is a platform not just a device. That means, developers (like me) can come up with (and should come up with) more ‘relevant’ ideas to extend its usability.


Is it perfect ?
Not yet, being a 1st generation device, there is room for improvement. Infact, its not even a first gen device. Google has been very nice to have outsiders to help them build this new product by asking them to try out early version (called explorer edition), test it in the wild, write apps and provide feedback. So, it is not perfect, but the “vision” is great and in the right direction :)


- Isn't it distracting while using ? or even more when you get notified of something, I mean notifications are right into your face.
- Better watch out for the truck coming your way when you are walking on the road
- So, if you get hit by a bus, does Google pay for your medical expenses or insurance payout?

It is surprisingly not distracting. Even I was concerned about this.


Firstly, the display sits above your right eye plus it is not on all the time. So, you can actually see through it. Even when the display is active, you can see through it on the other side. To look at the display, you have to look up slightly.


Secondly, the glass doesn’t start doing things by itself. Most of the notifications you get, just make a small sound (the screen is not activated). Then you can choose voluntarily (just as you choose to look at your phone) to look up to activate it and consume the notification.


It involves the same amount of risk (rather less) that would be when you are walking down the road looking at your phone or wearing your headphones/earphones while walking/biking. Rather I’d argue that the risk is less, since you are looking up and you have better peripheral vision as well as being able to see through the glass.


One of the goals of the product is to set you free from your phone whenever it is not needed.


It is so close to your eyes, doesn't it put strain ?
Nopes, they have designed it in such a way that, when you look at the screen it appears to be 1.5 to 2 feet in front (and above) of your line of sight.


I’m concerned about privacy. Anyone can take photos/videos in public without noticing.
Well, for taking videos/pictures, you need to either 1) press a button or 2) talk to it loudly to feed voice command. That solves the problem for not knowing when someone is taking a picture/video.
Also, do you know there are n number of cameras(and sensors) out there already capturing you that you don’t even know of. And they are increasing, glass is just one of them and it is not even hidden. Its there right on top of someone’s head, may be your own.

Update: Here is more detailed info on privacy by Robert Scoblehttps://plus.google.com/111091089527727420853/posts/SHZJ2giR7pE

What is the price ?
This is the explorer edition and it is priced at $1500


Wow, thats a lot :O
Yes it is. I don’t feel obligated to justify the price. BTW, I got mine free - I won the Glass hackathon at an event :) Be (more) jealous. I have earned those!


What will be its actual price?
Don’t know, however Google has indicated that when the consumer version comes out it will be less than $1500.


When will the consumer version come out ?
I don’t know. Google has indicated it may take another year


Do you work with Google ?
No. I have been a fan of their technologies, I use them, I build apps with them (heard of Android?), I live with their technologies. [Google, I need a life long pass for IO and other Google events :) ]
I do work with an awesome company called Tomfoolery (www.tomfoolery.com) with some crazy awesome people. Check us out and follow us www.twitter.com/tomfooleryhq


Is the Google glass awesome ?
Of course it is :)


Are you biased ?
Of course, I am. (However, I’ll mention the drawbacks later)


You look stupid wearing those.
Yes, I do.


You look awesome wearing those.
Yes I do.


What are the issues you have faced ? What are its drawbacks ?
Just to reiterate, this is the explorer edition. I expect it only to improve from here. Here are some of the issues I have found.
- Without any data connectivity, you can just capture video/photos. You can go through your previous timeline items, however any actions you perform won’t happen.
- Also, with a slow data connection, it can get frustrating.
- The bone conduction speaker is a bit funny. It tickles when it makes sound.
- Also the sound level is not very good. In crowded places its hard to hear. Especially when you are taking calls through bluetooth, it doesn’t help at all.
- If you already wear glasses, then you have to be patient and wait for the consumer edition later. Currently, you have to either wear both glasses (your prescription and google glass) or wear contact lenses.
- Quality of hangout is blurry most times (again depends on data connection)
- Battery life can improve.
- Sometimes I have bluetooth data connection issues. Esp. when I get out of a connected wifi.


Will it be a success ?
I believe it will. But really, I don’t know. There are various factors involved. Price, monetization, acceptance. But, if you ask me about usability, coolness - I’m sold


But I don’t like it. It is invading privacy, it looks stupid, it doesn’t make sense, its too futuristic?
You like it or not, it makes sense to YOU or not, it doesn’t matter. Accept it. It is still coming. If not Google glass then something else will or something else... Be open. Adapt.



Level: Technical / More curious


Does it run Android ?
Yes it does.


Can you run Android apps on it ?
Technically yes. I ran one this morning. (See this : https://plus.google.com/113624528637645978412/posts/Hze7DzPe6MM), but doesn't make sense to do that. It is a different form factor. Even if it runs Android, from app development/usage point of view, it is better to think of it as a different platform.


Do I need to know Android to write apps for glass ?
No. You need to know how to do HTTP calls from any language of your choice (this is the minimum requirement) and you need to know html. Here is their developer website : https://developers.google.com/glass

Thursday, June 9, 2011

Enterprise mobility and Android

Its quite some time after the GoogleIO. Have been busy digesting some info and thinking a lot. Just a day before IO, I wrote some of my thoughts on Enterprise mobility. Today, I'll try and visit certain aspects in detail as well as try to list what Android has to offer as of now.

Now, from current trends in market and from my understanding till date, I see the current enterprise mobility having 3 components as follows :



1. Device Management
2. Security
3. Application management

Enterprises looking for a complete mobility solution are mostly looking at these three areas. I'll try to briefly touch on each of these and discuss what Android has to offer (and not offer) to enterprise mobility. [For clear separation, I have marked Android Specific details in BLUE : I know Green (#A4C639) would have been appropriate, but I didn't think it was good for reading :)]

1. Device Management :  Device management (DM) mainly deals with being able to remotely alter certain aspects of the devices. Again, I see DM being split into the following.



i. Provisioning deals with mass deployment of various settings on large number of handsets.  For instance, provisioning the devices with corporate WiFi information, VPN access parameters and configuration of email settings etc... For the IT department, being able to provision these settings is beneficial since it helps them carry out the tedious task as well as reduces chances of human error and avoid complex email instructions.

Blackberry and iOS have most of the DM functions baked into the platform. This means, one can configure a DM server (may require manual steps). Once configured, the DM server can send commands to the device which will be understood by the device platform and reacted accordingly.

Android, however, requires an on-device management agent (aka Device administrator) which should implement the Device Admin APIs (Android 2.2 onwards) in order to perform any of the DM functions. Furthermore,  Android doesn't support provisioning out of the box. Rather of all the top IT demands (WiFi, VPN, Exchange etc...), only WiFi can be configured programmatically by the on-device agent.

ii. Device Control deals with being able to remotely take certain actions on the device that may affect the end user. E.g. device lock, unlock, wipe, set/reset password.

With the device admin software installed, Android can do these basic device control functions like device wipe, lock/unlock and set/reset password.
There is however one way to achieve device control functions without having to install any device admin. The trick here is that most Android devices ship with a Email application which can be configured with Exchange information. By default Exchange uses the ActiveSync protocol for syncing mails. Of lately (I guess Android 2.2 onwards), I have seen that while configuring Exchange, the platform shows the standard Device Management screen asking for adding the Exchange as a device admin. If you do this, then by configuring the Email, you can execute device control commands like lock/unlock, set/reset password, wipe etc... To check this go to Settings -> Location and Security -> Select Device administrators. You should be able to see Email application being listed if you have configured Exchange (ActiveSync ).

iii. Device Policies : Policies allow enterprises to control certain settings of the device. This is different from provisioning in that policies can be considered as 'enforced' settings. While someone may change the provisioned settings, device policies are not "meant" to be changed. On Blackberry and to some extent the iOS, the platform restricts the user from changing any policies set by the IT administrator. These policies may include restrictions on the browser to disable javascript, avoid using the phone as USB storage device, disabling camera, etc...

Again, in the case of Android, you will need the on-device admin app to control (only) a subset of what the IT demands traditionally. Basic policies like enforcing a device password, password quality etc.. are supported out of the box with the Device admin APIs.

2. Security : By far, this is THE feature enterprises cannot live without. When enterprises allow data to be accessed remotely, its security is of prime importance. There are 3 components related to security that I visualize as follows:



i. Encryption : Any data that is stored by any application as well as any data that is communicated to and from the device, needs to be encrypted.

Android apps can use SSL tunnels through with data can be transported. However, the data stored on the device (phone memory and SD) is up to the applications. Prior to honeycomb (Android 3.0) there is no support for turning on encryption on the device. Even with Honeycomb, a device administrator application can request for the encryption process to begin, and it will start the encryption ONLY IF it is supported by the device on which the agent is running. Things are still pretty unclear about the way encryption is supported (hardware vs software etc...). One of my previous posts raises these issues. I'll update both the blog posts once enough information is available.

ii. Device Policies : I have purposefully included policies again under Security. I think this link is important to note. This is just to remind that policies are restrictive settings enforced in order to avoid security compromise.

iii. Compliance : Now, we have policies in place. And as I said these need to be enforced on the device. However, it may happen that the user knowingly or unknowingly changes some setting that violates certain policy (that cannot be technically enforced on the device - technology limitation). This may put corporate data at risk. It is important for the IT to determine such instances. This leads to constantly monitoring the device and making sure that it is "in compliance" with the policies.
Usually, compliance checking may be done on the server that monitors the device. This can be achieved by querying the device for certain parameters periodically and then running the compliance rules against the values received. These rules usually test whether the device adheres to all the policies, if not then the resulting actions could be anything from blocking corporate access for that device to wiping the device. This totally depends on the IT policies for the enterprise.

The device admin app can play the role of reporting parameter values to the DM server. To monitor Android for certain metrics, the server can implement the Google C2DM (cloud to device messaging discussed in this blog post) to send query messages to a device admin app which can reply back. 

3. Application Management : One of the basic goals for enterprises is to mobilize the business. As a result, enterprises have started mobilizing many internal applications. So, as a part of enterprise mobility, the IT also has to manage the mobile apps. Application management (AM) can be again viewed as having the two main functions :



i. Monitor/Debug apps : Since most of the applications may be internal apps, the development and testing phase becomes critical. Also, since these apps may directly affect employee productivity, debugging these apps during development and after deployment is crucial too. One of the tasks of AM is to help the development and debugging process easier. Once the app is in production, AM can help monitor the status of apps and surface any problems earlier. Monitoring of apps may also refer to getting an apps inventory and determining "blacklisted" apps from security point of view. This may tie back to compliance.

ii. Deploy / Remove apps : With many such applications there is a demand for Enterprise application catalog on which apps would be listed and shown/accessed depending on the role of the employee. Since these apps may contain critical corporate information, it is important for the IT to be able to control these apps remotely. Being able to install, remove these apps is one of the most popular demands from IT.

With Android, anyone can "sideload" an application. This means all the application (apk) files can be accessed via a webpage. However, there are few points to note. In order to install any application that is not listed in the Android Market (consumer app), one has to enable a setting called applications from an "Unknown Source". While doing so, the user gets a dreaded message that may scare him off. Also, it is worth noting that there is currently no official way to push the application on the device and install/uninstall it without the user intervention. If you already have your device admin agent on the device, then it can download the app binary and trigger the install process or trigger the uninstall process of an existing app which will redirect the user to the install/uninstall approval screen. There are some app markets (like AppBrian) which have (with limited capabilities) "managed" to remotely push and install applications on Android phones. However, there is no official way to do so.

So, here is a complete picture of how I see Enterprise mobility as of now:




To summarize, Android really doesn't have much to offer at this moment apart from few Device Admin APIs and Encryption (hardware dependent - 3.0 onwards). With the growing demand for Android and the changing trend of Employee liable devices, it certainly is a challenge for IT. The Google enterprise team unfortunately didn't seem to address most of these issues and didn't seem open to a lot of questions posed at the GoogleIO. The talk at GoogleIO can be found here : (http://www.google.com/events/io/2011/sessions/taking-android-to-work.html) I hope they have some plan for the Enterprise mobility because the wave has just begun.


Monday, May 9, 2011

Understanding Enterprise Mobility


[I'm sitting at a Starbucks waiting for the GoogleIO registration to open up. There is an interesting session 'Taking Android to work' which I'll be attending. Google's approach to enterprise mobility seems to be different than Blackberry or Apple : they don't have anything baked into the platform. The GoogleIO session will hopefully provide more insights into the future path. If you are an attendee and interested in this topic, I would definitely love to have a chat with you. You can follow me on Twitter : @advantej ]

For the past few months, I'm trying to understand the enterprise mobility space. It had kind of existed in the past but emerging again with a new face altogether. Its definitely a larger wave than the earlier one.

A look into the past: 
Laptops introduced mobility into enterprise. There were cell phones before, but those weren't 'smart' enough. Their primary purpose was just to carry out conversations. Laptops made it possible to take the work with you. There was also a short period that showcased Personal Digital Assistants (PDAs) which were rather bulky to carry around and capabilities mostly limited to managing your schedule, taking notes and some basic messaging. But the truly workable mobile devices were laptops.

The Enterprise Viewpoints: Two sides of a coin
The Good:
For enterprises, mobility means a lot. It is a means of growing business, capturing opportunities and bringing back information, knowledge, keeping the organization going on, no matter where the people in the organization are. Be it the CEO, CTO, marketing or sales people or any other management folks or your awesome engineers: mobility builds the necessary bridges whenever it matters to achieve the required goals.

The Worrisome:
However, practically this means accessing company resources from devices and environments on which enterprises may not have any control. While mobility helps enterprises grow the concern about information security in uncontrolled environments makes enterprises take a step back.

In the laptop/PDA wave, managing devices was pretty much conventional. There was nothing new to do at least for the laptops because they had to deal with the same operating systems on laptops for which IT management was already being used for a long time.

For pretty much long time, RIM provided enterprises with a solution to control the Blackberry mobile devices, enabling them to configure, manage and enforce policies on the devices.

With Apple and Android powered devices entering the consumer market with different form factors, mobility has a new face. Not just that there are a lot of devices from different vendors and operating systems, its the fact that employees are consumers first. They are pretty much demanding the use of devices of their choice for accessing enterprise resources. Moreover, people don't like to carry multiple devices : a personal device and a company owned device. They want it there - all in one.

The challenge for the IT is to support multiple mobile devices ensuring safety and security of enterprise resources. Apart from security which is central to enterprise mobility, IT demands being able to configure devices no matter what OS its running.

Being a newbie to this space, I think of a lot of questions that I'm trying to answer. With many enterprise applications emerging, is enterprise mobility management limited to managing just the devices ? What about the applications ? Do we need to control and analyse those too ? With employee owned devices is it acceptable to enforce enterprise policies all the time ? Some policies require control over the hardware as well. In my masters thesis, I explored context awareness frameworks for mobile devices and prototyped one. I was wondering if it makes sense to exploit user context for enterprise policies. This may help in selectively applying policies depending on user context. This may help develop a win-win situation where employees don't feel controlled all the time but would be able to access the required resources. (For curious reader : here is an interesting academic research project trying to identify high level contextual aspects for a mobile user.)

Have got these questions and many more.... but one thing for sure - this wave is very large, unavoidable, with a lot of challenges and comes with competitive problems for the architects and engineers to solve.


[Thank you Starbucks for the internet !]

Thursday, March 31, 2011

Android Thread Constructs(Part 4): Comparisons

In this series of posts we have seen the following thread constructs:
1. Basic threads and communication between them [see article]
2. Understanding the Main thread or the UI thread [see article]
3. IntentService [see article]
4. AsyncTask [see article]

NOTE:  These are Android specific constructs. Android also includes the java.util.concurrent package which can be leveraged for concurrent tasks. That is out of the scope of my discussion.]

So, when to use what ? What is the exact purpose of each ? What are the drawbacks of using one over the other ? Which one is easier to program ?

I came across all these questions when trying to understand each of these. In due course of time, I have come up with some guidelines which I discuss in this post.

NOTE: Any of the recommendations made in this post and the table below are not comprehensive and final. There may be better and alternate ways of doing things. I would love to know any different views and get an insight into a different thought process. The views expressed in this post are my personal views.

Service
Before proceeding further, let me touch on the Service class. Traditionally speaking, the notion of service reminds us of task running in the background while we can work and interact with the UI. This causes confusion for newbies. Because in Android, even if the Service runs in the background, it runs on the Main Thread of the application. So, if at the same time if you have an activity displayed, the running service will take the main thread and the activity will seem slow. It is important to note that a Service is just a way of telling Android that something needs to run without a user interface in the background while the user may not interacting with your application. So, if you expect the user to be interacting with the application while the service is running and you have a long task to perform in a service, you need to create a worker thread in the Service to carry out the task.
So, even if Service is not a threading construct, its a way of executing a task at hand. Hence I have included it in the comparison.

The table below tries to summarize various aspects of four task execution mechanisms : Service, Thread, IntentService, AsyncTask.

Most of the points in the table are self-explanatory. However, some points that need an explanation are numbered and explained  below the table. Also, this table is just to summarize about the concepts discussed in the previous posts. So, if anything is still unclear, I recommend to go through each individual posts in this series.



ServiceThreadIntentServiceAsyncTask
When to use ?Task with no UI, but shouldn't be too long. Use threads within service for long tasks.- Long task in general.

- For tasks in parallel use Multiple threads (traditional mechanisms)
- Long task usually with no communication to main thread.
(Update)- If communication is required, can use main thread handler or broadcast intents[3]

- When callbacks are needed (Intent triggered tasks). 
- Relatively long task (UI thread blocking) with a need to communicate with main thread.[3]

- For tasks in parallel use multiple instances OR Executor [1]
TriggerCall to method
onStartService()
Thread start() methodIntentCall to method execute()
Triggered From (thread)Any threadAny ThreadMain Thread (Intent is received on main thread and then worker thread is spawed)Main Thread
Runs On (thread)Main ThreadIts own threadSeparate worker threadWorker thread. However, Main thread methods may be invoked in between to publish progress.
Limitations /
Drawbacks
May block main thread- Manual thread management

- Code may become difficult to read
- Cannot run tasks in parallel.

- Multiple intents are queued on the same worker thread.
- one instance can only be executed once (hence cannot run in a loop) [2]

- Must be created and executed from the Main thread

[1] API Level 11 (Android 3.0) introduces the executeOnExecutor() method, that runs multiple tasks on a thread pool managed by AsyncTask. Below API Level 11, we need to create multiple instances of AsyncTask and call execute() on them in order to start parallel execution of multiple tasks.

[2] Once you create an object of an AsyncTask and call execute, you cannot call execute on that object again. Hence, trying to run an AsyncTask inside a loop will require you to each time create a new object in the loop before calling the execute on it.

[3] Recently I was brought to notice that AsyncTask is not recommended for long running tasks. While this is technically possible, I agree with the commenter. The idea here is any task which would potentially block the UI thread - I referred to this as a long task. May be I should have been clear. Thank you for pointing it out.


To be very precise, you cannot do something like :
        TestAsyncTask myATask = new TestAsyncTask();
        for (int i = 0; i < count; i++) {
            myATask.execute("one", "two", "three", "four");
        }

But you can do :
        for (int i = 0; i < count; i++) {
            TestAsyncTask myATask = new TestAsyncTask();
            myATask.execute("one", "two", "three", "four");
        }

[3] Thanks to comment posted by Mark Murphy (@commonsguy) : "there's nothing stopping an IntentService from communicating back to activities. A broadcast Intent is good for that, particularly with setPackage() to keep it constrained to your app (available on Android 2.1, IIRC). An ordered broadcast can be particularly useful, as you can rig it up such that if none of your activities are on-screen, that some manifest-registered BroadcastReceiver picks up the broadcast and raises a Notification."

Conclusion:
With a pretty understanding of the AsyncTask and the IntentService classes provided by Android, it would be a good idea to leverage these for most of the tasks as against trying to manage threads manually or implement your class as a Service unless there is really a need to do so.

Tricky Things:
There are some tricky scenarios that need some special handling. After all, we are dealing with a mobile environment and things are pretty unpredictable. For instance, the user opens your activity in which you start an AsyncTask, but before completion of the task, the user decides to exit the application (say by pressing the back button). Or your activity may be terminated (read kicked off) due to say an incoming call, when you are running a long task in the background. In such cases, where your application is not shutdown, but any foreground tasks have been closed or changed, all the background tasks need to know of this and try to exit gracefully.

Friday, March 18, 2011

Android thread constructs (Part 3) : AsyncTask

After examining thread communication, UI thread and then IntentService, I would like to talk about another threading construct called AsyncTask.

Similar to IntentService, AsyncTask allows us to run relatively long running tasks in the background. However, unlike IntentService the implementation is not straight forward. One of the reason people might think is that it involves generics ! There is no need to be afraid about those really. We just need to know 2 important things. One is the type of data that will be moving around and secondly these types cannot be primitive types like int, float, boolean etc... Before going further into the implementation, let me try to explain at a conceptual level.

NOTE: Recently I was brought to notice that AsyncTask is not recommended for long running tasks. While this is technically possible, I agree with the commenter. The idea here is any task which would potentially block the UI thread - I referred to this as a long task. May be I should have been clear. Thank you for pointing it out.

Concept:

You have a long task to do. You extend the AsycTask class and somewhere in there, specify your task. Then, from the main thread, create an instance of your extended class and call the execute() method. This should somehow result in a background thread executing your task. Pretty simple !

Now, there are 3 kinds of data that you will be dealing with:
1) Params : The parameters you pass on to the background task
2) Progress : The data units which the background task will be passing to you (UI thread) reporting its progress.
3) Result : The data that will be returned by the background task (to the UI thread) on completion.

Clearly there seems to be a communication going on between the UI thread and the worker thread. Hence, I like to visualize the AsyncTask as follows:


All the methods mentioned in the diagram will be a part of the extended AsyncTask class but however will run on different threads as indicated.

1) You have an instance of the AsyncTask and will call the execute() method. This method runs on the UI thread and serves as a trigger to the platform to spawn a worker thread.

2) Before handling the control to the worker thread, the platform will execute the onPreExecute() method on the main thread. We can perform any necessary task setup.

3) After this method finishes, the platform executes the doInBackground() method on the worker thread.

4,5) Now, whenever the worker thread calls the publishProgress() method, the platform calls the onProgressUpdate() method on the main thread with the parameters passed to the publishProgress() method.

6,7) Finally when the long running task is over i.e. the doInBackground() method returns, the return value is passed to the onPostExecute() method.

And, for all this to happen our AsyncTask class needs to know the datatypes for the 3 kinds of data discussed above.

It is important to note that just like IntentService, AsycTask also spawns a SINGLE worker thread and hence only one task can be run in background. Furthermore, once an instance of our AsyncTask is created, you can call the execute() method on it only ONCE. An exception will be thrown if you try to call execute() on the same instance of AsyncTask more than once. Hence, with AsyncTask if you want to run multiple tasks in background, create multiple instances and call execute on them.


Note: API level 11 (Honeycomb) adds the executeOnExecutor() method which enables to run multiple tasks on a pool of threads managed by AsyncTask class. I have not studied and tried this. I will update the post (or write a new one) once I try this out.


Implementation details:

Extend the AsyncTask class and pass to it the datatypes for Params, Progress and Result

class TestAsyncTask extends AsyncTask<String, Integer, Integer> {
}

So, here, we are telling that our worker thread will accept String parameters as input, the worker thread may publish the progress to the main thread as an Integer value and finally the return value of the doInBackground method will be an Integer. Note that the Integer class is used instead of primitive data type int.

Now, It may happen that, you have a worker thread that doesn't need any input, doesn't wish to convey any progress or any result. In that case, the AsyncTask definition will look like:

class TestAsyncTask extends AsyncTask<Void, Void, Void>{
}

Okay. Sticking with the first example, lets add in the doInBackground, onProgressUpdate and onPostExecute methods.


class TestAsyncTask extends AsyncTask<String, Integer, Integer> {

    protected Integer doInBackground(String... strings) {
        // Long running task - say processing of each passed string
        for (int i = 0; i < strings.length; i++){
               // Do processing of strings[i]
              publishProgress(i); // publish that ith string is processed
        }
        return 0;
    }

    protected void onProgressUpdate(Integer... item){
        Log.d("TestP", item[0] + " item has been processed");
    }

    protected void onPostExecute(Integer result){
        Log.d("TestP", "AsyncTask returned : " + result);
    }
}


From the main thread (say from your Activity or service), create an instance of the AsyncTask.

        TestAsyncTask myATask = new TestAsyncTask();
        myATask.execute("one", "two", "three", "four");

As mentioned before, if you want to run multiple AsyncTasks in parallel, just create another instance and call execute on it.
        TestAsyncTask myATask2 = new TestAsyncTask();
        myATask2.execute("five", "six", "seven", "eight");

There are 4 threading rules we need to follow for AsyncTask to work properly. These are mentioned in the AsyncTask documentation,  but I'll mention those again so that everything is available at one place.

1. The task instance needs to be created on the main thread.
2. The execute() method needs to be called on the main thread.
3. Do not  explicitly call any of the preExecute(), postExecute(), doInBackground() and onProgressUpdate() methods.
4. The task can be executed only once on one instance.

Thats all you need to know to execute AsyncTask.
I'm pretty much excited about my next post. I'm planning to do a comparison of various background mechanisms that we have seen till now as well as try to come up with some guidelines. I'm still working on it, hope to post them soon. Stay tuned !