Showing posts with label debug. Show all posts
Showing posts with label debug. Show all posts

Wednesday, February 27, 2019

How To Pass User Defined Properties To Android APK

We were looking around for ways to pass additional information to our Android app at run time. Main intent behind this was, to effectively test certain flow in the app - one such example would be the In-App Purchase flow.

One way of achieving this is by setting properties via ADB and reading their values from within the app via code. This post is about documenting the steps needed to achieve this.

There are two main parts to the solution
  • Setting the properties via ADB on the command line
  • Reading the property value from within the app via code and using its value to alter the app behaviour.

Without further ado, let's look at the actual code needed to achieve both parts.


The Solution

Setting the properties via ADB is pretty straightforward and we can easily do it with one line of code as follows


Here we are setting the property "log.tag.GITIAP" to value "DEBUG"

Reading the property value from within the app via code, needs a little bit of work. Here is the full code that will let you read the property "log.tag.GITIAP".


That should do it! When you call the method "PropertyHelper.initializeProperty()" it will set the value of "gitIAPValue" to the value that was passed via ADB.


Tuesday, October 30, 2018

How to debug a web page on iOS - Part 2

In this post we will continue our pursuit to debug a web page on iOS. Wont it be nice, if we had Chrome Developer Tools kind of interface even for the iOS?

The second way to investigate webpage errors on iOS is going to achieve exactly that, but using Safari!

The Solution

