Saturday, March 31, 2018

How to Debug A Pre-built APK

Android Studio 3.0 added a nifty little feature -- The ability to debug and profile pre-built APK's. For developers working with a mix of Native (C/C++) and Java code for their applications, this is an extremely valuable feature.

I stumbled upon it, while I was looking for something else. Wrote this post with the intent that more people will be able to find this feature and make good use of it!

Here are the steps needed to debug a pre-built apk:
  • On the launch screen of Android Studio 3.0+, select the option "Profile or debug APK"
 

  • It will open up a dialog which will let you choose the APK you want to debug.
  • Ensure that the APK is build with debugging enabled
  • Next, Android Studio will try and create a new project in this folder ~/ApkProjects
  • Once it finishes loading the APK it will open up a screen that looks like this
  • As you can see it has unpacked the APK. It shows various part of the APK along with their sizes.
  • It has not fully decompiled *.dex files into *.java files. It show them as *.smali files. 
  • When you open the *.smali file, it will give you an opportunity to Attack Java Sources
 
  • Clicking the link Attach Java Sources will open up a dialog which will let you select the folder where Java sources are located.
  • Once you do this, you should see the Java classes in their full glory. You can now attach breakpoints and debug through the APK as if it was real source code.
  • If your project contains native code, it will let you attach a library containing debug symbols for that too.
  • Hitting the Debug or Run icons on the IDE will popup a dialog which lets you select the Device on which you want to install the APK and start debugging.

  • On selecting the device, IDE will install APK on the device and attach the debugger.
  • You should see a screen like this on the device

  • In a second or so, you should see your app's first screen loaded and ready to be debugged!
  • That's about all that is needed, you can debug, step through the code, evaluate variables and what not!
As you can see its a valuable little feature which can help in locating the bug in tricky situations!

Saturday, March 17, 2018

How to get to Tadoba and things to take along!

We had an opportunity to visit Tadoba Tiger Reserve, its a pristine and unique eco-system situated in the Chandrapur district of the Maharashtra, India. It contains some of the best of forest tracks and endowed with rich biodiversity. Its a brilliant place for nature lovers.

When I was planning the trip, one thing I found particularly challenging was to get pin point location of various safari gates and how to get there. This blog is an effort to help people like me, with landmarks to locate various safari gates. This post also list certain Do's and Dont's to best enjoy the safari.

Safari Gates and Getting There

Tadoba is close to a city called Chandrapur which is around 140KM from Nagpur. I drove to Chandrapur from Nagpur using a Zoomcar (Use my referral code MTI5NDU while making your first booking and get flat 15%(max discount - ₹1500) off).

Chandrapur has a bunch of decent hotels and is about 25-45 KM away from Tadoba Gates. Safari Gates are well spread out so make sure you are book a safari for a gate that is closer to where you are staying.

As a landmark locate Hotel Siddharth Chandrapur on Google Maps, the road to various gates of Tadoba is bang opposite this hotel.

We visited the following gates:
  • Devada Adegaon Agarzari Zone
  • Agarzari Zone
  • Moharli
  • Junona Zone
  • Zhari (Kolsa)




Devada Adegaon Agarzari Zone and Agarzari Zone are right opposite to each other. They are about 25KM from Hotel Siddharth.

Moharli and Junona are pretty close by as well and they are about 35KM from Hotel Siddharth. These gates are around 11KM from Agrazari Zone gates, basically you have to follow the same path but go a little ahead.

Zhari (Kolsa) is on the other side and is about 35KM from Hotel Siddharth.

Here is an interactive map to give you a better idea


Buffer Or Core Zone?

Tadoba has two types of zones, Buffer and Core. Some people say that, there is a high probability of spotting the tiger in core zone, but my personal experience is that its all about a little bit of luck and timing. You need to be at the right place, at the right time, to spot the tiger. To put things in perspective, out of the 4 buffer zone safaris we did, we spotted the tiger in 3 of them!

Safaris are done in open Jeeps with one guide and one driver. One safari typically last for around 3:30-4 hrs. You can book the safaris online from here.


How many safaris to do?

To have a decent chance of spotting the tiger, I would recommend doing at least 4-5 safaris. This gives you a higher chance of spotting the tiger. If you just do one or two safaris, there is a good chance that you would return without spotting the tiger.

