Wednesday, September 26, 2012

PendingIntents in Android

PendingIntents in Android are fundamentally used for allowing other apps to perform actions on behalf of your app regardless of your app is alive or not. For example, if you want to perform some action in the future, you just create a PendingIntent and populate with an Intent and then giving this to the AlarmManager to wake you up at the specified time. Simple enough!. 

Complexity appears when you want to control the pending intents. Just think about a scenario in which you created a PendingIntent and want to perform an operation in the future. However, you realized that you no longer need to perform this operation which means you now need to cancel it. Android provides cancel operation in AlarmManager so no problem. In order to cancel it you need to create the same PendingIntent with the same intent in it. Newly created intent should return true for the intent.filterEquals(Intent otherOne) method. If it fails, then cancel operation will not succeed. This method basically looks for the same action, data, type, class, and categories for the same intents. So far so good!. Now think about a scenario where you need to create multiple pending intents, but want to use the same BroadcastReceiver. There are two alternatives here: first you can create an intent with different intentFilters, i.e. action. So you need to register your broadcast receiver to every different intentFilter you create. Sigh!. And the worst part is when you want to unregister, there is no option of unregistering for a particular intentFilter. If you unregister your receiver, all of the intentFilters goes away automatically. 

There is a hidden parameter called requestCode while creating the PendingIntent and it basically serves this purpose. If you create exactly the same pending intents but differ only in requestCode then canceling one doesn't cancel the other one. It means requestCode can be used to uniquely identify pending intents. Therefore, you can use the same BroadcastReceiver (and registers one) with the same intent, but with different PendingIntents if you change the requestCode. The funny and sad thing about this is: Android documentation states that "request code is currently not used". On the other hand, it is actually used to differentiate PendingIntents and it is quite useful.

Sunday, September 2, 2012

LineKing: Crowdsourced Line Wait-Time Estimation using Smartphones

We all suffer from waiting in the lines of coffee shops, banks, DMVs and many more such places. I can easily enumerate hundreds of such places. Even in the advent of technology in many areas of life, we still have to wait in the line of a coffee shop to get our simple order done. This could take a few minutes or if you're in a popular place, then it would even take more than 20-30 minutes. Think about how many times you entered a line and thought of leaving instead of waiting such a long line. Or you may even think to switch the line to get to the cashier faster if the place have more than one line. The thing is; you never know unless you visited the place. Below showcases the dilemma we face everyday.


Ok, maybe it is more of a luck then estimation on this particular case and it might be very difficult to estimate this particular one too. But most of the lines aren't that unpredictable, and most of them exhibit pattern that repeats itself time to time, day to day and season to season. The point is; isn't it awesome to know how many minutes you'll wait in the line of your favorite coffee shop in a particular time. Moreover, if you just look that information up from your mobile phone, then it would even be better.

We recently published a paper called: "LineKing: Crowdsourced Line Wait-Time Estimation using Smartphones" in Mobicase, 2012. We developed a smartphone application that can detect the time spent at Tim Hortons in the Student Union of University at Buffalo. We utilize domain specific, i.e. for both Android and iOS, localization techniques to understand the time spent at this particular place. This includes both location-sensing and WiFi-sensing. Once we detect a wait-time, we immediately send this information to our server deployed at AWS EC2. 

We had many challenges during the initial phase. At first, we got a very few readings as we hadn't had too much user-base. But once the popularity of the application increased along with a viral advertising campaign, we quickly reached 1000s of users that provides 100s of readings daily. At first this was amazing as we thought we're very close to the solution that gives users real-time estimation of the current status of the lines. 

