Android App Porting Guide

From F-Droid
Jump to: navigation, search


Android is fast-paced platform, and has been on the market for a while now. Android devices also come in various shapes, form factors, for various uses and intended audience. This means that Android ecosystem is highly fragmented. Android platform itself has good means to avoid and deal with fragmentation, but not all application developers know and use those features, which leads to all of the following and more:

  • Old applications developed/tested on old Android versions don't work well on newer OS versions.
  • Newly written apps don't work on devices with older Anroid versions.
  • Some apps don't work properly or at all on particular devices or set of devices (based on their features).
  • Particular features of some apps misbehave or cause force-closures on some devices due to presumption of available environment (like availability of Market/Play app) and lack of proper error handling.

Open Source allows to remedy most of the issues above, and F-Droid strives to provide well-behaving and usable application for as many devices as possible. This page collects documentation and fixes for common problems seen in the application. Ideally, all the fixes should be submitted to the upstream projects. Sometimes, upstream authors don't respond in timely manner, and it may be acceptable to fix the issues using patches applied in F-Droid build recipes.

Specific Cases

Ugly Screen Compatibility Mode 1

There're few screen compatibility modes for older apps running on newer Android versions, with mode 1 being most annoying, causing an app to run in stamp-sized window on a bigger screen. Based on the quoted doc, the best and safest way to disable this compatibility mode is to have android:targetSdkVersion="4" (or higher). Note that this doesn't change app behavior otherwise - in particular, it doesn't limit minimal version of Android the app may run on. You just certify that the app is Android 1.6 (or higher) ready (which you of course should verify by running the app, but any decent app not using absolute coordinates for layout should work). Btw, don't use android:resizeable="true" - it's deprecated. Also note that having explicit android:minSdkVersion="4" is kind of mandated for newer SDKs, so you may want to set that too (to "1" if in doubt, that's default).

Implicit permissions for API < 4

Apps with both minSdkVersion and targetSdkVersion values < 3, implicitly get WRITE_EXTERNAL_STORAGE and READ_PHONE_STATE which is both alerting to users and actually has security issues. So, targetSdkVersion should be at least 4 for any app (minSdkVersion can be as low as 1).

Rigid Access Requirements for Peripheral Devices/Features

As Android progressed, and variety of device features appeared, Google added application feature requirements. However, if feature requirements (were introduced later) are not explicitly specified, they are implied from permissions the app requests (were introduced earlier). It may seem a bit far-fetched to imply that if an app requests access to camera, it 100% needs it and can't work without it. But Google actually had little choice, taking into account poor quality of available Android software. The logic chain is: if an app requests access to camera, that it kind of expects to have access to camera, then it probably doesn't handle lack of camera gracefully. Experience with packaging software for F-Droid project proved such assumption to be very valid - lot of software will just crash on accessing a feature which is not available on a device, be it camera, GPS, or something else. So again, Google had little choice but to "protect" users of Market from force closure they would for sure experience.

That said, feature requirements (required/optional) are not build deep into OS, so it's possible to install "incompatible" package via ADB/direct download to device. But features are still used as "filters" for compatible software by software repositories like Android Market and F-Droid, so it makes full sense to set them right.

Typical patch to apply is:

     <uses-permission android:name="android.permission.CAMERA"/>
+    <uses-feature android:name="" android:required="false" />

Here, if we know that an app just could use a camera as convenience for user, but otherwise doesn't depend on it in any way (for example, if it just allows to scan a QR-code or can also open an image from a file), that's what we do: set camera feature as optional.