Sat, 21 May 2016
Releasing another Android app on Google Play
Summary: I started releasing Android apps in 2011, this is about my recent release of an app I wrote over the past 2 1/2 months. I walk through my whole process.
From mid to late February, I spent two weeks working on an Android app, a process which I write about here. With that done, I began casting around for my next project.
I wanted to write an Android app for which the time I would spent writing it would hopefully be financially remunerated. From previous experience, I knew writing an app for the mass market would be the most likely to yield this, as opposed to an app for some niche market. As I have not had much success with games on Android, but have had success with non-game applications, I decided not to do a game. I've also had success with ad-based apps so I decided to get revenues from ads.
These constraints satisfied, I now have a more limited number of possibilities to choose from. I could do a photo editor, a battery saver, a wallpaper app, a file manager and this sort of thing. So at this point I roughly estimated how long it would take me to write a minimally viable version 1 of each of these apps. Then I sorted this list by time. Then I ticked off some other factors, like probability of success in the timeline, how much competition would have to be dealt with (with say for instance, yet another flashlight app). Another factor is what appealed to me - what near the top of the list would be more fun to do, would I learn from etc.
Going over the list, a wallpapers app started to seem like the best choice. I could write version 1 in less than three months, it was for the mass market, I could probably compete enough with the existing players to get some of my time remunerated, it would be more enjoyable than the alternatives etc. It did have some drawbacks - if it were to be a success, I would need not just hundreds of wallpapers, or thousands, but tens of thousands, or hundreds of thousands or millions. But I could probably get away with only having a few hundred wallpapers for version 1. So I chose to do a wallpapers app.
I look at the competition. There are two apps with 10-50 million downloads, one with 50-100 million downloads, and one with 100-500 million downloads. So that looks good, I'll start doing OK if I go into the hundreds of thousands of downloads, if it goes into the millions I will start getting remunerated for real. The apps all differ from one another slightly, but most are similar in many ways.
I decide if one of these top apps lacked a feature and succeeded, my version 1 can lack that feature as well. So I don't need a search feature (with only a few hundred wallpapers, it seems a pointless feature any how). I don't need tags. The only tabs I need are recent, popular and categories. I can start with just 11 categories. I can skip a favorites feature. I don't need a share feature (although that would be desirable for increasing the app's popularity from both ends - the sharer and the person who gets the share and may learn of the app). I can skip some of the design and design animations. I can skip a related wallpapers feature. For picture information I will put license, attribution and perhaps some information on the picture, but can skip some of the other information for now. So a lot of this is just limiting scope so version 1 will be published in a reasonable amount of time. Some of these things can come later. I would prefer a high percentage of people who download the app to keep it and use it, and for its ratings to be high. So that reflects on the schedule as well.
Since I am doing the full stack and sourcing the images as well, I have to decide what order to do things in. As sourcing the images is the most outside my control (unless I make all my own wallpapers), I decide to start with that. The limitations I encounter there will guide the rest of the project. Also, if there are any unpleasant surprises I prefer to learn them early, and perhaps even drop the project quickly if they're too much, not having wasted much time on it. So I'll start with picture and picture information sourcing, then do the database, then make a REST API interface between the database and client, and then do the Android client.
So I start casting around for image sources. Wikimedia Commons seems a good first source. They have a lot of good images, the licenses are usually Creative Commons or public domain. Wikimedia Commons has featured pictures which help me pick pictures more quickly, featured pictures are also translated into many languages already, usually. They also have a decent API. I start formulating an idea of what the MySQL database schema will be (As this project's scope is limited, it will not entail a MySQL to MariaDB migration). I download a few pictures and note their picture information. I start writing a Python 3 script to parse the XML from the Wikimedia Commons API. Instead of hammering the API for the same XML over and over, I download it locally and work off the file.
Work on Python script.
So now I feed my Python script an image URL, or a source URL on Wikimedia commons, and it downloads the related image, as well as queries the Wikimedia commons API and gets the file name, title, size, uploader, license, description, and other information. It's pretty much pulling all I need to start with now.
So now I really start my database schema. I use MySQL workbench to help. I try to remember all that first normal form, second normal form etc. stuff. One thing I consider is things which are singular now, but might be plural in the future. What if a wallpaper can be gotten from multiple sources? What if a wallpaper has multiple licenses? I design with this in mind.
Still designing schema
Start writing functionality in Python to insert the information pulled from Wikimedia Commons API into the database created by the new database schema.
Keep adding database insertion functionality into Python script (take St. Patrick's Day off).
Finish putting in functionality. Start populating server database with image information and web proto-API with images.
I'm happy this is done, but 17 days in it seems we have not come that far.
I put a JSON on the web server pointing to the image files. I start working on the Android app. I had already decided to use the Android Universal Image Loader (UIL) library as I am familiar with it. I load the JSON, load the image URLs, then load them into a Gridview with UIL.
Start selecting images. Get pictures of food, animals, flowers etc. Now loading on the Android device. I notice Wikimedia Commons is good for many things, but is lacking in some areas. It is good for real pictures, but not so much images of inspirational quotes, artwork, photographs with heavy filters overload on them for artistic purposes, and this sort of thing.
I start looking for another image source, to fill in for what Wikimedia lacks. Deviant Art seems a good choice. They have a good API, and many of their pictures have amenable licenses which I can use. They also fill out many of Wikimedia Commons gaps - images with inspirational sayings, artwork, filtered photographs, themed photographs (flowers in a heart shape and that sort of thing). So I start working on a deviantart script. This also reflects on the database schema - ultimately the database will have various image sources, so adding a second source hardens up the database. For example, Wikimedia commons gives a sha1 hash for its images, DeviantArt does not, so I will either have to do a sha1 for each new image, or drop that column from the database schema.
This is getting long, so I'll be more brief for the middle section of the project
Add a details JSON for each wallpaper
Add functionality so that people can download and set wallpapers on Android
Download wallpapers from Deviantart
Make Android icon for app
Work on JSON for details page
Work on Android details activity. Work on picture grid design details.
Wikimedia commons uses a lot of HTML for details - so put clickable links in Android for them
Get more wallpapers. Increase database size for various columns.
Select which categories to do. Start downloading sports pictures (one of the categories for v. 1)
Wallpaper image on details page can be smaller than final downloaded wallpaper. The images in the image grid can be yet smaller. So write Python scripts (using Python Imaging Library) to shrink the original images down to a detail thumbnail and an even smaller grid thumbnail.
Add code to check for network connectivity problems and deal with them accordingly
Download content for first categories. Cats, dogs, cities, outer space etc.
Also, from April 19th to the end of April, I don't do much programming for the app, as I am busy with other things, including sending Android-related patches to XScreenSaver for its 5.35 release.
OK, with all this content, now the initial JSON is starting to get pretty big. Even though this is version 1, I will have to deal with this sooner or later and dealing with it now will cause less headaches later. So I start splitting the JSON up.
It makes things much more complex, but it will inevitably be this way any how if the app is a success. It's complex due to mutual exclusion - UI events etc. can be happening between the request and processing of new JSON image URLs. For the next 19 days I will alternate between dealing with this, and everything else that needs to be done.
So I have been implementing the splitting up of JSON primarily since April 30th. My code was refactored a lot between April 30th and May 3rd to deal with this. By March 14th I have the components for split JSON, but a lot of crud has accumulated and the logic is a little off. Much of the crud is due to the splitting of JSON, but that is not just it - there is also duplication of code and unneeded complexity. It would be quicker to just start from a fresh Android project, and string together the various components of what has been written so far.
To prepare for that I clean things up. I move any string in the code to strings.xml. I add local Android information for various licenses in the server database. I add language to the web REST API. I modify the UIL to deal with out of memory errors on older devices. Then I start rewriting the app from the ground up.
I put an onScroll listener on the image grid, and use the end of the scroll as a trigger to load more JSON
I get rid of code duplication among the category and recent/popular activities. I combine the common code, and subclass the unique functions to different classes.
UIL has an annoying flicker when the data set changes, so I change the code to not reload on that signal. I start the app by downloading a small JSON, and when that's processed, do two things asynchronously - load those images, and fire off another JSON to have the information to load the next 48 images off the screen if we scroll down.
We're headed into the home stretch. I register a domain name for the app. I add Google Analytics (too much analysis it complains - so I cut down on the number of messages I send). I fix up the design some. I publish the app to alpha testing on Google Play.
While there is something to be said of a waterfall method of programming and releasing a polished jewel, the reality is that my income or capital or what have you is not unlimited. Also, I would like to start seeing what the market response will be. So I prepare for release.
Some minor tweaks and - release! Yay! I post to my Facebook and Twitter pages and can see from the server and Google Analytics that I am getting some downloads.
In a few hours I see that I released with a bug in the code. In Android Marshmallow (6.0), permissions changed, which ultimately renders the app unable to set wallpapers on Marshmallow devices. I had QA'd the app on a 6.0 AVD/emulator, but not the set wallpaper step. I already dealt with this problem on another app, so I code up a fix and release version 1.1 of the app.
I set up some ad campaigns for the app. I don't want to do a big promo right off the bat, but to drive in a trickle of interested users. Also it takes a little bit to get ads setup and approved and tuned right.
Then I write this up.
I have plans for future versions. One of the first is to download more wallpapers, so I am already on that. I also have other ideas which I punted on for the first version. You can download it now.
So I am still downloading new images and coding up various improvements for the next version. Also some other things I put aside I will get back to working on. Nonetheless, all that considered, I should start thinking of my next app. I want to put out a few apps that have potential, and then hopefully one will take off somewhat, and then I can put more wood behind that arrow. So soon I'll start thinking about what my next app will be.
Tools used:Database schema design: MySQL workbench
Android programming: Android Studio - code is Java language with Android-specific classes and quirks. I run the Android Studio IDE locally on my Ubuntu machine.
Android 3rd party libraries: Android Universal Image Loader
REST API programming: Python 3 on an Apache web server, hooked to a MySQL backend. Running on a Debian Linux VPS at Linode. I use vi to edit the Python code on the server.