Showing posts with label howto. Show all posts
Showing posts with label howto. Show all posts

Friday, September 24, 2021

Practical Guide To Waking Up At 0500 Everyday

There is a sense of calm early in the morning. Everything is silent, there is no hustle bustle of daily routine. It's the time of the day when you can get a lot more done in a very short period. 

I can do a shitty job at describing what it feels like. But to really understand what I mean, you have to experience it yourself. 

Almost a year ago, I start listening to the book "The 5AM Club" on Audible, it was just like other self help books that try to teach you one thing. I used to listen to book and not really read them. I always wanted to read books regularly but in my messy schedule, I never got around doing it consistently. 

Listening to "The 5AM Club" changed it for me - I am very grateful for its advise. I have been reading consistently since about a year now. On an average, I read around 2.5 books in a month. That's an exponential improvement over 0!

What Changed?

I think you must have guessed it by now, I decided to try out the advise mentioned in the book. The book talks about getting up at 5AM at least 5 days a week so I started waking up at 5AM all weekdays. 

It was super hard to do it initially but then slowly but steadily it started getting better. This post is an attempt to document what worked for me in the hope that in someways it can help you make the transition to "The 5AM Club".

First Thing - Read The Book

There is no shortcut to this, you must start by reading/listening to "The 5AM Club". I am not getting incentivised in anyway to say this, I do like the book very much. It's a quick and easy read, you will feel like you are reading a story. At times it does get repetitive (just like any other self help book) but you could easily skim through those parts. 

The Why?

Now you need to think a little bit and find answers to the following question
  • Why do you want to get up early? 
Our mind is a big trickster, if you do not have a strong reason to this question, you are at a huge disadvantage. When the time comes, the mind will come up with a million reasons why it such a bad idea to get up early. If you do not have a strong reason, you will lose the battle. Your fluffy soft bed will attract you like a magnet and you will go back to sleep. 

It has happened to me a million times, but once you have a strong reason to get up early, something changes in your mind. It sort of knows that you are determined to get up early and supports you in doing that. 

For e.g. When you have to catch that early morning flight, do you not get up early? Thats the thing, have a strong reason for getting up early. The reason could be anything like

  • I want to read 
  • I want to go for a walk
  • I want to get some calm, peaceful time for myself
  • ...
My reason was "I want to read and become a better version of myself".

The How?


Start Sleeping Early

People want to wake up early but they don't sleep early. As simple as it sounds, most people will fail at this point. 

Nobody is a Superman, don't try to stay up till midnight and then expect that you will wake up at 5AM. It might work for a day or two or even a week, but it's not sustainable as an habit. 

Getting up early doesn't mean we sacrifice on good sleep, it just means adjusting your sleep schedule a little to reap incredible benefits of rising early. 

Start slow, I started by adjusting my sleep schedule by just 15 minutes every week. This means, I was sleeping 15 minutes early every week and waking up 15 minutes earlier in the morning. I continued that for 2 months and voilĂ ! I was sleeping at 2200 and waking up at 0500.

Before you go to bed

You need to setup the environment so that it's ripe to sleep early and rise early. Here are somethings you could do

  • Set an alarm for when you want to wake up and keep it at a place where it's out of your reach. It should be placed in such a way that, to turn it off you would have to get up from the bed. It needs to be in the same room that you sleep but not reachable from your bed. There are two essential things here
    • You should be able to hear the alarm - so it needs to be close enough
    • You should not be able to stop it without getting up from the bed 
    • This simple trick does the difficult job of getting you out of the bed easily. 
  • To prime the environment further, think about why are you getting up?
    • If you plan to read the book, keep the book that you want to read next to the place where the alarm was kept
    • If you plan to walk, keep your shoes next to the clock
    • You get the point right?
    • This will motivate you further to actually quit the laziness and work towards achieving your goals. 
  • Stop staring at screens 60 minutes before you plan to sleep. This includes no mobiles, TV, iPad or laptop. 
  • Before you sleep, remind yourself about why are you doing this? Remember "The Why?" thats driving this whole thing. It needs to be a strong force, something that you always wanted to do.
After you wake up 

The brain will make excuses and it will tell you to go back to bed and sleep for another 5 or 10 minutes. It's a trap, don't fall for it, remember "The Why?" and get out of bed.