We did a total of 5 safaris (4 in Buffer zone and 1 in the core zone). In one of the safari we were extremely lucky to witness a Gaur fight. The idea is not to keep looking only for the tiger, there are plenty of other animals which are equally majestic. Trust me, these safaris are well worth their time and money.

Some random clicks:
Spot the tiger!

I am watching you!
Do's and Dont's
  • Lot of dust will settle on you and your clothes while doing the safaris. Its advisable to carry a scarf or handkerchief to tie around your head and mouth.
  • It will be cold, especially during the morning safari. Do carry something to cover yourselves so that you do not feel too cold.
  • Take ample water to drink and keep yourselves hydrated.
  • Carry some light weight foods like sandwiches to eat if you feel hungry during the safari -- Especially if you have young children.
  • Food options near and around Tadoba Gates are pretty limited. There is a nice MDTC Resort nearby with a decent restaurant. 
  • Please don't litter -- Anywhere!
  • Be patient and don't get disappointed if you don't spot a tiger. There are lots of other animals in the forest to see too. Even the flora and fauna has a lot to offer!

What a hot afternoon!



Closing Remarks

Its a must visit place according to me. If you are a nature lover, you would love to visit Tadoba. Its a very well maintained and protected national park too!

Saturday, February 24, 2018

Using jsoup with Kotlin to parse HTML

Time and again, I have had a need to parse HTML using Java -- And I have hated it. Partly because of much better tools in other languages.

Recently, I had one such need. I needed to,
  • Fetch HTML response from a URL
  • Parse it and scrape information from it
  • Dump it somewhere
  • Do all of the above using Kotlin
Yuck! Parse HTML in today's world? Unfortunately, there  was no known public API that would return JSON or XML or something else. The information was only available as HTML and only way to get that information was to parse and scrape it.

With that in mind, I went and looked out for libraries available to parse HTML using Java or Kotlin. I stumbled upon jsoup.

Its a nice lightweight library to parse real-world HTML. jsoup API is more or less similar to jquery API -- Which makes it a pleasure to use. Without wasting much time lets just jump right into code.

How Do They Do It!

Lets say, we just had a simple requirement, parse the Google Search Result Page and list all the result title's and URL's.

NOTE: I know that google does expose search API to return JSON response, but for the sake of this example just assume it didn't have any such API.

jsoup can be included via many ways. Here's how we could include it via a gradle file.

Next up, lets write a simple test, it will do all of the above mentioned things. Here are the relevant parts of the code.

This prints out the search index, title and URL from the search result page. Here's the sample output

That's about it!

PS: Here's the link to the sample code used in this post.

Saturday, January 27, 2018

Integration Testing first RESTful web service with Kotlin and Spring Boot

We have been building a lot of infrastructure using Kotlin and Spring Boot -- And I am loving it! I have decided to start documenting parts of it for my own reference. I also hope my rant is useful to someone else, who's trying to solve similar problems :D

In this post we will be looking at building our very first RESTful web service using Kotlin and Spring Boot and writing an integration test for it. We will be using Gradle as our build tool.

Gradle File

First important component in the puzzle is the Gradle file. Following is the complete gradle file that we will be using for this post. Notice the use of all-open plugin. This is needed so that Spring can Autowire dependencies into our Kotlin classes.


Code

Lets create a very simple Book data class, it has got properties like title and author.


Adding a BookController, it has only one method which serves the requests from /books/search?title={title} path. This method will return the details of the books whose titles contain the searched term.

Note: The books collection is hardcoded for this example but nothing stops us from getting it from an external source, e.g. a database.


Next we need to add the application class which will expose the main method.


Test

The fun part about Spring Boot + Kotlin is the ease of testing this service. We will test this service out in two ways

  • Testing the API in browser
  • Writing a integration test 

Browser Test
  • Boot up the server using the following command
  • If everything goes great you should see a message informing that the server is up and running.
  • Open up the browser and open the http://localhost:8080/books/search?title=Steve
  • You should see the following response in the browser

Integration Test

Spring Boot provides a convenient class TestRestTemplate to test out the REST api's. Here is an example test for testing our API


As you run the test, notice that it boots up the server, invokes the api and fires the asserts on the responses!

