Previously

After implementing a class hierarchy and a unified point of database access via a Content Provider the core mechanisms of my app were in place: the ability to do basic CRUD (Create, Retrieve, Update, Delete) actions on the various types in my database. It was time to put the finishing touches, not all of which were trivial.

Time Keeps Ticking…

The first major task was to enable the user to create notifications for the various data types, most of which had date fields attached. However, in order to get the database functionality working, I had skipped any attempt at verifying user entered dates, which were stored in the SQLite database as plain strings. While a well intentioned user would no doubt enter real dates instead of "next week", it didn’t seem right to cause notifications to fail for incorrectly written dates, either silently or explicitly.

Related was the question of the order of items on the lists of terms/courses/assessments. Keeping with “getting it done” I had sorted them simply by the name of the entry, knowing I would eventually want to “do it right”. That time was of course now.

First I enforced that user entered dates be in a specific format, 23 April 2017. But while simple to enter by text and obvious to read, this type of data is not easily sortable. I needed to translate dates into something more like a timestamp for storage in the SQLite database. Thus was a class born DateFormatter, which contained several static helper methods to translate dates from my chosen human readable format, to a timestamp, and back again. I would also add methods to translate dates into Unix epoch timestamps, since this is how I would schedule notifications.

Notify Me

Actually getting notifications working wasn’t entirely trivial either, but not from a coding standpoint. This was the first time I ran into the stumbling block of the Internet: host to information about many different ways of working with Android apps, all from different APIs and few marked clearly.

I pressed on, found a strategy that worked and implemented it. Testing it consisted of forcing the menu items to schedule notifications not on the date specified, but some fixed amount of time, say 5 seconds, after SystemClock.elapsedRealtime().

Worth a Thousand SLOC

Next up was attaching camera photos to notes. I had kept putting this off because it felt like it would be complicated, but truly Android makes the simple things complicated and the complicated things simple. The actual code to call out to the camera to take a picture?

public void takePicture(View view) {
	Intent takePictureIntent = 
		new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
	if (takePictureIntent.resolveActivity(
				getPackageManager()) != null) {
		startActivityForResult(
				takePictureIntent, 
				REQUEST_IMAGE_CAPTURE);
	}
}

Taking the image and forcing it into and out of the database was somewhat more involved, but not very. SQL has a datatype blob for a reason. (Though better practice would probably have been to save a URI for the photo)

SMS was scarely more complicated:

private void sendSMS() {
	Uri uri = Uri.parse("content://contacts");
	Intent intent = new Intent(Intent.ACTION_PICK, uri);
	intent.setType(
			ContactsContract.
			CommonDataKinds.
			Phone.CONTENT_TYPE);
	startActivityForResult(intent, 1);
}

Minor Minor Minor

There were a few other minor details to fulfill various requirements or my own sense of pride:

  • finding something semi-reasonable to store not in the SQLite database, but with SharedPrefs
  • making sure that somewhere I was using an ArrayList
  • fixing a nagging InternalException that had not disrupted anything but been hitting the logs since the beginning of the project
  • validating deletion of database items to prevent orphaned data
  • adding a wider selection of sample data
  • icons
  • reducing some layout duplication
  • refactoring the massive amount of duplicated code in the ContentProvider

Wrapping it up in an APK

Ultimately I learned a lot, including that working with XML is not my idea of fun and that mobile app development might not be either. You can certainly develop something rapidly if you know what you’re doing, but boilerplate is everywhere. Android Studio seems almost a necessity, just to keep track of the massive Android library. Discerning which information is from too far in the past to be of use, which information is for an API too far in the future to be of use, and which information is just right is a massive pain.

Making it all look good is certainly not as easy as it looks. It may be some time before I revisit Android development, but I’m glad I was pushed to do it.