Knowing what you are going to do after you get up, helps a ton! Follow a schedule, it helps getting into some sort of rhythm. Here's my rhythm:
  • 0500-0530: Getting fresh
  • 0530-0600: Meditate 
  • 0600-0700: Reading 
  • 0700-0745: Any form of exercise i.e. run, walk, jog, skip, yoga etc. 
  • 0745-0800: Breathing exercises with family (started after the COVID19 hit us)
  • 0800-0830: Shower and getting ready
  • 0830-0900: Breakfast
  • 0930 onwards: The work day begins!
I am not like the Subodh from Dil Chahta Hai, I do not follow the schedule to the minute. But jotting down what you are going to do when, improves the chances of that thing getting done. 

Your rhythm doesn't need to follow mine, experiment a little and do what works for you. By the time it's 0930 so many important things get done and I start my day with a feeling of content!

One specific problem that I struggled with a lot was, feeling very sleepy especially while Meditating or Reading. I tried a few things but the thing that worked the best was to follow this advice 

Keep Calm And Drink Coffee

I usually make a cup of hot black coffee and sip it while reading. It makes me feel super fresh and my brain feels sharp, fully ready to absorb all the new ideas!

Final Thoughts

I am not going to sugar coat the reality, getting up early consistently is hard - at least for me. Doing this consistently needs a lot of discipline. 

There are days when my body doesn't feel like getting out of bed and I don't. I do fall off the wagon and the rhythm breaks but keeping the focus on "The Why?" helps me get back and continue doing it. 

I hope this memoir helps you in some way, if it does or doesn't or if you have a better way of doing it, please do let me know!

Sunday, August 30, 2020

Invoking AppStore Connect API via Command Line

Sometime back Apple had opened up the AppStore Connect API for its developers. The API is a bunch of RESTful service which can be used to customise and automate our workflows. It helps us automate tasks across developer tools, such as App Store Connect, Xcode, and Certificates, Identifiers & Profiles, to give us greater flexibility and increased efficiency in our workflows. We could use it for development, beta testing, managing app metadata, reporting etc.

It can be very helpful to invoke the AppStore Connect API via command line. I use it primarily to check the structure of the response object. Although the documentation of the AppStore Connect API is good, but there is nothing as good as seeing the response object with real values in it.

In this post we will see how can we invoke the AppStore Connect API from the command line.

How To Do It? 

To invoke the AppStore Connect API via command line we will follow these steps.

  • Create API Key from the App Store Connect Web Portal
  • Create JWT JSON Token for Accessing API using XCToken
  • Invoking the API from command line using curl.

Create API Key 

  • To generate an API Key you will need to login to iTunes Connect portal. 
  • Navigate to the "Users and Access" section


  • In there, navigate to the "Keys" tab
  • Choose the "Key Type" as "AppStore Connect API"
  • Make a note of the "Issuer Id" we will be using this later on to generate the JWT JSON Token.


  • Generate a New API Key, by clicking the "+" icon. This will open up a dialog which ask you to name the key and select the Access type. I am going to choose "Developer" for this post.


  • This will generate the API key, make a note of the generated Key Id we will be using it later to generated the JWT JSON Token.
  • iTunesConnect will give you an opportunity to download the generated key only once. So please make sure you download it and keep it safe.


  • This completes the steps necessary to generate an API Key.

Create JWT JSON Token

To Generate the JWT JSON Token we are going to use a command line utility called XCToken. It can generate on-demand JWT tokens forAppStore Connect API. To install the utility just run the following command.

gem install xctoken
To generate the JWT JSON Token this utility expects three environment variables.
  • ISSUER_ID = This is the issuer id which we have noted in the earlier step from the iTunes Connect page.
  • KEY_DIR = The full directory path where the API key was downloaded from iTunes Connect
  • KEY_ID = The key id of the newly generated API key.
Once these environment variables are set up the XCToken is ready to generate the JWT JSON Token. Here is the sample script that will generate the token.

export ISSUER_ID=ABCD
export KEY_DIR=~/Downloads/
export KEY_ID=ABCD1234
xctoken  generate
This will spit out the token on the console, make a note of this token, we will be using it to invoke the AppStore Connect API.

Invoking the API

Now that we have generated a new JWT JSON Token, we are ready to invoke the AppStore Connect API. Here you can find various endpoints and their documentation. For e.g. to get a list of all your apps, use the following command.

curl  https://api.appstoreconnect.apple.com/v1/apps --Header "Authorization: Bearer <GENERATED TOKEN>"
Thats about all we need to do to invoke the AppStore Connect API via command line!

