With ABI Filters we specify the architectures that we want to keep, which is the opposite of what we were previously doing, which was manually removing the libraries we didn’t want to keep. So, what we’re doing is keeping 32-bit architectures, both for ARM and x86 (we’re excluding 64-bit libraries and MIPS).
Notice that nowadays I would also exclude “armeabi”, as all the nowadays devices use at least “armeabi-v7a”.
You now provide fallbacks for missing build types and flavors using matchingFallbacks (which replaces buildTypeMatching and productFlavorMatching). You also provide the default selection and fallbacks for missing dimensions using missingDimensionStrategy (which replaces flavorSelection).
So, our previous app build.gradle gets converted to:
//buildTypeMatching 'releaseWithLogs', 'release' // remove this
//buildTypeMatching 'debugMinified', 'debug' // remove this
matchingFallbacks = ['debug'] // instead use this
matchingFallbacks = ['release'] // instead use this
Notice that, instead of saying that buildType releaseWithLogs will also match with release (buildTypeMatching 'releaseWithLogs', 'release'), we specify the match inside the buildType itself. Same for debugMinified matching debug. Also notice that there’s no need to include this in release and debug buildTypes, as they already match.
I’ve been working with Kotlin for a while, mainly for side-projects or toy-projects. Since last Google I/O 2017 announcement it has become clear that there are no more reasons or excuses to not use it in production.
One of the big selling points of Kotlin is that you can start small, by converting one class or two, or by creating new ones, while keeping all the remaining code in Java. So, interop between the two languages is almost 100% transparent. Almost.
Working to convert a small project step by step, I started to convert activities into Kotlin. Those activities use ButterKnife (I’m using current version, which is 8.7.0) to inject the views. So, after converting the first activity I stumbled upon a problem with the annotation processor: in Gradle script, you have to use either annotationProcessor or kapt, but not both at the same time. So, you have to choose:
using annotationProcessor only will not find Kotlin classes, and because of that injection will silently fail at runtime,
using kapt only will make compilation fail.
The final workaround I found was:
using kapt3 (by applying kotlin-kapt plugin to the Gradle script) and,
adding a @JvmField() annotation in addition to ButterKnife annotations so Kotlin compiler generates public fields instead of getters and setters.
By applying kapt3 we fix the compilation error involving “kotlin.jvm.internal.FunctionReference.(ILjava/lang/Object;)V” and by converting Kotlin fields to plain-old Java fields we allow ButterKnife compiler to find the fields to inject, as is unable to find Kotlin fields.
You can find the source code with different options in different branches (the one with the final solution is kotlin-workaround) in this GitHub project.
The project has two activities, one (MainActivity) that is written in Java and kept in this language, and the second one (NextActivity) that is converted to Kotlin. Notice that a simple suite of tests is available to check that both activities are being correctly injected, and that there is a TextView in both activities that has its text replaced by code to prove that the activity has been successfully injected.
Sometimes you have to add code to your applications that is used for debugging purposes. This can be very useful, and sometimes is keep there as it helps in the development and debugging of different parts of the application. But, some of this code can have unintended consequences:
it can reveal sensitive data to a potential attacker (internal URLs, session cookies, etc.)
it can have a performance impact in your application (excessive logging, performing operations not needed for release builds, etc.)
it can lower the security of your application (backdoor-like features to help while debugging, that can disable certain security features, or completely bypass them, etc.)
We have a Jenkins server taking care of CI for an Android project. In the server we were using Java 7, but since we updated a few dependencies we needed Java 8 to run some Gradle plugins. After the change, we suddenly started to get this error in the builds:
* What went wrong:
A problem occurred evaluating project ':my-project-app'.
> java.lang.UnsupportedClassVersionError: com/android/build/gradle/AppPlugin : Unsupported major.minor version 52.0
Jenkins is configured to run using Java 7, and changing may pose some problems (and currently any failure could put our schedule in jeopardy)
we decided to just run Gradle script using Java 8. To configure it, the following change was done to the configuration of the job: in section Build Environment, enable Inject environment variables to the build process and add the following to Properties Content:
This morning I was playing with a toy app I have which uses Retrofit, and I’ve found the following problem with it (and Instant Run):
02-16 07:41:55.550 2976-2976/com.test.android A/art: art/runtime/thread.cc:1329] Throwing new exception 'length=227; index=1017' with unexpected pending exception: java.lang.ArrayIndexOutOfBoundsException: length=227; index=1017
The exception was in the call itself, so it was either Retrofit doing strange things or something deeper. I found the problem to be because of some interaction between ART and Instant Run, and it was already reported.
All in all, currently there is no fully reliable solution. So, if you find this problem in a call using Retrofit, the best course of action is to disable Instant Run and rebuild. Preferences -> Build, Execution, Deployment -> Instant Run -> (uncheck) Enable Instant Run to hot swap code/resource changes on deploy (default enabled)
I’ve been toying with Kotlin for a while. Yesterday RC was released, making it one step closer to have a stable version.
One small change that has made me scratch my head a little, even if I read the solution, has been the changes regarding Kotlin Extensions. This had been integrated with the main Kotlin plugin (instead of being a separated plugin) but on RC you need to change your Gradle file a little to keep using it.
The symptom is that you find an “Unresolved reference: kotlinx” plus others that come from the same namespace. Resolution is easy: in the announcement for the release Kotlin 1.0 Release Candidate is Out! in the section Tooling, it reads (bold is mine):
To enable Android Extensions in Gradle in a more idiomatic way, we now say:
apply plugin: 'kotlin-android-extensions'
in the build.gradle file (individually for each project).
The old way doesn’t work any more and prints fixing instructions to the output.
So, I haven’t found this instructions, but the solution is easy: apply the new kotlin-android-extensions plugin right after the kotlin-android plugin in your gradle file. Usually, the end result will be like this: