Saturday, May 28, 2011

How to build the web project on the CI server without Visual Studio 2010

On one of the ASP.Net project, we were using Visual Studio 2010 IDE and MSBuild, to compile and build the application.  Pretty standard setup for a web project right?.  On developer machine all worked very smoothly, since each developer had Visual Studio 2010 installed locally on their machines.

We setup a continuous integration (CI) server Jenkins (formally Hudson) for this project.  Naturally, we didn't wanted to install Visual Studio 2010 on the CI server.  But we still wanted to build our app on the CI server.  Hence, we installed Microsoft Windows SDK 7.1 and all its components on the CI server.  After installing the SDK, we were able to build all projects except the web project on the CI server.

The error that we were getting was

Obviously, since the Visual Studio 2010 was not installed on the CI server, the path mentioned in the error didn't exist and that's why the web project was not able to build.

I opened the csproj file in Notepad++, to find the reference of "Microsoft.WebApplication.targets".  I found a reference of "Microsoft.WebApplication.targets" in the csproj which looked liked 

Indeed the web csproj file had an import statement, which added the reference to "Microsoft.WebApplication.targets". But I was not sure why this reference was needed in the first place.

My first attempt at fixing the CI server:

I removed the reference of "Microsoft.WebApplication.targets" from the web csproj file and tried building the application using MSBuild.  To my surprise, the app build fine, it ran all the tests without any issue.  My confidence grew a little, I thought I had the solution.  I thought the reference was added to the csproj by Visual Studio 2010, but was never used.

I committed the fix, build went green on the CI Server as well!

After a few hours, some developers complained that, when they now open up the web project, Visual Studio 2010 prompted for converting the project into a Visual Studio 2010.  Certainly, this behaviour was triggered after I removed the import statement from the web csproj file.

Its pretty clear now, why the import was required.  Visual Studio 2010 identifies that, the project is a Visual Studio 2010 Web project using the import of "Microsoft.WebApplication.targets".  Hence, although the build run's fine using MSbuild on developer machine as well as on CI server this is not the right fix!

My second attempt at fixing the CI server:

Googling a little I found that, there are only two options to fix this particular issue.
  • Install Visual Studio 2010 on the CI server
  • Copy the "Microsoft.WebApplication.targets" file manually from any developer machine to the CI server
It was sad to see that there was no standalone installer that installed the "Microsoft.WebApplication.targets" at the desired location.  We had to either install the full Visual Studio 2010 or copy the file manually.


I decided to chose the lesser evil of the two.  We copied the file "Microsoft.WebApplication.targets" from my machine (located at path C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications on a Windows 7 64 Bit installation) onto the CI server (at the path C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications.  CI server has Windows 2003 OS installed on it.) and then ran the build.  Yep! It worked!  The build went green on the CI server.

I know, its just an hack, but for now I had no other option!

Saturday, May 21, 2011

iOS: Fixing the WiFi connection closed after 30 minutes

One nice Saturday afternoon when I was doing almost nothing, I got a phone call.  The number was big and didn't look like it was from India.  I picked up the call and said "Hello...", a familiar voice replied back.  The voice was of one of my good friend.  This friend of mine had gone to Germany for a month, his iOS project was going live.  He had called me that afternoon to discuss about a problem that he was facing in his app.  

The Problem

The application was to be deployed on iPad.  Application used to poll the server for updates every 10 seconds.  For the application to work correctly, it was necessary that the polling should work flawlessly.

This polling worked well, however, he was facing one ugly little problem.  The issue was, after about 30 minutes, the polling would stop and because of this the application would not function correctly after 30 minutes.  This would happen only if the iPad is not connected to the charger or a computer.  If the iPad was connected to the charger or a computer polling would function correctly for any duration.

The workaround

To get the polling to work again user has to do one of the following
  • Connect the iPad to a power source i.e. a charger or a computer
  • Pressing the home button on the iPad and reopen the application
The Fix

I had not faced this issue earlier.  In fact, I have not done much iPhone development (at least non yet), but I decided to give it a shot anyways.  I decided to google about this issue and find a fix.

After some intense googling, I found that, iPad switches off the WiFi connection automatically after 30 minutes to preserve battery.