Tuesday, March 31, 2020

How to access data of Redshift cluster from PostgreSQL RDS

We were using Amazon Redshift as our data warehouse. It is a columnar-oriented petabyte-scale,  OLAP database suitable for analytical queries and applications.

There were many times when we wanted to pull data from Amazon Redshift and power our dashboards. This is basically using an OLAP database for OLTP use case - it was obviously not going to work very well.

Amazon RDS provides a feature called DBLink. DBLink enables us to access Amazon Redshift table directly from Amazon RDS. We don't need to explicitly copy over the data from Redshift to RDS, DBLink handles it for us and moves the data at the block level.

In this post, we will review the steps needed to setup the DBLink on Amazon RDS. This post assumes that you already have a running Amazon Redshift cluster and an Amazon RDS PostgreSQL instance.

Setting up DBLink
  • First we need to enable the DBLink extensions on the PostgreSQL RDS instance.
  • Next step is the main step which creates the link to the Amazon Redshift cluster and PostgreSQL RDS instance.
  • To achieve this we need to create the server link and the user mapping
  • Please note that all the values that are enclosed within <angle brackets> need to be replaced with actual values from your environment.
  • You might have to use the private IP address of your Redshift cluster. It totally depends on your setup.
  • Now that the DBLink is created, its time to query the Redshift cluster from the PostgreSQL to check if everything is setup correctly
  • Everything enclosed within $REDSHIFT$ is the actual query that runs on Redshift and results are sent back to PostgreSQL.
  • To create the cache of the Redshift data, we need to create a materialised view. 
  • Query the view just like you query any other view.
  • To refresh the view, use the following code

Thats about it, these are the simple steps using which you can access data of Redshift cluster from PostgreSQL RDS instance.

Monday, December 31, 2018

How To Reorder cells in UICollectionView using Swift

While building out a feature, in one of our Apps, I was faced with a need to reorder the cells in UICollectionView using Swift.

I looked around and found many ways of doing it, some of them work and some of them didn't. Heres an implementation that we ended up using and which is working for sure.

The Solution

Here are the steps to get the reorder feature working using drag and drop

  • We need to implement the method collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool from the UICollectionViewDelegate protocol, to indicate that the cells in UICollectionView can be moved around.
  • Next, we need to implement the UILongPressGestureRecognizer for the UICollectionView so that we can better handle the long press gesture
  • We are adding the gesture recognizer to the UICollectionView and setting up the callback method to handleLongGesture(gesture: UILongPressGestureRecognizer)
  • In the callback method we are letting the UICollectionView know about the interactions. 
  • Most of the work is already done, only thing left is to handle what should happen when the items are moved around. This can be achieved by implementing the method collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) from the UICollectionViewDelegate.
Thats about all the code thats needed to achieve reordering of cells in UICollectionView using Swift!

Saturday, June 30, 2018

How to map PostgresSQL JSON column with Hibernate value type and Kotlin

At makkajai, there has been no dearth of challenging problems :). Recently we moved our analytics partner. I will not bore you with details on why we had to move, but what is significantly more interesting is how we executed the move. Some key requirements for the move where:

  • Migrate all the data collected by previous analytics partner i.e. around 40 Million events to the new partner.
  • Honour concurrency limits of old and new analytics partners. Because if we didn't honour them, they will stop responding for a period of 10 minutes (which would be costly 10 minutes)
  • Old analytics partner had a limit of 3 concurrent requests.
  • New analytics partner had a limit of sending 1000 events per second. 
  • Migration had to be reliable and fault tolerant. For e.g. we could run the migration multiple times during the migration window.
I am not going to go into details of how we solved the whole problem (may be some other time), in this blog I am going to focus on a very small part of the problem. 

The Problem

PostgresSQL JSON column type has great querying features, I wanted to use it to save parts of events JSON response received from our old analytics partner. For this to happen, I needed to map the PostgresSQL JSON column type to Hibernate value type. This blog post is to document the steps needed to achieve this using Kotlin.

The Solution


There are 4 steps involved to make things work.

  • Adding a custom PostgreSQL dialect to register the JSON column type with Kotlin String.
  • Registering the custom PostgreSQL dialect in application.properties.
  • Adding a custom user type class to map kotlin String to PostgreSQL JSON column.
  • Annotating the model classes, to use the custom user type class.
Here is the exact code needed to achieve all the 4 steps mentioned above