We quickly noticed that "having lots of data is good only if you can interprete them". So, we started to analyze the data to have an understanding of how line wait-time evolves and later developed an approach to estimate future wait-times. First, we built a heuristic nearest neighbor estimation (NNE) algorithm. The idea is; for a given query, lets say January 1st, Monday 11am, find the 5 similar previous point in the history that has the highest similarity to the given query. To implement this, we represent every data with 3 dimensions namely; "week of the year", "day of the week" and finally "interval of the day"; [w,d,i]. The problem here is to define a similarity metric between vectors. To do this, we assume that wait-time (v) is linearly dependent to each dimension of the data vector; [w,d,i] as v = a*w + b*d + c*i. Using the previous history of wait-times, and using linear regression, we estimate the optimal a, b and c parameters and use these parameters to calculate the dissimilarity between two vectors; d(v1,v2) = a*(w1-w2) + b*(d1-d2) + c*(i1-i2). So the problem is to find the 5 most similar ones from the history of wait-times for the given query. Then we take the avg. of them as the forecasted value. This technique (constrained nearest neighbor search in a multi-dimensional space) works well and provides MAE of ~3 minutes. Since the wait-time changes between 2 to 20 minutes in this particular coffee shop, it wasn't a bad estimate.

Second, we thought of building a model, specifically a time series one, to improve the estimation, however we quickly realized that our data neither complete nor uniform. Although, we had 100s of readings daily, it was not enough to fill all the 10 minutes intervals that we want to estimate. In reality, general time series analysis depends on data that is uniformly distributed along the time. So if we wanted to use a model then we had to construct a uniform and equally spaced data before building any kind of model. This was basically a missing data problem: for the intervals that don't have any readings we need to fill them out in some way. One way to deal with missing data is to use regression and our NNE technique is a perfect fit to this problem. Hence, we use our previous approach (NNE) and fill the missing data. Now, we have a complete and uniform data, so we can build a model from it. We consider ad hoc exponential smoothing and a more complex Holt Winters as models. Our results indicate that we improved our previous results around 1 minutes and reduced MAE to ~2 minutes. Our results also indicate that exponential smoothing and Holt Winters exhibits similar errors where Holt Winters beats exponential smoothing in small margins. Since our experiments was only for 8 weeks of data, we believe that margin will increase as we have more data that shows more seasonality and trends. 

This is basically the story of our paper, dubbed as LineKing (LK). Applications can be found on the following link. Our future plan is to make localization more robust while scaling LK to other coffee shops and franchises. 


Sunday, August 5, 2012

Handling Orientation Changes in Android

In Android when the orientation of a device is changed, activity is destroyed and recreated again (onDestroy() and onCreate() methods are called). If you put your logic into the onCreate() method, i.e. network operation to get some data from the server, then everytime you change the orientation onCreate() will be called and it'll make a costly network request each time. Of course this is not good for performance and user's experience. In order to prevent this you have a couple of options. You can either save your activity's state and then check if the state is changed when the activity is recreated or you can simply put android:configChanges="orientation|screenSize" to your activity in the manifest. Note that most of the solutions in the internet propose to put only orientation however as of Android 3.2 screen size is also changed when device moves from portrait to landscape and omitting it cause your activity to be restarted again. You can check the following link for further information:
http://developer.android.com/guide/topics/resources/runtime-changes.html

Tuesday, June 19, 2012

Certificate Failure for UIWebView

If you're using UIWebView for connecting to a website which uses https, you rather hope that website has a trusted/validated certificate. Otherwise, it fails obscurely and you need to implement some tricks to get around this limitation. Btw, I am not sure how app store would react to this kind of change as it may cause some security risks.

Anyway, if you still want to go on, follow these steps. If you never heard of "Category" in Objective-C, I would rather suggest to look at the link (Objective-C categories), before implementing anything. Basically, a Category allows you to add additional methods to a class even the one you don't have the source code. For instance, if you want to add toCompare method to NSString class, you need to implement a category for it. Categories are so powerful; you can even use the instance variables (even if they're private) defined in the original source code. The only limitation is you cannot define new variables.

If we return to our original problem; we need to somehow turn off the certificate checking for the websites which has no valid certificate and insist on using https (this is most of the case your testing host). To do this, you need define a category for the NSURLRequest class and override the private allowsAnyHTTPSCertificateForHost method which takes NSString as a parameter and return bool. I would like to warn one more time to not use this method for the app that you're submitting for App Store, as this is a private method and I suspect that Apple will reject your app. But in any case, it is a good way to temporarily turn of certificate checking especially while testing your app towards the website which has not valid certificate yet.

Authentication/Authorization Protocols

