A common problem for Android developers is figuring out how our app will act under different network conditions. From slow connection speeds to none at all we need to make sure the user experience remains enjoyable.
In addition, we also have to comply with today’s web standards, and those standards say every response must have a response code. We take these response codes very seriously and use them to determine if our request succeeded or failed.
At TaskRabbit we use Retrofit to send requests to our web API. The response we get back is captured and converted to success or error using a callback we attach with each request. Success callbacks are easy to test by simply using the app and seeing it progress as we interact with it, but errors are another story. Errors come in all shapes and sizes. Was it a user error? A server error?! A network error?!?! It’s important to make sure our app acts appropriately for all kinds of errors.
For example, our server will send back a 426 (upgrade required) response code when a user is on an outdated version of the app. This means they have to upgrade before they can perform any actions, regardless of where they are in the app. If we get a 422 (unprocessable entity) response code it’s because the user entered invalid data that we did not catch on the app, so we want to display an understandable error message, hide spinners and re-enable user input.
We found ourselves with the following questions:
- We want to test how an activity will behave after receiving specific response codes. How can we get the phone to think it received a 426 or a 422 without changing any code from the app or server?
- In slow network conditions our app may be waiting 10 - 20 seconds for a response. That's a lot of time! What if the user navigates to another activity during this time? We need to make sure our callbacks don't bomb out trying to move components on a view that is no longer rendered. How can we test slow network connections from the fast network speeds within our office. Airplane mode isn't going to cut it.
What is Charles? In a nut shell, it’s an HTTP proxy we use to intercept requests from our phones. It will serve as the middle man between the phone and the server.
How Does Charles Help?
We use Charles for both network throttling and changing the response code that gets sent back to our phone. At any point we can tell Charles to forget about going to the server, just send back this response. So when we want to make sure our form allows user input again after getting a 422, before hitting submit we can enable rewrite (on Charles) and get back a 422 response code. If you want to try this I describe an example below.
Set Up Charles
Before doing anything we need to quickly install a certificate on our phone that will allow Charles to see its SSL requests.
- Make sure your computer (with Charles installed) and Android device are on the same wifi network. At the time of writing this we are using Charles 3.10.1.
- From Charles go to [Help] -> [SSL Proxying] -> [Install Root Certificate On A Mobile Device Or Remote Browser...]. You'll see a small window with instructions open up. Leave this open.
- On your Android device go to your list of wifi connections. Find your current connection (assuming its on the same network as your computer) and long click it to modify it.
- At the bottom of the dialog that opens there should be a check box to "Show Advanced Options". Make sure it's checked.
- Select "Manual" in the "Proxy" drop down.
- Now enter the "Proxy host name" and "Proxy port" details that are showing on the Charles window you opened above. Hit "Save"
On your phones browser go to "charlesproxy.com/getssl". You'll see something like the picture below. Name the certificate anything you like and hit "OK".
Now go back to your computer. In Charles hit the "Sequence" tab. You should see any HTTP requests your phone has made.
Throttling Network Speeds
This is pretty self-explanatory and can be done in [Proxy] -> [Throttle Settings].
Modifying Response Codes
Here is how you can use Charles to take requests going to google.com and give back a 426 response code.
Open Rewrite Settings. [Tools] -> [Rewrite] and make sure "Enable Rewrite" is checked. Hit "Add" at the bottom. You should get something like this.
In the "Locations" panel, hit the "Add" button and in the window that appears enter "google.com" for "Host" and hit "OK".
Now in the "Rules" panel, hit the "Add" button. In the window that appears from the "Type" pulldown select "Response Status". In the "Replace" section enter "426 Upgrade Required" for "Value". Hit "OK".
- Hit "Apply"!
Go to your phones browser and go to "google.com". You should see this come up on Charles.
The fun doesn't end here. If you want to add json payloads to your response, add a new "Rule" in the "Rewrite Settings". From the "Type" pull down select "Body". Make sure only "Response" is checked. Write some json inside the "Value" input field in the "Replace" section like shown below. Apply these changes.
Now your response will have the following text with it.
The browser on your phone will look like this
For as long as your phone is using your computers’ proxy and rewrite is enabled you’ll always get back a 426 response code whenever you send a request to google.com.
I hope you found this useful and easy to follow!