Above is the custom PostgresSQL Dialect to register the JSON column type with a Kotlin String.

Sample Application properties to register the custom dialect.

Above is the custom user type mapping class. This will be used to map Kotlin String to PostgreSQL JSON column.

Above is the simple UserEvent model class that uses the string property properties and maps it to the PostgreSQL JSON column data type.

Thats about it! When we create the instance of UserEvent class and set the value of properties it will be correctly saved in PostgreSQL JSON column type. PostgreSQL will also validate that its a valid JSON String before saving the information.

Tuesday, May 29, 2018

How To Print 1x1 Shipping label on a 2x2 A4 Generic Sticker Paper

When you are running a startup, you will face numerous business problems on a daily basis. Some problems are within your core competency and some fall outside your comfort zone. Being a startup founder, you really cant afford to not solve the problem because it falls outside your comfort zone. Also at times, you only need to be street smart to solve the problem and move on :)

I recently faced one such, not so interesting problem, but it was essential for me to solve it.

Background

We ship books to our customers in India and we recently moved to Delhivery as our delivery partner. Have you noticed the stickers on the packaging, when you receive deliveries from Amazon/Flipkart/Delhivery etc? Those stickers are called Shipping Label. It has bunch of information like:

  • Who is the package for.
  • Where is it coming from
  • Contact details of the client 
  • Contents of the package and its approximate value
  • And many other things.
This is how a Shipping Label looks:

When we create the shipment in Delhivery portal, they generate the shipping label for us. Shippers are supposed to print it and affix it on the shipment. So far it feels normal and business as usual, what's the problem is not clear?

The Problem

We usually we ship in bulk, hence we ship to hundreds of our customers in one batch. Delhivery generates a PDF with 1 shipping label on every page, hence if we are shipping 100 shipments, Delhivery will generate the PDF with 100 pages i.e. 1 label on each page in a 1x1 format.

If we had access to a specialised printer which could print these stickers on a sticker roll, that we would be sorted. But unfortunately we didn't have that printer.

There are generic sticker papers available in the market to print shipping labels. However each A4 size generic sticker paper would cost around Rs. 5. Its not optimal from cost as well as resources perspective to print just one sticker on the entire A4 page.

Considering the size of the Shipping Label, we could easily print 4 shipping labels on one A4 size paper. If we were able to do it, the cost of printing one label will drop 4 folds. Something like this


Initially you might think, why is saving few bucks so important. Thats because of a simple concept called unit economics. If you ever want to get your startup in the successful zone, you need to get the unit economics right :D!

The Solution

Now that we know whats the problem and why we need to solve it, lets focus on how did I get it done.

Speed of execution is everything in startup world. I had to solve this in way that its easily doable by any non-tech operations guy, at the same time I didn't have the luxury to build a sophisticated custom solution. 

So, what did I do? I tried to breakdown the problem into smaller steps and try to solve each of those smaller steps.

  • First thing I observed in the Shipping Label's PDF was that, There was some extra information around the shipping labels like the footer of the page and some more unimportant stuff. 
  • In order to arrange it in 2x2 format I need to trim the unimportant stuff. For this I looked for a site that could help me trim all the PDF pages in one go. Sejda was perfect for this. The free plan has some restrictions but we could live with those.
  • You could upload the PDF and you could crop all pages with a mask in one go. What I got after that was a PDF with all pages having only the important stuff.
  • Next, I need to export each page as a separate image either in PNG or JPEG format. This was necessary so that I could use mail merge to actually arrange the shipping labels in 2x2 format.
  • I exported the PDF pages to png using pdf2png site. The result was a zip file with all the PDF pages exported as PNG files.
  • Final step was to use "Microsoft Word Mail Merge" to arrange these images in 2x2 grid. I followed the this nice article, to get that done.
  • Once I followed the steps, I finally got a 2x2 grid of all my shipping labels. These could be printed on a generic A4 paper with a 2x2 sticker grid.
  • In the end, I had a very low tech solution (which could be easily followed by any Operations guy) to a business problem.
The entire solution is in line with the theory suggested by Mark Watney, from The Martian :)
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!


VoilĂ , my job here was done!

Friday, April 27, 2018

How to get Snowplow-Mini running on AWS

While looking at various Analytics engines we came across Snowplow Analytics. We wanted to give it a shot and experience it first hand. Luckily, they have something called as Snowplow-Mini. Its an easily deployable, single instance version of Snowplow. It essentially gives us, a taste of what Snowplow can do for us, as far as data collection, processing and analytics is concerned!

