This is a story of hindsight being 20/20. I have been a full-stack web developer for something like 16 years now. After developing for that long, I know what I need to build a web application from top to bottom using different technologies. 

But in my latest job, I became an Android developer for the first time and have been for the last couple of years. It took a while to realize that Android development and mobile application development require a slightly different thinking process than web development. 

Some issues created by being a beginning Android developer can be fixed later through simple refactoring, modifying your build process, or grinding until you get the unit test coverage you want. But certain missteps, some of which I'm not happy to say I've made, can seemingly linger around for the life of the app and have you wishing you'd done things differently from the start. Here are a few tips that will prevent temporal paradoxes – well maybe not that – but prevent the kind of problems that are hard to get rid of.

Add in-app update

Just add this now. An update notification feature was not added to our app until after it had existed for at least a year. This created multiple issues, including the next two in this list. It is now relatively simple to add it to your app. Before you had to roll your own custom process and users could find a way around it. This new built-in way to do it only takes a little code.

// Creates instance of the manager.
val appUpdateManager = AppUpdateManagerFactory.create(context)

// Returns an intent object that you use to check for an update.
val appUpdateInfoTask = appUpdateManager.appUpdateInfo

// Checks that the platform will allow the specified type of update.
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
    if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
        // For a flexible update, use AppUpdateType.FLEXIBLE
        && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
    ) {
        // Request the update.
        appUpdateManager.startUpdateFlowForResult(
        // Pass the intent that is returned by 'getAppUpdateInfo()'.
        appUpdateInfo,
        // Or 'AppUpdateType.FLEXIBLE' for flexible updates.
        AppUpdateType.IMMEDIATE,
        // The current activity making the update request.
        this,
        // Include a request code to later monitor this update request.
        MY_REQUEST_CODE)
        }
}

You will make breaking changes to your app. Plan on that. Existing users of your app may already expect an in-app update through other apps they have and think it is just a feature of the mobile platform. In fact, until I became an Android developer, I did. So when your app stops working, they may not look for an update and just uninstall it, or worse, leave a review.

Restrict API keys

I know you just want to get things working and then you will get back to it. Do it now. This is a story specifically about the Google Cloud Platform, but I'm sure this lesson can be applied elsewhere.

For GCP, you just have to log in and go to the API key in question and in the edit screen and choose Android apps under Application restrictions. Then click ADD AN ITEM. There you will have to add the package name of the app you will be restricting the key to. To get the certificate fingerprint for the other field in the form, you can copy the command and follow the instructions on the right side of the page. It takes a few minutes.

We restricted our keys when our app was two years old. Afterward, one of our maps didn't work. We rolled the change back, and it took a while to figure out the problem. It turns out that the official Google package we used in most places in the app handled the change with no problem, but we had to write custom code for one map that didn't account for the possibility of restricted keys, which require a different API call. If we had restricted the API keys from day one, it might have added time to development, but the story would have ended there.

But it didn't end there. In order to restrict the API keys and not break that one map, we had to force an update. We had stats we could watch as users went through the update process. But it took weeks for the 90% of users who could get an update notice to get the version with the fixed map. There were still 10% of users that had to have a majorly broken version of the app and used it, but I am not sure how.

Version in-house APIs

When I was primarily a web developer, I was never quite sure why someone would want to do this. After I updated the front-end code, why would I need an old version of the API around? It seemed like overkill.

But when users may have different versions of the app, a major change to your APIs can break the app for a large portion of them. In-app update will help mitigate this issue, but this process is never as quick as you think. Versioning APIs now seems more like a very simple way to prevent broken apps than the over-engineering I once thought it was.

Use offline first

Our app is meant to be used in the field. When we got reviews about it being unresponsive and timing out, I was so clueless about mobile development that I discovered a new term, offline first. If our users didn't have a connection, anything they tried to save was lost and they would have to re-enter everything once they re-connected.

Offline first architecture will write changes to a local database before syncing that with the web connection. This not only allows users with no connection to use your app but also makes the app more responsive when it does have a connection because it doesn't have to wait for a response from a remote server to go to the next task.

OfflineFirst

This can be harder to implement later than in the beginning, depending on the complexity of your data. So decide if your app needs it now. We are still working out how to best do this with our years-old app...

Choose navigation wisely

If your Android app is complex with a lot of views, changing navigation late in development may be harder than it would seem. We switched to bottom navigation late in our app's life.

For some background, activities in Android can be thought of as the code for a screen in your app. Fragments were added later to Android, and you can think of them as the code for sub-views or partials in the app. Both of these will have a layout defined in XML.

We started with navigation that consisted of a dashboard of cards that linked to the main activities in each section of the app. These then launched more activities for a total of over 30 activities. There were only about four fragments in our app. Our app was designed based on activities. Drawer navigation is another common type of navigation that is designed for activity-to-activity navigation.

Bottom navigation is designed for fragment navigation because the bottom bar is always visible. If the bottom bar is added to an activity, you only have to add the code for it to that activity and its view to that activity's layout. Then you load a fragment into the activity when a button on the bar is clicked.

So to add a bottom navigation bar to our app, I tried converting the activities to fragments. It took a month. It was full of bugs that caused the app to crash, and it was a waste of time. With five or six activities, I may have tried to fix the bugs, but not with 30. 

So I threw that work away and spent a month adding functionality for the navigation to every activity. I did create a helper class, but there was still code that had to be added to each activity. The bar also had to be added to each layout, and space had to be made for it. I also had to manipulate the activity stack programmatically to prevent race conditions. It was not fun, but in the end, it worked pretty well. It just would have been easier to start with it and a fragment-based design.

This is not a complete list

Of course, there are all the common things you should do before beginning your first Android application, like adding unit tests and picking some sort of pattern for your app and sticking to it, but if you have been exposed to any other type of development, you should just know these type of things. You may not run into issues exactly like mine, but I know you will run into a few that are similar. Hopefully, these tips help you remember Android development is slightly different and some development decisions you make will stick around for longer than you think.

Discussion

Categories
Share Article

Continue Reading