Whoever gets his hand dirty for developing applications needs to handle some form of authorization/authentication in the first place. There are different protocols which gave developers ways to go for different needs and options. OpenId, OAuth and SAML are just some of them that I've had to face so far. Each exhibits different traits and differs in terms of purpose, functionality and the implementation. I'll lay down some of these traits for OAuth and OpenId below.

OAuth
OAuth is designed to solve authentication problem of an application who wants to use the data and functionalities of the provider. In this case provider can be Twitter or Facebook and they provide APIs to access user's data. In OAuth, provider returns an access token which provides the application the ability to access user's data on behalf of him. Since access token is used as primary measure of authorization, application don't need to see user's username and password. OAuth protocol is currently in version 2 which differs from the first one in terms of security and complexity. V2 supports security by SSL while the v1 expect application to provide this. So it is a huge win for v2. Twitter, Facebook and Google all supports v2 now.

OpenId

OpenId is another standart protocol which is used for authorization (as opposed to OAuth which is used for authentication mostly) in a decentralized manner. The basic logic behind OpenId is to eliminate the need for implementing sometimes complex and obscure authorization module for applications. Basically this is delegated to some third party namely OpenId providers. User can register himself through these providers and use the same username and password for authorization to another application. Google, Yahoo and IBM are just some of the providers...

Thursday, February 2, 2012

Install/Uninstall .apk to System Directory on Android

Here is a simple way of installing and uninstalling an .apk to system directory on Android.
  1. Open adb shell
  2. su
  3. mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system
  4. cat /sdcard/[YourAppName].apk > /system/app/[YourAppName].apk
  5. mount -o remount,ro -t yaffs2 /dev/block/mtdblock3 /system
  6. reboot

To uninstall issue following commands:
  1. mount -o remount,rw -t yaffs2 /dev/block/mtdblock3 /system
  2. rm /system/app/[YourAppName].apk

Monday, January 16, 2012

Location Sensing on Android

Android provides several mechanism to sense location of the device. It utilizes three main sources in order to learn location, i.e. GPS, Wi-Fi and Cell Tower. Last two are grouped into Network category under the Android documentation. Accuracy of GPS can be up to 5-10 meters in an open sky environment. GPS is known to have some problems especially in indoor conditions, hence other mechanism need to be exploited in order to learn location more precisely (Google is known to work on indoor mapping). Wi-Fi and Cell Towers are among the alternative tools one can use to learn location. Especially, Cell Tower could be very useful especially for the application which needs coarse-grained location information to work (most applications can fit into this category). Another advantage of using cell tower is its availability: mobile devices are always connected to network, i.e. location information is already available. Also note that smartphones are known to be battery hungry, so instead of opening GPS up, using already available information one can preserve a lot of battery. Here the downside comes: in order Cell Tower location to be accurate enough (1-2 km), it needs to be supported by a method called triangulation. However, to my surprise, sometimes, if cell tower changes (even when you're not moving), location can also changes dramatically (the circle can show you somewhere where you actually not). You can try this out by turning off GPS, Wi-Fi and opening the Map application with 3G. Although it doesn't happen frequently, Android's cell tower information can actually be tempting if your application depends on this crucial information.

After a lot of experimentation and exploration I ended up with the claim that Android fails to provide a nice and clean way of accessing location information. Although it seems to give developers freedom of choosing the source of learning, it doesn't give it as a uniform, power-aware way. Therefore, no wonder to see a lot of applications which drain user's battery carelessly. A lot of papers coming to alleviate this problem recently, citing one of them here.

[1] Improving Energy Efficiency of Location Sensing on Smartphones

Friday, January 13, 2012

Is it safe to rely on onDestroy() method of a Service

When running a service (either Service or IntentService doesn't matter), sometimes we need to wrap up things to degrade safely. For this, one can tempt to use onDestroy() method of the Service. However, keep in mind that this method is called by the System and it doesn't guarantee of calling in time: depends on several factors including the memory constraints. Therefore, one should not rely on this method to do critical wrap up operations, such as releasing a wake lock. Same argument is also valid for the Activity. More information can be found on the following links:

http://developer.android.com/guide/topics/fundamentals/services.html
http://developer.android.com/guide/topics/fundamentals.html