We started with the quick start guide and usage guide, performed all the steps mentioned there to get the Snowplow-Mini instance working. However, we did faced two annoying issues, investigating and fixing them, wasted a few hrs. This post is about those two issues, so that my fellow developers do not have to waste any time on investigating and fixing them.

Unable to: Generate a pair of read/write API keys for the local Iglu schema registry

We followed all steps mentioned in the usage guide but we were unable to generate the keys.
  • Navigate to http://<public dns>/iglu-server
  • Input the super API key set up in previous step, in the input box in the top right corner
  • Expanded the keygen section
  • Expanded the POST /api/auth/keygen operation
  • Input the appropriate vendor_prefix for this API key
  • Click Try it out!
At this, it should have generated the read and write keys for us. But all it did instead was, showed a progress bar and runs forever without return.

Investigating it in Chrome Developer Console revealed that the calls were failing with 401 UnAuthorized. After googling for this error a bit, I found that someone else was also facing a similar problem. Their solution was to do HTTP POST via CURL and that seemed to work. However it didn't work for us either.

I looked around for ways to debug the problem.
  • I connected to the Showplow-Mini instance via SSH (refer to AWS documentation on how to do this)
  • Checked the config under "snowplow" directory on the instance. Could not spot anything unusual there -- not that I knew much about it anyways :D
  • Checked the logs under "/var/logs" directory. Found a few things but could not really solve the problem.
  • Connected to PostgreSQL DB on the instance using the following command
    • psql --host=localhost --port=5432 --username=snowplow --dbname=iglu
      # Password is "snowplow"
  • Ran the query to check the API key
    • select * from apikeys;
  • What I saw next, made my jaw drop, in disbelief!
  • They API key is case-sensitive and the key Snowplow-Mini had saved was all in lowercase, even though when I had given it the key, I had given it in all caps.
  • Passing the key in small case and making the following call did result in generating the read/write API keys for local iglu schema registry
    • curl http://<IP address of your server>/api/auth/keygen -X POST -H "apikey: <your case sensitive API key>" -d "vendor_prefix=com.makkajai"
  • Duh! Yea I know.

  • How to connect to PostgreSQL Snowplow-Mini DB, I got to know that from here 
I must have easily wasted an hour trying to fix this problem. I hope others can save that time!

Unable to: See events in Kibana Dashboard

This was a tricky one. After raising sample events, I was unable to see them in Kibana Dashboard. This happens mainly because the "snowplow_stream_enrich" is not able to connect to the "elastic search service".

How Did I figure it out?
  • ssh into the Snowplow-Mini instance
  • I checked the logs under "/var/logs" directory. 
  • The logs seemed to be filled with exceptions like
    • Exception in thread “main” java.net.UnknownHostException: ip-xx-xx-xx-xx: ip-xx-xx-xx-xx: unknown
  • Googled it a bit, found the solution here 
  • Edit the file "/etc/hosts" and add the IP address information in that file as follows.
    • sudo vim /etc/hosts 
    • xx.xx.xx.xx ip-xx-xx-xx-xx localhost
  • xx.xx.xx.xx being the AWS local IP address.
  • Save and exit and re-start all services from the Snowplow-Mini console.
  • Generate a few events and open Kibana dashboard, and it worked this time!
After these two problems were out of the way, my Snowplow-Mini instance was fully up and running on AWS!

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!

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!

Saturday, October 31, 2015

How to fix Cocos2.1 shader crash on iOS 9 - Part 2

In my previous post, I explained how to fix the open GL Shader related crash on iOS 9.  This crash was specifically occurring for apps using Cocos 2.1, the crash fix did work correctly on iOS8 and above.  But the fix had introduced another crash on iOS7 devices.  The crash report looked like this:

I investigated the issue for sometime and then I had my "duh!" moment.  The code that fixes the crash on iOS 9 used the method "containsString" of NSString class to find whether string A contains string B (on line no 18).

The method "containsString" was only introduced in iOS 8 hence, it was not available on devices running iOS 7 and below.  When the code tries to use that method it obviously crashes the app!

We changed the code to not use "containsString" and used "rangeOfString" instead.  This method was supported on iOS 7 as well.  The updated code looks like this:

Heres the fully updated code that works on all devices running iOS 7 and above.
Such a silly mistake this was!

