LinkageError and Your Android Code
I received a couple of reports of a java.lang.LinkageError
when
using my older CWAC-Camera
library on apps with a compileSdkVersion
set to 23. My resulting
investigation points out an interesting problem in Android development,
particularly for those of us publishing libraries.
What happened was that API Level 23 added a
getHost()
method to Fragment
.
That’s all fine and well, but my library ships a subclass of Fragment
(CameraFragment
), and I had my own getHost()
implementation, dating
back a year or two.
Mine returns a CameraHost
, while the framework’s one returns an Object
.
They also have distinctly different roles.
If you open up the class (CameraFragment
) in Android Studio, you now
get a Lint message, indicating that “This method is not overriding anything
with the current build target, but will in API level 23”. That’s useful,
but it does not help with existing compiled code.
If your compileSdkVersion
is 21 or higher, and you have an incompatible
override like this, you will get the LinkageError
. My guess is that
this is somehow related to ART, as I cannot understand why API Level 21
would otherwise be a magic API level here (the source history shows that
getHost()
was definitely added in Android 6.0). As it turns out, if you
leave your compileSdkVersion
at something lower (e.g., 19), not only
do you compile cleanly, but you appear to run OK, so long as the
accidental override is not being used by the framework (I guess).
In my case, the problem is compounded by two things:
-
The method (
getHost()
) is part of the library’s public API, meaning that fixing this “for realz” requires a breaking API change -
This is a library that I have replaced due to a poor job implementing the original library
The moral of this story: when a new API level comes out, and you
publish a library, double-check your existing code to see whether
or not you get these Lint messages… even for code that otherwise
should be unaffected by the API level. This is especially true where
you are subclassing Activity
, Fragment
, or other BFCs
(Big Frakkin’ Classes), where Google is likely to add new methods that
might collide with ones in your subclasses.