If you’ve followed along with my previous posts, you’ll know I have been playing around with React and React Native. I have experimented with a couple of apps to try out different component and libraries available within the React Native ecosystem. I have only published those applications to Expo and not to the Google Play. Well not until now, I published
Australian Tax Calculator android application built using React Native to the Google Play Store.
Australian Tax Calculator — Apps on Google Play
Calculate your estimated income tax for FY 2018–2019. All outcomes provided by this app are based on the information…
I have published the same
Australian Tax Calculator app back in 2013 (geez that’s 6 years ago). At the time, I was playing around to see how much money I could generate by putting ads in the application. Honestly, I had forgotten about it as the application was removed from the Play Store a few years back as I didn’t keep updating the app to be in line with the changing Play Store developer policies.
A bit of background
So you might ask, why would I redo the same application 6 years later. Let me give you a bit of background, a few weeks back my colleague was looking at integrating ads in his application which made me check how much money has been accumulated in my AdMob account till now. To my surprise, there was around $67 collected through ads. I was like cool, time to transfer it to my account but I couldn’t as Google has a threshold limit set to $100 before paying out.
Update: As of 07 March 2020, I have surpassed the minimum payment threshold to $102.63 🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉
I could have just left this as it was but I thought why just leave the money sitting there. Recently, I have started donating to ShareTheMeal, an initiative of the United Nations World Food Programme (WFP). The cool thing is $21 can feed a child for an entire month. I thought instead of leaving the money sitting in my account, why not get it up to $100, get the money and then donate it for a good cause. I made up my mind and started working on the app. I started working on the app using React Native and eventually published the app to the Google Play store.
I decided to make the app very simple with few screens as I wanted to get the app out as soon as possible. I started with a couple of screens to essentially ask the question to the user about their pay frequency and the salary.
Then, I added screens for providing superannuation rate and showing the results for the user’s income tax and superannuation amount at the end.
The screens are essentially made up of header text, an image, an input, and a navigation button to continue to the next screen. Below is a sample structure of the react screen.
Sample structure of the react screen
Once all the screens were done, I was thinking to add some sort of intro to the application which will be visible after the app has finished loading. I was on the lookout for npm package which can easily provide this functionality. I came across
react-native-app-intro-slider which provides easy-to-use and very configurable app introduction slider/swiper based on FlatList. Based on the package, I came up with three screens that tell users that they will need to enter their salary and superannuation and finally see their income tax.
After all the screens and underlying logic to calculate tax and super was done, I started working on integrating ads into the application using Google’s AdMob platform. Once again, doing a quick search online to add ads to react native application, I stumbled across
react-native-admob npm package. It provides a react-native module for Google AdMob GADBanner, DFPBanner, and GADInterstitial. The banner is implemented as a component while the interstitial has an imperative API. I decided to use the interstitial API to add an ad when the user lands on the first screen, the
freqency screen where the user can select the frequency of their pay and when the user lands on the last screen, the
results screen where the users can see their income tax result. I used React lifecycle method
componentDidMount to show the ads to the user.
Displaying an interstitial ad in componentDidMount React lifecycle method
Journey to Play Store
After updating the splash screen and creating a simple logo for the app and with some refactoring done, it was time for the app to go live. Expo can manage the build process and can generate the apk file. Expo can generate a signed apk by running
expo build:android -t apk or an Android App Bundle(AAB) by running
expo build:android -t app-bundle. Once I had the apk, it was time for me to upload it to the Google Play store to publish the app.
Navigating to the build monitor link, we can see all the build steps and the logs for different steps during the build process. This link is only accessible to the expo user which kicked off the build. This is pretty cool and the generated APK or AAB in uploaded to Amazon S3 bucket.
Creating an app listing
I sideloaded the application on my Android device and everything was working fine. It was time to create an app listing in the Google Play Store. I filled out the basic information required for the app, i.e. title and description, and added application screenshots.
Google Play Console has changed a lot over the years and has a lot of features now. There’s a release management option where releases for an alpha, beta and production environments can be created. Android vitals is also available which is a program designed to help developers understand and analyze Android app performance.
Australian Tax Calculator is as an Ad Supported app. This SERVICE is provided at no cost and is intended for use as is…
At the time of publishing, the apk size was ~28Mb. It seems high for an app with a few screens and images to be that big. Also, the app had unnecessary permission listed. As part of a new update, I wanted to get the size smaller and remove all unnecessary permissions. One of the recommendations in Play console was to upload an AAB.
One of the mistakes I initially did was, I did not look at Expo docs to see if an AAB can be generated. Instead, I ejected the expo app and was trying to generate the app bundle using Android Studio. I ran into a lot of issues after ejecting the react native app. The build would fail, and the dependencies would not resolve. To remove unnecessary permission, I removed them from
AndroidManifest.xml and tried linking it back to the react native app, that didn’t seem to work either. I eventually stumbled upon Expo docs and found that I can run a simple command
expo build:android -t app-bundle to generate an app bundle🤦♂.️ To remove additional permissions, I can set the permission property on the android config in
app.json file to [ ].
Setting an empty array on Android permissions property
After uploading the AAB, the size of the APK was down to ~9 MB. That’s a reduction of about 65% which is crazy. Not sure what magic Google does after providing an AAB, will need to do some reading on that. I was happy with the size and the app had only minimum permission listed.
At this point, I was pretty happy with the app and its implementation. 🙏🙏🙏
UI is broken in the simulator but when actually running on a physical device, the issue is no longer there
I was trying to get the styling right when running the app in the simulator, but when I ran it on a physical device, it wasn’t even an issue in the first place. 🤦♂️
Keyboard hiding the input textbox
Since my text input is around halfway down the screen, whenever the input received focus, the keyboard would just hide the input, making it difficult to see what was being entered. To overcome this, I used an npm package,
react-native-keyboard-aware-scroll-view that handles keyboard appearance and automatically scrolls to focused
I had to fiddle a lot around getting the styles right across iOS and Android
I was making sure the app UI looks fine on Android as well as on iOS since I am building a cross-platform application. I had to come up with different styles for the two platforms to achieve a similar look and feel on the native platform.
Pressing the navigation button did nothing in iOS
I wasn’t sure why but when I tested the application on iOS simulator, the navigation button worked fine, but when I ran on my mate’s iPhone using Expo, the button wasn’t working. I fixed the issue by wrapping my button in a
By default, Expo adds a lot of permissions
Looks like Expo adds a lot of permission which is not really required. As mentioned earlier, I eventually got around this by setting the permission property for Android to [ ].
The font size on different screen rendered differently.
The font size does not scale properly based on the screen resolution. Expo provides a way to get around this by using
PixelRatio which essentially gives access to the device pixel density. Instead of implementing a custom solution, I used an npm package
react-native-responsive-fontSize which provides responsive font size based on screen resolution in React Native.
Read the docs
I am still learning about React Native and Expo workflow. For my next app, I will look at the official docs provided in the SDK before jumping online trying to find answers on Stack Overflow. 😞
Simply uploading an APK to Play Console is not enough
Expo adds permission which can discourage the user from installing the app
The first time I uploaded the APK, a lot of unnecessary permissions were listed which can discourage the user from downloading the app in the first place. In a new update, I set the config in Expo so that only the permission that the app requires is added.
Expo can create standalone binaries for iOS and Android which can be submitted to the Apple App Store and Google Play Store. This is pretty cool as Expo does all the heavy lifting, from building an APK or AAB to generating a Keystore.
It was a fun experience to rebuild the app and I learned new things along the journey. So far, I have got 10+ downloads and generated $3.50 in ad revenue. Hopefully, this will go up so I can hit the $100 threshold in AdMob revenue. 🙏🙏🙏