Lessons Learned: Unnamed Project 2016-05
May 28, 2016
An Unnamed Project
Last month my friends at Skyward Interactive requested my assistance with a project that needed a cross-platform mobile solution. The project, which will remain unnamed because the client is a start-up, is a prototype for a service and required phone, tablet and server development. The phone apps is for customers, the tablet app is for administrators and the server ties them all together.
For mobile development Skyward typically builds native iOS applications, but most of their iOS resources were tied up with other projects and since this project had a short deadline and budget they asked me if I could assemble the iOS and Android phone solution. Of course, I decided to use the Ionic Framework to create these prototypes.
The Risks
Of course, the risks were weighed before committing to a project like this as they should.
Working with Friends: When I say the folks at Skyward are my friends, I mean that. These are people who have seen me through some good and bad days. Who have lifted me up when I was down. Who have driven by to check on my house when I was out of town after I had a flash of anxiety during my flight and thought I'd left my front door open. These are good people who I didn't want to let down nor with whom I wanted conflict.
Not Knowing What We Don't Know: Working with a start-up is a risk category all in itself. I would have no direct interaction with the client and completely trusted Skyward to manage them, but I still had to ask these questions: Do they know what they want? Do they understand the developement process? Will they be active or passive during the project? Will they pay?
Apple Store & Google Play Submissions: One interesting point about this project was that the client wanted to place this prototype in the app stores instead of using a service like TestFlight as a way to test with actual customers. This is always a risk, as you never know how long it will take to get an application reviewed by Apple. Two days? Two weeks?
In past projects I've never submitted apps to the stores. Someone else had that responsibility. I've never submitted an application built using Ionic to the app stores. Skyward had never submitted an app to Google Play. So this is a potential point of failure.
These were the risks as I saw them, eyes wide open, going into the project. On the reward side, I'd have another app in the app stores, my first Ionic app in the app stores. It didn't hurt that since I'm seriously underemployed at this time I'd have billable work. So, off to the races.
And The Work Began
With wire frames in hand, I began to work laying out the application UI in earnest. I get excited sometimes. This time it cost me in frustration later in the project.
Lesson Learned: Haste Makes Waste -- Don't speed through your application layout. Make certain to take the time to make the UI easily updatable; every project gets a UI update or three. It happens. Plan on it and create HTML and CSS (in this case Sass) files you can maintain even for a prototype. Build it right the first time so the changes will be easy.
Cordova Plugins and Open Source Software
This is an observation, not a complaint: open source projects can get stale. For a group of projects like the Cordova plugins, this can be a dangerous thing. Just because the project was updated recently does not mean it very active. Just because a project hasn't had activity in a year doesn't mean the project isn't rock solid.
Lesson Learned: Get to Know Your OS Project Before Deciding to Use It -- Always review any currently open issues on the project's Github site before using any open source projects. It might save your life.
Lesson Learned: Be a Good OS Citizen -- If you find a problem with an open source project make sure you post an issue on the project's Github site, otherwise no one will ever know. If you find a work-around for any issues you encounter or issues already filed, post them as well so everyone else will know, too. If you know how to fix an issue, create a pull request. You may save someone else's life.
Local Notifications
This project required the use of Local Notifications mainly due to resistance of the time and expense of setting up Push Notifications. Push would have been the proper way, of course, but these are the cards we were dealt. Local Notifications shouldn't be all that tricky, but they can be depending on how you manage them, what kind of data you are given and create and the symptoms that occur when you're doing it wrong.
For instance, I was receiving specific times of events that reminders were to be created for. The times were given to me as a Unix timestamp. I needed to create a Date object from the timestamp, subtract an hour from that Date object then convert it to a timestamp that Local Notifications could use. That proved very tricky for me. Eventually I used Moment.js to wrangle the Date, time subtraction and creating of Local Notification timestamps and Moment.js was, as always, a joy.
Lesson Learned: Moment.js Is Your Friend -- If you are dealing with dates and time in your application, go ahead and add Moment.js. It is simple to use and worth the effort of being added.
Lesson Learned: Isolate New Features Before Implementation -- Before adding a feature like Local Notifications or Background Geolocation (as I will discuss later) to your project take the time to create prototype projects so you may master these features before adding them to your project. Test them on devices, too. The goal is to be able to ferret out any feature issues before mixing it with your application. You want to be able to avoid working on feature bugs and application bugs at the same time.
A lesson not learned? Notification and status bar icons on Android are not easy. And I still do not know how to make them work. Once I do, I will make a post.
UPDATE: 2016-05-30: Handle local notification icons on the Android platform by reading my post Setting Android Icons with Local Notifications.
Background Geolocation Plugin
Background Geolocation should also be easy. And, of course, everyone was very concerned about battery usage. Since we needed a cross-platform solution, but the normal solution requires a premium version purchase, which the project budget couldn't afford, unfortunately. As always, start-ups typically have shoestring budgets.
An alternative Cordova plugin for Background Geolocation was available and I decided to take a chance with it. It worked as advertised.
I did find one issue with this plugin for which I filed an issue: the 'ANDROID_DISTANCE_FILTER' setting was throwing an error, oddly enough, on the Android platform. Specifically on my Android Marshmallow phones. Changing the setting to an actual integer, in this case a 0, resolved the issue.
Lessons Learned: -- See above lessons of isolating a feature before implementing in a project, reviewing issues before committing to using a plugin and filing issues if you find them.
Lesson Learned: Background Geolocation Requires Movement -- In the app, we have a feature where the geolocation would automatically shut down after a period of time. I set the code up to check the time after each geolocation ping. During on-device testing I received a bug report stating the feature was not working. I asked "Did you move?" Yes, the geolocation doesn't usually ping if you don't move about 15 feet or so.
Apple Store Rejections
Here is where things went wrong. The first submission was rejected by Apple because "On launch and content download, your app stores 6.21MB on the user's iCloud, which does not comply with the iOS Data Storage Guidelines."
The project was using Local Storage, but only to hold two strings in an object. There was no content download. This rejection was a mystery to me and made me very frustrated. To make matters worse, there was no guidance from Apple or online that was helpful in this situation except for this: set a preference in the Cordova config.xml.
<preference name="BackupWebStorage" value="none" />
We did that and resubmitted. We were rejected again for the same exact reason.
Submitting a third time did the trick, but honestly this is still haunting me. What was causing this 6.21MB store? Was it Local Storage? Was it another plugin?Was it a by-product of building the app? Was it anything I was doing or could change or control? I wish I had answers, but I don't.
Lesson Learned: Apple Store rejection is a fact of life. -- Sometimes you get rejected. If you can fix what an Apple reviewer complains about, do it. If not, try again. But, for the sake of the project, allow for time for multiple reviews by Apple in your schedule. Right now, the reviews are taking less than 48 hours. Don't count on that always being the case. Consider Apple's schedule of updates to iOS; whenever an update is imminent, every app developer will be updating their apps and submitting them to Apple. Adding three weeks before the deadline might be advisable.
Summary
At the end of the day we have a working prototype live in the Apple Store and the Google Play Store. And I learned a few things about development and myself along the way. My hope is that this post may be of some help to you.