That's a good strategy alright but, what about the apps like my friends app?  The app need to poll the server every 10 seconds to function correctly.  How can we stop the iPad from switching off the WiFi connection automatically after 30 minutes?

The fix was pretty simple, One needs to set a property in the property list file.  The property is called UIRequiresPersistentWiFi.

Quoting from the Apple developer documentation
UIRequiresPersistentWiFi (Boolean - iOS) specifies whether the application requires a Wi-Fi connection. iOS maintains the active Wi-Fi connection open while the application is running.
 That was it!  I knew that, I have found a fix to my friends problem.  Asked him to add the property to the plist file and do a test again.  As expected the problem was solved.  Now, the app was able to poll the server for any duration without a problem even when the iPad was not connected to the power source!

Simple things like this waste a lot of developer time, but once you learn something the hard way, you will never forget it!

Saturday, May 14, 2011

Fixing the "skia decoder->decode returned false" error while downloading images on Android

I had to implement a common requirement in one of my Android project.  I had to show a image that was hosted on the web, in my Android application.  Now that is a very common situation right?  I am sure you must have faced this situation before.

I would have imagined, showing the images from the web would be as simple as setting the correct image source URL to the ImageView.  But as it turns out life is not always that simple. 

So how do we show the images from the web using the ImageView?

  • We have to first download the image using the HttpClient
  • Decode the image data using BitmapFactory and convert it into Bitmap
  • Associate the Decoded Bitmap with the ImageView
Lets look at the code to show the web image in the ImageView

The above code works and works well, it does show the image hosted on the web in the ImageView.  However, sometimes, I get an error in the log saying

Now, this is something unexpected. Whenever I get this error the image download stops and image is not shown in the ImageView.
The Cause:

Googled a little and as usual, I was not the only one to face this issue.  There are lots of threads online, that mention this particular issue (here and here), "decoder returned false". 

It seems that when skip method of the InputStream class does not skip the given number of bytes then, the BitmapFactory fails to decode the InputStream.  Usually, the issue occurs on a slow internet connection.  However, I cant confirm that, I have a 2Mbps dedicated internet connection, even on this connection issue is reproduicable! 

The Fix:

There are two ways of fixing this issue.

Method 1 - Method that involves writing some custom code

This method makes sure that, the skip method of InputStream actually skip's the mentioned number of bytes.

To do this, we will need to wrap the InputStream into a custom class, override the skip method and ensure that we skip the given number of bytes no matter what.  This can be achieved by subclassing the FilterInputStream class and overriding the skip method.  Lets look at how the new implementation of the skip method.

As seen in the above code, the skip method simply makes sure that we skip the give number of bytes.  The class FlushedInputStream now needs to be used while we decode the image. The updated code with the FilteredInputStream looks like

Method 2 - Method that involves using the BufferedInputStream

This method is very simple and straight forward we simply need to wrap the imageContentInputStream with the BufferedInputStream. This also seems to fix the problem. The updated code looks like

Yep, these two methods fix the "decode returned false" issue.

Saturday, May 7, 2011

Is your Bank Account safe with ICICI bank?

ICICI Bank is one of the biggest bank in India.  Its renowned for having most number of ATM (after SBI) in the country.  I always though that, ICICI Bank has a good security model to prevent online thefts.

No, this post is not an advertisement of ICICI bank, I wanted to share a weird experience that I had with ICICI Bank.  This experience will expose the security model of ICICI Bank.  Over and above it, I wanted to help them correct their mistake, but they didn't do anything as yet.

So what was the incident, how did I try to help and what was their response?

The Incident

One fine Monday morning, I got 4 SMS'es from ICICI Bank, informing me that for a certain account XXXXXXX12345

  • Address has been updated
  • ATM pin number has changed to 1234
  • Land line number has been changed to 020-30212345
  • Mobile number has been changed to 9912345678

When I got those SMS'es, I was a little surprised.  I was holding an account with ICICI Bank but I never requested them to change all this information for my account.  I had not called them for any such requests, then, who call them for changing all this information?  Was my Bank Account hacked?

After some initial anxiety, I calmed down and rechecked those SMS'es.  When I reread the messages, this time a little carefully, I realized that, my bank account number does not end with "12345".  Analyzing further I realized, I do not have a land line whose number is 020-30212345.  Surprising thing was, the mobile number was indeed correct.  9912345678 was indeed my mobile number.  Rest of the details (except the mobile number) were no way related to me.