Apple natively supports remote debugging of webpages on  iOS since iOS6. Here are the steps that are necessary to enabled it.
  • Open Settings app on iOS device
  • Click on Safari

  • Here, click on Advanced

  • Next, enable the Web Inspector switch.
  • Now, head over to your Mac and open Safari.
  • Click on Safari --> Preferences

  • Click on Advanced tab and enable Show Develop menu in menu bar 

  • This will Show a new menu item called Develop right next to the Window menu item.
  • Now, Connect your iOS device with the Mac using a cable.
  • Next, Open the Safari browser on the iOS device and open the webpage that you want to investigate.
  • Click on Develop and you should see your iOS device listed there.
  • Clicking on your iOS device name under the Develop menu, should show up all the web pages opened on the iOS safari browser.

  • Click on the webpage that you want to debug, this opens up the Safari Web Inspector 
  • Here, you can select elements, manipulate CSS, investigate console errors, look at all the network calls, profile your app and more. 
  • Notice when we inspect a div in the Web Inspector, it automatically gets highlighted on the iOS device



    Nice isn't it?

    Sunday, September 30, 2018

    How to debug a web page on iOS - Part 1

    One of our customer, recently wrote an email to our support team about a problem they were facing. They were not able to view the "Printables" section of Monster Math Games. This section shows list of free and paid Printable activities. This page is designed as a web page instead of a native screen and loads in a web view on the app. The customer was only getting a blank white page.

    I started investigating the issue, initially I thought it might be some sort of network latency issue or  something related to HTTP vs HTTPS. But it turned out, the problem was with one of Javascript API we were using.

    The Problem

    Debugging a web page on iOS device, is not as straightforward as I had initially thought. I learned two very interesting ways of debugging webpage errors on iOS. This post is an attempt at documenting these two approaches so that it could help someone who is facing a similar problem.

    The Solution

    The first thing I wanted to check was the actual source code of the web page. Here are the steps we need to follow to view HTML source of a web page.

    • Open this post on the iOS safari browser
    • Click the upload icon button on the menu bar, then click the "Add Bookmark" button.
    • Change the Title field to "View Source" and hit "Save"
    • Next we need to edit this bookmark and change the Address field to the following javascript code. Copy all the text from the following gist.

    • It needs to be done this way because, iOS Safari doesn't let us edit the Address field while creating the bookmark.
    • Click on the "Book Icon" in the menu bar to bring up your bookmarks. 
    • Click on "Favorites", you should see the newly created book mark "View Source".
    • Click the "Edit" and then tap on "View Source" bookmark.

    • Now select the Address field and paste the copied code.
    • Hit the "Done" to save the bookmark.
    • Visit the web page whose HTML source you want to view.
    • Once the page opens, click the newly created bookmark "View Source". 
    • This will open up a popup with details of the web page

    • This Popup has a "View Source" tab that shows the HTML source of the web page.

    Pretty cool, huh!

    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, December 31, 2011

    NHibernate throws InvalidCastException in DEBUG mode for entities with composite keys

    Recently we faced a very weird issue with NHibernate.  The issue was, on one developer's machine, when we ran an Integration test to fetch an entity (using its primary key), NHibernate threw an InvalidCastException exception.
    The issue was *not* reproducible on any other developer's machine.  This got me thinking, there must be some issue with the mappings which is causing NHibernate to throw the exception.  The developer must have made some local changes to the mapping files, that is causing the exception.

    Investigation:

    I tried various things to figure out what was causing the problem.  Here is the list of things that I tried.

    Check mapping files for modifications:

    I checked and rechecked the mapping files for any local modifications, but, No, there was no local modification.  I even checked-out all the mapping files just to be sure that there was no modification.  But still no luck, the issue was reproducible on her machine and not on any other machine.

    Tried to reproduce the issue on my machine by connecting to other developers Database:

    After the first failed attempt, next thought that crossed my mind was, may be, there was something wrong with entity data which is causing the exception.  I decided to run the same test on my machine by connecting to other developers database.

    Surprisingly, I was still not able to reproduce the issue.  This was totally weird.  I was 99% positive that, issue would get reproduced once I connect to the order developers database.

    I was running out of options.  How do proceed further?  What should be the next step?

    Stick to basics - Debug with Elimination:

    I was back to the drawing board.  Decided to use Elimination to narrow down the issue. The question that was bothering me was, Whats so special about the entity we are trying to load?

    The entity we were trying to load was called EmpDept, it represents the Employee Department information (actual names of the entities have been changed).  So what was so special about this table?

    This table was a legacy table, it did not have a primitive primary key, it had a composite key made of UserID and DeptID.

    So what?  A lot of legacy databases have composite keys, NHibernate works well when it comes to mapping the composite keys, in fact, NHibernate has no problems loading the same entity on my machine!

    I decided to, removed all other mapped properties and just kept the mappings for the composite key and try to fetch the entity.  This time, it did fetch the entity without any problems on the other developers machine!

    We were starting to get somewhere now!

    I started adding back the mappings to find out which one was causing the issue.  Finally, we did find the minimal possible mapping that would reproduce the issue.

    The Cause:

    We deduced that, the issue occurs when the following conditions are satisfied
    • Entity is mapped with composite primary key
    • Entity has a one-to-many relationship with other entity 
    • The one-to-many relationship is not based on the composite primary key, instead its with property-ref 
    • And the data type of property-ref is different from the id property 
    Wow!  I know, those are too many conditions to be true at one time!

    Let's look at the minimal mapping file that reproduced the issue
    What do we have here?  We have a very simple mapping between two entities.
    • Entity EmpDept is mapped to a table called EmpDepts
    • EmpDept uses a composite primary key to class EmpDeptIdentifier
    • The composite primary key consists of UserID and DeptID
    • EmpDept entity as another property called Email
    • There is a one-to-many relationship between EmpDept and Task entity i.e. One EmpDept can have Many Tasks
    • Note that the relationship is not based on the composite primary key
    • The relationship is based on a non identifier property called Email
    • The data type of the Email property is string while the data type of the composite primary key is EmpDeptIdentifier 
    By now, it must be clear that all of the required conditions for NHibernate to throw an exception have been satisfied, because of this NHibernate throws the InvalidCastException.

    So far we had figured out, what conditions were required for NHibernate to throw the exception.  However the real mystery was, Why was the exception occurring only on one developers machine?  Why not on other developers machines?

    The Enlightenment:

    Our curiosity levels were at all time high!  We decided to debug the NHibernate code to figure out why was exact same code working perfectly fine on one machine and failing on other.

    After some intense NHibernate code debugging we found the NHibernate code that was throwing the exception.
    Notice the line that throws the InvalidCastException in the above code?  This is where the exception occurs. 

    The above method is called to build a string that will be used for logging.  We traced back the call to this method, it was getting called from the MessageHelper.InfoString method, which in-turn was getting called from the LoadContexts.LocateLoadingCollection method.

    We now knew the place from where the exception was thrown, but we still didn't know why it was thrown only on one machine. 

    Looking through the NHibernate code we realized that, the method MessageHelper.InfoString is only called if NHibernate is running with DEBUG log level.

    That ladies and gentlemen, was the "Aha Moment!" for us.  This was the missing piece of the puzzle.   The developer on whose machine the test was failing was running NHibernate at log level DEBUG, while I was running the test at log level INFO.  Because of this the method MessageHelper.InfoString was never invoked on my machine and thus no exception!

    We Googled a little and found that there is an official bug reported for this scenario.  

    Eventually it turned out that, what we initially though as a big issue was really a non issue, since NHibernate will not be configured in DEBUG mode 99% of the time (because it logs hell lot of information).  The issue we were facing is very unlikely in real systems.  Although it was not such a big issue after all, this experience taught us quite a few things about NHibernate!
    Have some Fun!