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
versionCodeincreased, andversionNamehaving a higher „patch level“ (see semantic versioning). The tag name should correspond to the newversionNamethen, 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 andDeclared READ_CONTACTS |
READ_CALL_LOG |
minSdk < 16 andDeclared 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
targetSdkof a library is set to itsminSdk - 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).
Fastlane and Translation Services¶
Translators are often unaware of consequences when exceeding character limits (hint: all text behind the limit will simply be truncated, even mid-word), and thus commit „longer strings“ even when told not to. Luckily, some translation services provide means to enforce such limits.
Weblate¶
Weblate allows to set „enforcement checks“ for string lengths. In your Weblate component, go to Operations › Settings › Translations › Enforced checks and make sure „Maximum length of translation“ is on the right side. Then, block ignored checks from getting committed.
Despite what you would think from the description of „enforced“, users can still just hit submit a second time to force-submit a translation. So you need to prevent those from being committed. For this, in your Weblate project, go to Operations › Settings › Workflow › Translation quality filter and make sure it is set to „Skip translations marked as needing editing“. This keeps them from being committed to git.
After you've done both it should work as intended to prevent new incorrect submissions.
(source: this issue comment by Sylvia)
Crowdin¶
Crowdin also allows you to set a maximum translation length, see Adding Strings and String Editing in their documentation.