The Response

By now it was clear to me that there has been a mistake.  I decided to call up the ICICI Bank call center to find out what was wrong.  I cleared the IVR authentication, got my call transferred to the Customer Service Executive.  First, I wanted to confirm that my Bank Account was not hacked.  I asked them if there were any requests made for changing the address, phone number, atm pin of  my account.  Thankfully, there were no such requests made for my account.  

Now the question that was bothering me was, who holds the account that ends with "12345" and why was it associated with my mobile number?  I asked the Customer Service Executive about which accounts are associated with my mobile number?

She said, there was indeed one account associated with my mobile number that ends with "12345".  Bingo! 

Being a decent man, I told her that, the account that ends with "12345" is not my account.  There seems to be a mistake, because of which my mobile number was associated with incorrect account.  She told me, she can see that the account is held by some "Mr. Pathak".  She also told me that the account was newly opened in the "Bhandarkar Road Branch - Pune".  I requested her to kindly delink my mobile number from his account.  She agreed and said this will be done in 2 days.  I was relieved.

By now I was thinking, this is such a big problem.  If someone gave an incorrect mobile number, or the bank's customer service executive made a mistake noting down the mobile number, All vital information will be SMS'ed to the incorrect mobile number.  I knew the other guys ATM pin number, I knew his account number, I knew his address, his land line number.  If this information falls in wrong hands, anything is possible.

By now you must be thinking that the issue must have been resolved.  But unfortunately, the issue does not end here.  After about 5 days I got an SMS informing that 25000 Rs. were credited into the account ending with "12345"

My first reaction to this was, WTF!

I called up the ICICI Bank call center again, to find out why my mobile number was not delinked.  This time they informed me that they cannot delink my mobile number from "Mr. Pathak's" account on my request.  I need to prove that, the mobile number under question is actually my mobile  number.  I asked them, what should I do to prove it.  They said visit any nearest ICICI Bank branch with and ID proof and the post paid Bill of my mobile number.

My reply to that was, I have no motivation to go to the bank to prove this.  Its a clear case of human error, they should have delinked my mobile number from Mr. Pathak's bank account.  

I wanted to help them rectify their mistake, but they will not let me do so.  Why the hell should I waste my time?  I definitely have better things to do!

The conversation ended there.  I was frustrated, why do people stop using their brains?  Why are processes so rigorously implemented that people stop using common sense?  

A few days passed, I got two more SMS informing that 25000 Rs were withdrawn from the account ending with "12345" and the account balance was 0.0 Rs.  The other message informed that, the balance of bank account ending with "12345" had fallen below the allowed limit of 10000 Rs.

This was the limit, I decide to actually visit the ICICI Bank branch and once and for all get my mobile number delinked from Mr Pathak's bank account.  I carried a photo identification proof (my PAN Card) and the post paid bill of my mobile number.  I went to the "Shivaji Nagar - Pune Branch"

The response that I got from the branch was unbelievable.  The lady at the bank said she cannot delink Mr. Pathak's account from my mobile number.  I showed the bank lady, my pan card, even the post paid mobile bill for my mobile number with my name written all over it!

Unfortunately nothing helped, she said she cannot do it.  She said it was against the processes of ICICI Bank!

I urged her that, there has to be a way to do it.  Inform Mr. Pathak about the mistake, get him to rectify this problem.  She assured me that something will be done.  But till date nothing has been done.  Till now I get SMS'es about Mr. Pathak's bank details on my mobile number!

How did I try to help
  • Called up the call center twice to inform them about the mistake
  • Went to the bank and proved that the mobile number indeed belonged to me but still they didn't delink it from Mr. Pathak's bank account.
  • Wasted 5 hrs of my life fixing a problem that didn't impact me much.

What should we learn from this incident

Software is meant to reduce human effort.  Processes are meant to reduce human mistakes.  This incident is a perfect example of what happens when people follow processes and use software without using their brains!

PS: All events and conversations mentioned in the post are real.  However, all Names and Numbers have been changed to preserve the privacy of a certain person.
Have some Fun!