Wednesday, September 30, 2015

How to fix Cocos2.1 shader crash on iOS 9

We have been using Cocos2D 2.1 for our game Monster Math.  Recently we decided to release an update to the game by compiling it against iOS 9.  To our surprise the game started crashing right at the launch with the following error.

A little investigation showed that it was crashing while creating OpenGL shaders.  A little googling proved that others were facing the same issue (more details here and here).

Whats the Fix - How Do They Do It! 

To fix the crash, I had to modify code in file CCGLProgram.m of Cocos2D and change the method compileShader as follows.

Once I made the change, the crash disappeared and it stared launching the game without any problems.

After this change we released an update of our game to AppStore.  We did however see a few crash reports around this very same issue from devices that were running iOS 7.

Will have to investigate further and fix it for iOS 7 devices as well.  Will keep you guys posted on what we did to fix it for iOS 7 devices, till then, have fun!

Monday, June 29, 2015

How To access multiple SQL Server databases without MS DTC

In one of my .NET projects, we had the following situation.
  • We wanted to access multiple SQL Server databases hosted on the same SQL Server instance 
  • These databases had to be accessed via EntityFramework (EF)
  • And from a single transaction.
Sounds simple enough?  

Only problem is, as soon as we use two or more connection objects in the same scope, the transaction is elevated to a distributed transaction (DT).  Such transactions are handled by Microsoft Distributed Transaction Coordinator (MS DTC).

All is well, if you really need DT.  But in our setup, we were sure that all these databases will be hosted on a single SQL Server instance.  I really wanted to avoid elevating the transaction to DT, obviously wanted to avoid the performance penalty.

I went looking for answers, on how to achieve this, after some searching and hacking, I was able to achieve this (here is the SO post that explains the solution).  So here's how its done!

How Do They Do It!

It turned out to be pretty simple in the end.  All that is needed is to make sure that we do not instantiate more than one DbConnection objects in one scope!  

Well, then the key question is, How do we use the same DbConnection object, to talk to two different EF contexts - which access two different databases?  

Let me explain this with an example:
  • Say that you need two EF context instances
  • EF1 connects to DB1 and EF2 connects to DB2.
  • Pseudo code that will elevate the transaction to DT looks like this
  • To avoid DT all we need to do is, avoid EF2 from creating its own connection, instead use the Connection instance created by EF1 in someway.
  • We can get hold of the DBConnection instance from EF1
  • Change the database using the ChangeDatabase method
  • And use this DBConnection instance to build the instance of EF2
  • Updated pseudo code looks like this

That's about it!  A simple cheap trick to avoid paying the performance penalty of MS DTC!

Saturday, February 28, 2015

How to automatically set DateTimeKind, while fetching Datetime properties from database

In one of the my projects, we were saving all DateTime properties after converting them into UTC timezone.  However while reading these values (using EntityFramework) the DateTimeKind was reset to DateTimeKind.Unspecified.

Needless to say that, this behavior causes a lot of problems when we want to convert these DateTime properties into different timezone values.  What we wanted was, an automatic way to set the DateTimeKind value of our DateTime properties to UTC.

I found an awesomely clean way to do this, without doing it manually for each and every DateTime property.

How Do They Do It!

To get the desired effect we need to follow these steps.

  • Create an Attribute that will have the responsibility to set the DateTimeKind value of all eligible DateTime properties of an entity (essentially, those DateTime properties that have this Attribute)
  • Apply this attribute on the desired DateTime properties of all entities.
  • Lastly, we need to hook up this attribute to the ObjectMaterialized event.  So that whenever an entity is materialized, the attribute can perform its job.
Three simple steps to get done, lets jump right into the code.

The code for this attribute is pretty self explanatory, basically
  • It just finds all properties of an entity of type DateTime or DateTime?
  • Loops over these properties to find whether they declare the Attribute
  • If yes, then set the value of the property along with the desired DateTimeKind value.
All we are doing here is to apply the attribute to a few properties of our EntityFramework entities.

Hooking up the Attribute with the ObjectMaterialized event of ObjectContext.

As mentioned earlier, its a simple and clean way to getting the DateTimeKind value set for all DateTime properties of EF entities.

That's all folks!

Credits: SO

Friday, October 31, 2014

How to get Apple Cover Flow effect in an iOS app

Recently, for our flagship app Monster Math, I was on a hunt to find a control that gives me the Apple Cover Flow like effect.  After evaluating a few options I ended up using the awesome iCarousel control.

