Optimizing Android manifest file for largest number of supported devices

iwasrobbed picture iwasrobbed · Dec 24, 2012 · Viewed 8.4k times · Source

I am having issues getting my Manifest file to be compatible with a lot of the newer phones when I upload a new APK file and I don't understand why. I am testing it on a brand new HTC Evo V, but for whatever reason, that device won't show up in the compatibility list.

I'm compiling against API 17 with a minimum support of API 10, so that should encompass a large majority of the phones.

What I've tried:

  • Removed all permissions; no change
  • Tried making WIFI not required; no change
  • Removed installLocation to see if it made a difference; no change
  • Even tried adding small screen support to see if it'd show up; no change

What I've read:

My manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.somecompany.appname"
      android:versionCode="10"
      android:versionName="1.0"
      android:installLocation="preferExternal">

    <!-- For expansion pack downloads -->
    <!-- Required to access Android Market Licensing -->
    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
    <!-- Required to download files from Android Market -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Required to keep CPU alive while downloading files (NOT to keep screen awake) -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <!-- Required to poll the state of the network connection and respond to changes -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- Required to check whether Wi-Fi is enabled -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <!-- Required to read and write the expansion files on shared storage -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/>
    <supports-screens android:normalScreens="true"/>
    <supports-screens android:largeScreens="true"/>
    <supports-screens android:xlargeScreens="true"/>

    <compatible-screens>
        <screen android:screenSize="normal" android:screenDensity="mdpi" />
        <screen android:screenSize="large" android:screenDensity="hdpi" />
        <screen android:screenSize="xlarge" android:screenDensity="xhdpi" />
    </compatible-screens>                      
    <application android:icon="@drawable/icon" android:label="@string/app_name" android:allowBackup="false">
        <activity android:name="somecompany.appname.SplashScreen"
                  android:label="@string/app_name"
                  android:theme="@android:style/Theme.NoTitleBar"
                  android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="somecompany.appname.SoundAndCallActivity" android:screenOrientation="portrait" android:theme="@android:style/Theme.NoTitleBar"/>
        <activity android:name="somecompany.appname.MainScreenActivity"   android:screenOrientation="portrait" android:theme="@android:style/Theme.NoTitleBar"/>
        <activity android:name="somecompany.appname.SettingsActivity"   android:screenOrientation="portrait" android:theme="@style/Theme.Transparent"/>
    </application>
</manifest>

Answer

iwasrobbed picture iwasrobbed · Dec 24, 2012

I wanted to post this question and also an answer because I found this to be so frustrating to figure out at first. However, this changed my number of supported devices from 499 to 1968. Hopefully this will help more people in the future since it seems to be an obscure topic.

Technique 1: The reason why more devices wouldn't show up was because Google filters more aggressively when you use the <compatible-screens> tag. In my case, I didn't have enough of the different screen sizes and density combinations, so it filtered out all of the ones I left out (see Technique 2 below).

If you instead ONLY use the <supports-screens /> tags, then you will enable your app to be found by many more devices. So do yourself a favor and remove all of those other tags in the <compatible-screens> block.

You can use a shortform like this:

<supports-screens android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" android:anyDensity="true"></supports-screens>

Quoted from the original article:

Google Play filters the application if the device screen size and density does not match any of the screen configurations (declared by a "screen" element) in the "compatible-screens" element.

Caution: Normally, you should not use this manifest element. Using this element can dramatically reduce the potential user base for your application, by excluding all combinations of screen size and density that you have not listed. You should instead use the "supports-screens" manifest element (described above in table 1) to enable screen compatibility mode for screen configurations you have not accounted for with alternative resources.

Technique 2: Another technique you can use is to be more specific with your <compatible-screens> tag and get rid of the <supports-screens /> tags. You can base those decisions on your app requirements and also on the latest device distribution numbers.

In the example below, I don't want to support small screens or the ldpi densities of the normal, large, or xlarge screens, so I left them out.

<compatible-screens>
    <!-- all normal size screens -->
    <screen android:screenSize="normal" android:screenDensity="mdpi" />
    <screen android:screenSize="normal" android:screenDensity="hdpi" />
    <screen android:screenSize="normal" android:screenDensity="xhdpi" />
    <!-- all large size screens -->
    <screen android:screenSize="large" android:screenDensity="mdpi" />
    <screen android:screenSize="large" android:screenDensity="hdpi" />
    <screen android:screenSize="large" android:screenDensity="xhdpi" />
    <!-- all xlarge size screens -->
    <screen android:screenSize="xlarge" android:screenDensity="mdpi" />
    <screen android:screenSize="xlarge" android:screenDensity="hdpi" />
    <screen android:screenSize="xlarge" android:screenDensity="xhdpi" />
</compatible-screens>