Skip to content

Miscellaneous hints for developers

Never replace what was already distributed

Replacing an already published release, or APKs attached to it, can come with several side effects. To mention the most obvious:

  • folks who manually install from your releases, might not notice replaced APKs if they see no new releases
  • whatever goes by tags/releases to fetch the latest update, would not process the same tag/release again (e.g. our repo updater, our builders)
  • independent builders checking for Reproducible Builds, having processed the original tag/release/APK, will not process the replaced one – so their confirmation would be void (as checksums of the APKs no longer match)

If something went wrong, instead consider the following:

  • remove the APK from an existing release if it e.g. has serious issues (e.g. security problems, instant crashes)
  • make a new release, with versionCode increased, and versionName having a higher „patch level“ (see semantic versioning). The tag name should correspond to the new versionName then, of course.

Implied permissions

Sometimes, various permissions show up in the final AndroidManifest.xml of your Android app, and you wonder where they come from. Apart from dependencies having them declared, there are also permissions which are implied, based on SDK versions:

Importing a library Declares this permission in the merged application manifest
minSdk < 2 WRITE_EXTERNAL_STORAGE
minSdk < 4 WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
Declared WRITE_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE
minSdk < 16 and
Declared READ_CONTACTS
READ_CALL_LOG
minSdk < 16 and
Declared WRITE_CONTACTS
WRITE_CALL_LOG

(source: this article, via Warren Bank; also see aapt/Command.cpp)

Android libraries declare a minSdk, but they do not declare a targetSdk (the com.android.library gradle plugin deprecated and later removed the targetSdk property). When an application is compiled and the manifests for its libraries are merged:

  • the targetSdk of a library is set to its minSdk
  • depending of that targetSdk, implied permissions are then added to the application, as outlined in above table.

So if e.g. android.permission.READ_PHONE_STATE shows up unexpectedly with your app, check if any of your libraries has no minSdk declared (which would be considered equal to minSdk:0).