Its extremely customisable, lightweight, has numerous hooks and many many predefined effects, its simply awesome!  In this post, we will see how easy it is to get the iCarousel integrated into our app.

How Do They Do It!

To get this control up and running follow these simple steps

Installation

The installation is stock standard, you can install it via Cocoapods.  Use the following line in your pod file

and then run

Usage
  • There are two protocols that need to be implemented for the iCarousel to work correctly.  iCarouselDataSource and iCarouselDelegate
  • The iCarouselDataSource protocol has two mandatory methods to be implemented 
    • (NSInteger)numberOfItemsInCarousel: This method returns the number of items in the carousel 
    • (UIView *)carousel:viewForItemAtIndex:reusingView: This method returns the view that needs to be shown in the carousel.
  • The iCarouselDelegate protocol has no mandatory methods but its good to implement the following method
    • (CGFloat)carousel:valueForOption:withDefault: This method can return values for different options which alter the display and behaviour of the carousel.
Thats about all the methods we will need to implement to get the cool Apple Cover Flow effect.  Lets jump into the code to see the details of implementation


In this snippet we are just initialising the iCarousel and setting the type of carousel to iCarouselTypeCoverFlow2, this type's behaviour closely mimics the App Cover Flow effect.

Next up are the protocol methods that we described earlier.

This snippet implements the two mandatory methods of iCarouselDataSource protocol.  For the view we are showing a simple image from our assets.  And we have total 4 items in our carousel.

The last and final method just customises two options of the iCarousel.  It basically wraps the view so that we get an infinite view sort of a feeling and adjusts the spacing between the views a bit.

With all the pieces in place lets fire it off and see how it looks!

An Infinite Cover Flow Effect

An Infinite Cover Flow Effect

Pretty impressive for such little code, won't you agree?  

That's all folks, until we meet again, Guten Tag!

Monday, September 29, 2014

How to map Fluently mapped NHibernate Entities To Stored Procedures ResultSet

In one of our .NET/NHibernate project, we wanted to move a time and resource consuming NHibernate generated query to a Stored Procedure.  Nothing else should change, the stored procedure should return the same result set as the query.

The motivation behind this move was to use some native techniques to tune/optimize the query for example compute some intermediate result set and put into a temporary table etc.

Now that the requirements are clear lets dive into the problem a bit more.  We were using Fluent NHibernate to map our entities and the problematic query was generated using NHibernate's criteria API using one of the Fluently mapped NHibernate Entity.  This object was a pretty big object with numerous associations to other NHibernate Entities.

I (being a lazy developer) was in no mood to map the result set of Stored Procedure all over again in an hbm.xml file.  Basically I was trying to do as little as possible to get the job done :).  What I had in mind was to directly map the result set of Stored Procedure to already mapped Fluent NHibernate Entities.

DISCLAIMER: Before I say anything else, let me make it very clear that its was not NHibernate that was generating an un-optimized query, our schema is a legacy schema and the query itself was pretty complex to begin with.  In all likelihood its a problem caused by us not using NHibernate correctly.

OK enough of context setting, let jump into code.

How Do They Do It!

Lets assume that we have two NHibernate entities called Department and Employee.  Department has a one-to-many relationship with Employee (i.e. A Department can have many Employees).  The mapping files of Employee and Department are stock standard, but just for sake of completeness showing them here

Now lets say we have a method that queries the departments by Name.  We want to move this query to a Stored Procedure.  The method and the generated query (for reference)


To move this NHibernate generated query to a Stored Procedure we need to do the following steps

  • Create a Stored Procedure that returns the exact same result set as the NHibernate generated query

  • Configure the stored procedure as a Named Query in hbm.xml file.  

  • Invoke the named query via NHibernate
That's about all the changes we need to map the result set of Stored Procedure to the Fluently mapped NHibernate entities.  As shown above all the lazy loading and other relationships work as before!

These simple steps got us what we wanted without some painful mapping jugglery.  As always, NHibernate just does not cease to amaze!

Thanks all folks!

Shameless Plug: we will be launching the best ever arithmetic app called "Math Monsters" very soon on the AppStore.  Checkout the details on our Website and like us on Facebook!

Thursday, July 31, 2014

How to generate strongly typed C# client for ASP.NET Web API

Recently, I was looking out for ways to consume the ASP.NET Web API via strongly typed C# client (i.e. a client similar to C# Web Service Client).

