I haven’t founded a better solution that simply setting the System property as specified in the bug report. Thus, I have a simple class I add to every project’s test suite as a work around. It sets the dexmaker cache and tests the Mockito is property configured.
1 2 3 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
I recently tried out TravisCI and found it much more pleasant. Travis doesn’t seem to be as configurable as Jenkins, but the main uses cases are much simpler to setup. The UI is also much cleaner. Hosted TravisCI is free for open source projects, and there are a few price tiers for commercial projects.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
The before_script
section for launching the Android emulator was based on the setup in the Android TDD example application by Paul Estrada. The sdk_components
block is a bit difference than what is commonly shown on the web for Android (including in the official documentation as of this writing). There is a TravisCI linting tool for testing configurations, and it warns for the more typical android configuration. Note that TERM=dumb
is necessary to have clean Gradle log output.
There are a few assumed pre-conditions. Obviously the project is using Gradle, and specifically the Gradle wrapper. I always find using the wrapper rather than the system Gradle makes configuring the build much simpler. I also typically have Jake Wharton’s SDK Manager Plugin in the build, but that is not strictly necessary if you are only depending on the latest platform version. TravisCI will include the latest platform by default when the language is set to android.
I generally prefer a rapid feedback loop over all else when it comes to CI, including perhaps comprehensive testing of devices & flavors. By default TravisCI runs on every commit to every branch, which really helps catch mistakes early. Although TravisCI can run multiple emulators, I use only 1 to keep the build as short as possible. I also generally run the tests against one specific build variant rather than all variants as shown above. That cuts the build time significantly.
Content Providers are accessed via Content URIs. The first portion of the Content URI is the Content Authority, which should correspond with the package name of the app. The Content URI has to match in both the Manifest and the definition of the Content Provider’s authority in Java. A typical implementation of a Content Provider’s manifest & Content URI definition for an app with a constant package name is below. (For a complete example of implementing a Content Provider I recommend Wolfram Rittmeyer’s post.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Generating multiple packages from Gradle is relatively straightforward. You can either specify the entire package name for a particular build variant or use a packageNameSuffix. The example below specifies the complete package name, but in practice I prefer setting the root of the package name in the manifest and then appending build variant specific suffixes. This example shows splitting the packages based on build flavor (free v paid), though this applies equally to splitting the packages based on build type (debug vs release), or some combination of both.
1 2 3 4 5 6 7 8 9 |
|
No matter how you decide to split the packages, setting up the Content Provider Authority is the same. Since the release of Gradle Plugin 0.7.0 the package name is automatically added to the BuildConfig file and is available for use in constants.
1
|
|
If you are working with several build variants, it is important to understand how Gradle merges the various sources sets. For Manifests, the XML from main, buildType, and buildFlavor are combined. This means that you do not have to duplicate your entire manifest into each build variant folder. Leave the constant portion in src/main, and then only extract the variable portion to the build variant specific folders. The example below is for splitting the package based on build flavor (free/paid), but would also apply for splitting based on build type (debug/release). In this case, nothing about the Content Providers is in the debug & release specific Manifests. Note that you still must put the Content Provider definition within the application block in the build variant specific manifests.
The actual definition will have an authority derived from the package name, but the Content Provider class reference does not change. When you change the package name for your app it effects the .apk’s ‘package name’, but it doesn’t actually change the Java packages at all.
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
You can inspect the merged manifests in build/manifests/free/debug/AndroidManifest.xml and build/manifests/paid/debug/AndroidManifest.xml. If everything is setup correctly, the final merged manifest for any particular build variant will look almost exactly like the original single manifest, except with package name specific Content Authorities. This will allow you to run both apps on a single phone at one time.
]]>Unfortunately I ran into a huge pitfall with Parcelable objects. I have been using a very basic unit test to ensure my Parcelable implementation was correct, and didn’t realize the test wasn’t actually proving everything was working as intended. The other day I was refactoring some code and seeing ClassCastExceptions when pulling a particular Parcelable object out of a Bundle. I couldn’t figure out where the type was getting switched in my code, but it never occurred to me that the actual Parcelable implementation was at fault because I had too much faith in my unit tests. After a couple hours of digging I figured out that the naive unit tests I have been using for Parcelable don’t actually ensure anything. Hopefully this post can help you avoid the same mistake.
First, a quick summary of implementing Parcelable if you have not done it before. In order to make an object Parcelable, you must handle writing to the Parcel, creating an object from the Parcel, and provide a CREATOR factory. This code is pretty straightforward although there are a few gotchas. Take a look at the implementation below for class ‘Foo’. Note that in order to test these types of classes I always make sure to write (or generate) a proper equals() method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
|
(Bonus rant: why did the Android team not include writeBoolean() and readBoolean() methods? I generally pack booleans as an int but you can also use a byte or a String to pass them. Thanks to this answer on StackOverflow for the inspiration on how to pass them cleanly.)
My original unit test naively mirrored how you actually use Parcelable objects. Stick it in a Bundle, pull it out of a Bundle, and check equality.
1 2 3 4 5 6 7 8 |
|
Thus, the above test passed even though the Foo class’s CREATOR was written originally as shown below. Note that CREATOR is returning type Bar instead of type Foo. This is one easy pitfall when writing the boilerplate associated with Parcelable.
1 2 3 4 5 6 7 8 |
|
After finding the actual bug, my concern switched to figuring out why the unit tests hadn’t caught it. It turns out that Bundle doesn’t actually serialize/de-serialize each value until the Bundle itself is parceled. Thankfully James Wilson has a nice solution that correctly tests the object.
1 2 3 4 5 6 7 8 |
|
In fact, with this code the test suite won’t even build because CREATOR’s return value is type checked at compile time, rather than casting from Bundle’s getParcelable() at runtime.
I would recommend writing that unit test anytime you are creating a Parcelable object.
]]>Unlike the release signing keystore, the debug keystore can be changed at any time. In fact they expire 1 year after creation, so if your project runs for a significant amount of time you will have to update it. Simply copy your local debug.keystore file into the repo. On Linux and Mac OS X this is located in ~/.android/. I personally create a new folder named external to keep it separate from the project source code and assets.
Once you have the keystore in your repo, override the default debug signing configuration to use shared file. The sample below are for Gradle, but this is also pretty straightforward in Ant and Maven.
1 2 3 4 5 6 7 8 9 10 |
|
If you have custom build variants, you can use the debug signing configuration as shown below.
1 2 3 4 5 6 7 8 9 10 |
|
This is generally one of the first things I do when setting up a project so I don’t have to ever bother with uninstalling and reinstalling an APK manually. For a bit more information on the debug.keystore file, and where it is located on Windows, see the Android Documentation.
]]>Android’s Gradle build system has had a built-in task for running ProGuard for a while now. The Android Tools site has a small section about ProGuard, but it misses a few crucial details.
The first step is to enable the ProGuard task on a particular buildType by setting the minifyEnabled flag. By default, ProGuard is disabled on the debug build type. I personally make this explicit, but it is not strictly necessary.
Next, use one of the two default Android files as the basis of your ProGuard configuration. Depending on the age of your Android project, you may have a stale base configuration file. I found the newer files work much better. The safest option is the non-optimized file, I have had trouble with the optimized one in the past.
1 2 3 |
|
Next add the required ProGuard rules for the project dependencies. I personally prefer to keep each library’s rules in a separate file so that I can re-use the ProGuard configurations between projects easily. The simplest location for these files is in the top level of the project next to the build.gradle file. I have started a collection of ProGuard files for common libraries on GitHub. Using this approach also untangles the ProGuard configuration when removing unused dependencies from a project.
1 2 |
|
Finally, add one ProGuard configuration file that is a catch-all for the truly project specific rules. Common candidates are any classes that require GSON for parsing (or reflection in general). See the ProGuard manual for more detail on actual configuration rules.
1 2 |
|
When you put it all together, a basic ProGuard configuration looks like the code sample below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
One final note, make sure to keep the mapping.txt file produced by each build to de-obfuscate stack traces. It is located in the build/{appname}/proguard/{buildvariant} folder. You will have to upload the mapping.txt file to your crash reporter (BugSense, Crashlytics, etc). This file changes every time the build is run, so make sure you are careful with versioning the build artifacts (APK & mapping.txt).
]]>