Bonus

The toJson and fromJson methods are extension methods, they convert Objects into JSON representation and visa-a-versa. I use them all the time, they are pretty handy!

Project Structure

The best way to show this is via a screenshot.


Thats about it, we have a web service written in Kotlin using Spring Boot and we have successfully written a test for it as well!

PS: Here is the complete source code of the example used in this post


Friday, September 30, 2016

ICICI Bank and their goof-up's!

This is yet another post to highlight goof-up's made by ICICI Bank (one of the biggest banks in India).

What I wanted to get done?

My current debit card had a problem because of which it used to work in some ATM's and some ATM's refuse to accept it.  All I wanted, was to get a replacement debit card.

Goof-up 1
  • I went to the ICICI Bank branch which is almost next door to where I stay.  
  • Told them I want to get a replacement debit card
  • The bank representative took the request and assured that the card will be delivered in 10 days
  • To my surprise after a few days I received a message saying my new cheque book has been dispatched to my communication address.
  • So although I wanted a replacement debit card they decided to send me a cheque book instead :P
Goof-up 2
  • Since visiting the branch didn't seem to solve my issue, I decided to place the request for my replacement debit card using Phone Banking.
  • The lady took the request and gave me the tracking number as well.  
  • I checked with her, the address to which the card will be delivered and it was accurate
  • She assured me that the card will be delivered in 10 days.
  • After a few days, I got an SMS saying the card has been dispatched and I got the tracking details of the card as well.  The card was being dispatched from Delhi.
  • To my surprise, I found that the card was going to Ahmedabad!  
  • From Delhi why would the card go to Ahmedabad when I stay in Pune?
  • I called up the call centre to find out whats going on.  The lady said that, "from Ahmedabad it will come to Pune, don't worry".
  • To my horror when I tracked the card again (after a couple of days) it said it was delivered to someone in Ahmedabad!
  • I immediately called the call centre and they said its delivered to some ICICI Branch at Ahmedabad.  The lady said that she is marking an email and ensuring that the card gets delivered to my Pune address from Ahmedabad.
  • I was like WTF is going on!  
Goof-up 3
  • After a few days I realised that they have send the card from Ahmedabad to my old communication address @ Ankleshwar via Speed Post.
  • Obviously, I don't stay there right now, so I called the callcenter and told them about this error and asked them to recall the card immediately.
  • The lady again assured that the card won't be delivered since you are not staying at that place and will come back to one of the ICICI Bank branch.
  • This was getting tricker by the minute.  
  • After a few days another Surprise, the card was delivered to my old communication address to someone without even checking for ID Proof.
  • Wait wait there is more, even the debit card pin got delivered to the same place.
  • I was lucky that it was collected by my old neighbour but it could have very easily landed into hands of any un-trust worthy person.
  • By this time I was fed up with them and I decided to write to them about the whole episode and here is their response:
We inform you that as you are in non receipt of the debit card, you may call customer care and block the debit card through IVR and place the request for reissue of the debit card to be delivered to any of your nearest ICICI bank branch so that it gets delivered in 05 working days and you may collect it from the branch.
  •  They tell me to block the debit card number which was not delivered to me - Then how the hell would I know the number @#$@#$
  • They also asked to request a replacement debit card all over again!! - Its like, I have nothing else to do in life but to play Debit Card, Debit Card with ICICI Bank.
I fail to understand how such a big bank which is supposed to have state of the art software and facilities can operate like a bank from 1980's?

PS: All events mentioned in this post are completely real and I would recommend everyone dealing with ICICI Bank to be extremely careful with your account and its security.

Friday, July 29, 2016

Monster Math - Journey to the Android launch!

Its been a thrilling roller coster ride for all of us at Makkajai.  I remember the days when we were building our first game Monster Math Classic on iOS,

  • We had no clue of how to develop a game?
  • How to market it?
  • How to get customers etc.  
All we knew was that, we had an idea and a lot of determination to execute it :D

In November 2014 we launched Monster Math Classic our first game on iOS.  Even though this was our very first game, we still managed to get lot of love from parents, teachers and students.  They had very kind words to say about our game.  Not just that, they also gave us some very awesome feedback, which could take user engagement to the next level.  We heard our customers and we incorporated their feedback which made them even more happier.