Initially I thought, Microsoft would have a utility to generate the client but, I was wrong, they don't have any such utility.  Why would they not provide such a utility is beyond me, I really don't understand why would they not expose such a utility, it would have benefited everyone who wants to consume Web API using strongly typed classes.

None the less, After a bit of googling, I found this awesome open-source project which does exactly what I needed.

The detailed instruction on how to use it can be found here.  In summary you need to do the following steps to generate the strongly typed C# client for ASP.NET Web API


How do they do it!

Setting up the Server
  • Install the NuGet package "WebApiProxy" into the project that hosts the Web API.  This package will host a proxy endpoint for your service.  This proxy endpoint can be used as the JavaScript client to invoke the Web API via JavaScript.  The endpoint will be hosted at URL "/api/proxies"
  • Once you have this installed in your Web API, if you browse the URL "/api/proxies" you should see a JavaScript client already generated!
  • This package also exposes the metadata necessary to automatically generate the C# client.
Creating the client
  • Create a Client project which will be used to invoke the Web API via C#.
  • Install the NuGet package "WebApiProxy.CSharp" into this project.  This package seamlessly integrates the proxy generation build task with the project build step.  
  • Every time you rebuild the project it will try and generate the C# client for the desired Web API.
  • The configuration required to generate the C# client is placed in a file called "WebApiProxy.config"
  • This is the simplest XML file I have ever seen.  It only expects you to provide the 
    • endpoint - The location of the Web API where it will be hosted.
    • namespace - The namespace in which the C# client will be generated.
  • That's about all the setup that is needed to generate the strongly typed C# client for a given Web API
Example
  • Imagine you have an EmployeeController on the Service side. 
  • We can invoke this Web API via our generated client as follows
  • As you can see its very straightforward and intuitive to invoke the Web API with strongly typed C# client.
Further Reading
  •  I went ahead and modified the source code to generate not just the Async method but also the Sync version of the Web API.  
  • This is done so that anyone who wants to invoke the Web API in a Sync manner does not have to deal with the Async behaviour.
  • The above code for Sync invocation can be reduced to the following
  • Updated source can be found here
  • TIP: In case if you are trying to modify the source to suite your needs, make sure that you kill the MSBuild process before you rebuild the Task and the Client.
Thats all folks!  

Monday, June 30, 2014

How to run Entity Framework Migrations using MSBuild and Migrate.exe

Recently, one of out client moved to Entity Framework.  Along with that, they also decided to use the Entity Framework Migrations.

On a DEV machine, Entity Framework Migrations can be executed very easily using the the Update-Database command in Package Manager Console.

Naturally, we do have a Continuous Integration (CI) server that builds and integrates the checked-in code.  We needed to run the migrations on the CI server as well.  For building our project we were using MSBuild.  I wanted to integrate Entity Framework Migrations with MSBuild so that the migrations can be executed outside the Visual Studio and on the CI server as well.

Looked like a no brainier task to me, I hoped that there will be an MSBuild task that would run the Entity Framework Migrations and my job would be done!  But to my surprise, Entity Framework Migrations is not fully thought through, it does not come with any task for MSBuild which can be executed out of the box.

Turns out that there is a Migrate.exe that could be used to execute the migrations.  This could then be invoked from MSBuild to get the job done.  So how do they do it, how to run Entity Framework Migrations using MSBuild and Migrate.exe

How do they do it!
  • Migrate.exe can be found under the tools directory of the Entity Framework package that comes along with NuGet.
  • We could create a simple task that can invoke migrate.exe using the Exec MSBuild task. 
  • However, simply running the above task will not get your the desired results.  When you run this task you might end up getting some weird exception.  I got the following exception
  • Turns out that to successfully run Migrate.exe, it needs to be copied to the directory where the DLL holding all the Entity Framework Migrations is located.
  • I don't understand why such a restriction is necessary.  Why could they not use the StartUpDirectory parameter or some other parameter to accept the full directory path of the DLL that has the migrations.  May be when someone wrote the code for Migrate.exe, he/she found it convenient to run it this way!
  • Anyways, so the fix to this problem was simple, first copy the Migrate.exe to the folder where the DLL is located and then run the Migrate.exe
  • Updated target code looks as follows.
As you can see, its not very straightforward to get the Entity Framework Migrations integrated with MSBuild, but with some hacks, we can get it working! 

Have some Fun!