Programming an Android Zotero Client - Part 1

18th of January 2018

I've started writing an Android application. It's almost ready for release on the Google Store. This is the first time I've properly ventured into the app-economy. It's been an interesting few months thus far. I have a few tips for these starting out.

Zotero

If you aren't familiar with Zotero, it's a fantastic program that organises all your documents. It focuses mostly on academic writing, creating citations, bibliographies and such. It started out as a browser plugin, then it was followed by a standalone application. You can save your PDF from, say, IEEEXplore or PubMed direct to your library and autogenerate all the fields for authors, journals, dates etc. If you need to export for bibtex or evernote, all of that stuff is one click away. Basically, I couldn't do my research without it.

Zotero makes it's money through offering storage for your PDFs in the cloud. This is basically a front-end to Amazon. If you have your own Webdav setup though, you can use that inside.

Finally, the Zotero crew have a really good community that I've been talking with. Getting advice from potential end users has been really helpful, and I'd encourage folks to consider getting such people on-board as beta testers if they are keen. You'll get a lot of good feedback.

Beginning Android development

Android Studio
A typical Android Studio session for me, with a simulated device in the foreground.

To program in Android, you can used Android Studio which is what I do. I believe it used to be based on Eclipse but now it's IntelliJ or similar. You could probably develop for Android using just the command-line, java compiler and notepad++ if you wanted but I've not tried. For ease of use, I installed all this on Windows - it's just a little easier to sort out.

There is quite a lot to sort out once this is installed. Inside Android Studio there is a manager for all the Android SDKs. You'll need to install at least one for a particular Android version.

One of the best things about the development process is the Android Device Emulator. You can setup pretty much any device with any Android version. So you can be running your program right away on a simulated device. i tend to have a few different devices with difference screen sizes, Android OS versions and what not, so I can get a good idea of how my application will look on different devices.

Learning Android Java

So if I was to sum up android development, it would be copying and pasting from StackOverflow until your development environment breaks.

Android Development
This is pretty much what android development is really all about if we are honest.

It's a shame but the reasons are simple. There are so many versions of the Android SDK and what-not, and so many different devices to support, you often find differing code to do the same thing. For example, here is a function I had to write to find a place on disk to save downloaded files:



Vector paths = new Vector<>();
paths.add(download_path);

paths.add(activity.getApplicationContext().getFilesDir() + "/ZotDroid/");

File root_dir = new File(activity.getExternalCacheDir(), "ZotDroid");
paths.add(root_dir.getAbsolutePath());

paths.add(Environment.getExternalStorageDirectory().getAbsolutePath() + "/ZotDroid/");

root_dir = new File(activity.getExternalCacheDir(), "ZotDroid");
download_path = root_dir.getAbsolutePath();
paths.add(download_path);

paths.add(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).toString() + "/ZotDroid/");

for (String path : paths) {
    root_dir = new File(path);
    if (!root_dir.exists()){
        if (root_dir.mkdirs()){
            download_path = root_dir.getAbsolutePath();
            break;
        }
    } else {
        if (root_dir.canWrite() && root_dir.canRead()) {
            download_path = root_dir.getAbsolutePath();
            break;
        }
    }
}

I need to check a variety of different places depending on all the versions. I had to wander through a few Stackoverflow posts but the thing is, I don't really care. Sounds terrible but I just want a directory to save things! I'm thinking about other things such as the Zotero API, or what database schema I need. I don't have time to worry about this simple thing, even though it is crucial to function. Android is full of this sort of thing. The UX in particular is also problematic, with many things that are supported or not.

Debugging

This is crucial of course. Like many programmers I don't like writing tests, but it's possible to write unit tests reasonably easily inside the IDE. Perhaps more usefully, it is good to be able to get remote error reports from your end users and beta testers if you can. Because there are so many devices you need to test, it's better to leverage what you can. I suspect there are probably services you can use to automatically test your app on many devices but I settled for using the library ACRA. When your app crashes, ACRA will catch it and send the errors to you via email, webdav or similar. I decided to setup a CherryPy UWSGI setup on my server machine to catch errors. The setup for ACRA is quite easy and once you've dropped your library into your project, it should work fine. The webserver, uwsgi part is a bit more troublesome but that's for another time.

Next time...

Writing this Android App has been both useful and a slog. I started this because I really wanted to read academic papers on my tablet, away from my main workspace. It turns out I'm not alone in that. In my next post, I'll talk about the database backend, OAUTH, and the tricky nature of large Zotero libraries.