Somewhere in October 2015 we launched two new games Monster Math and Monster Math Multiplayer which got an even better acceptance than Monster Math Classic.  All these were still iOS only games.

One question which kept on coming from our customers was: When is it getting launched on Android!

It was not as if we didn't want to launch on Android.  We wanted to, but since our game was using Cocos2d (A game engine only for iOS), we couldn't do it just by a flip of a switch.

Somewhere in March 2016, we decided we need to launch our game on all major platforms, so that more and more kids can take advantage of our solution.  We started the effort on porting Monster Math solution to Cocos2dx.

When I first started to port, it felt like a never ending task.  We had around 50K+ line of Objective C code to be ported to C++.  Just the though of doing this humongous task -- that too all alone -- gave me nightmares :D.

There were many many problems to solve before we could could even compile an APK.  But as our dear friend Mark Watney (The Martian) says:

At some point, everything's gonna go south on you... everything's going to go south and you're going to say, this is it. This is how I end. Now you can either accept that, or you can get to work. That's all it is. You just begin. You do the math. You solve one problem... and you solve the next one... and then the next. And If you solve enough problems, you get to come home!

So thats exactly what we did, we started solving one problem at a time.  First problem was how can we quickly port Objective C code to C++ with minimal effort?

Instead of manually re-writing 50K+ line of Objective C code to C++, I wrote a quick and ugly Objective C to C++ translator.  It reads and parses any Objective C file and translates code into C++.  Simple right?  This translator does not generate compilable C++ code (because that would be difficult and time consuming).  It only get 90-95% of the job done!

This one step alone saved us few months of mundane work :D

  • After the initial translation was done, I manually fixed the compilation errors.  
  • Replaced Core Data/Realm with SQLite.
  • Added memory management code, since there is no ARC to cover us.
  • Replaced various SDK's with cross-platform equivalent.
  • Where a cross-platform equivalent SDK was not available, we used platform specific code to integrate native SDK's.
After solving innumerable such small problems, on July 14 2016 (after around 4 months of starting the project) we launched Monster Math on Android!

I am very grateful to have gotten this opportunity, I learned (and unlearned :P) so many things in such a short duration.  I am super excited (and proud at the same time) to have achieved this feat.

Finally, I hope Monster Math on Android gets even more love from its users.  Keep Calm and Have Fun!

Thursday, June 30, 2016

How to enable Immsersive Full Screen mode on Android with Cocos2dx

We are executing a project to port our flagship solution Monster Math 2 from Cocos2d to Cocos2dx.  This would enable us to release the solution on variety of different platforms including Android and Windows Mobile.

During the port, I came across one simple yet interesting problem -- Need to make the game UI truly full screen.

A lot of the Android devices have software navigation buttons at the bottom of their screens.

Android System Navigation Buttons
They seem to occupy part of the screen and block some part of the game UI.  Needless to say this does not give a great experience to the end users.  A better experience would be to hide these buttons.  But hey, if they are hidden then how do users navigate to the home screen or different apps?

Ideal experience would be to hide System navigation buttons at all times, but have some gesture to bring them back for a short duration when user needs them.

Android 4.4 (API Level 19) natively supports this functionality using the flag "SYSTEM_UI_FLAG_IMMERSIVE_STICKY".  This mode is called the immersive full screen mode.  When immersive full-screen mode is enabled, game continues to receive all touch events.  The user can reveal the system bars with an inward swipe along the region where the system bars normally appear.  System bars will automatically hide again after a few moments.  Perfect isn't it!

Usually setting this flag is enough to achieve the desired functionality, however in certain edges cases we need to do some additional work.  For example if you have a text field which accepts user input, once the on screen keyboard is dismissed the system navigation bars seem to stick around and do not hide until you kill the app and open it again.

In this post we are going to see how exactly to handle all situations so that the immersive full screen mode will always stick around for the app.

How Do They Do It!

What we need to do is basically setup SystemUiVisibilityChangeListener and FocusChangeListener and hide the system status bars in the callbacks.

Here is the sample code on how to do it.
That's it.  Once you run this Activity you should see that the game launches into immersive full-screen mode and remains in that mode!
Have some Fun!