Google Play Console error – Non-upgradable to installed app

According to the Android documentation:

You can use the aapt tool, included in the Android SDK, to determine how Google Play will filter your application, based on its declared features and permissions. To do so, run aapt with the dump badging command. This causes aapt to parse your application’s manifest and apply the same rules as used by Google Play to determine the features that your application requires.

By running that command on your installable and instant app apks the following info is printed.

Installable app (version 551):

package: name="skyesoftware.blogspace" versionCode="551" versionName="0.3.1.551" platformBuildVersionName=""
sdkVersion:'18'
targetSdkVersion:'26'
uses-permission: name="android.permission.INTERNET"
uses-permission: name="android.permission.READ_EXTERNAL_STORAGE"
uses-permission: name="android.permission.WRITE_EXTERNAL_STORAGE"
uses-permission: name="android.permission.ACCESS_WIFI_STATE"
uses-permission: name="android.permission.ACCESS_NETWORK_STATE"
uses-permission: name="android.permission.RECEIVE_BOOT_COMPLETED"
uses-permission: name="android.permission.ACCESS_COARSE_LOCATION"
uses-permission: name="android.permission.ACCESS_FINE_LOCATION"
uses-permission: name="android.permission.WAKE_LOCK"
uses-permission: name="com.google.android.providers.gsf.permission.READ_GSERVICES"
uses-permission: name="com.google.android.c2dm.permission.RECEIVE"
uses-permission: name="skyesoftware.blogspace.permission.C2D_MESSAGE"
…
feature-group: label=""
  uses-feature: name="android.hardware.faketouch"
  uses-implied-feature: name="android.hardware.faketouch" reason='default feature for all apps'
  uses-feature: name="android.hardware.location"
  uses-implied-feature: name="android.hardware.location" reason='requested android.permission.ACCESS_COARSE_LOCATION permission, and requested android.permission.ACCESS_FINE_LOCATION permission'
  uses-feature: name="android.hardware.screen.portrait"
  uses-implied-feature: name="android.hardware.screen.portrait" reason='one or more activities have specified a portrait orientation'
  uses-feature: name="android.hardware.wifi"
  uses-implied-feature: name="android.hardware.wifi" reason='requested android.permission.ACCESS_WIFI_STATE permission'
…
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--' 'af' 'am' 'ar' 'az' 'az-AZ' 'be' 'be-BY' 'bg' 'bn' 'bn-BD' 'bs' 'bs-BA' 'ca' 'cs' 'da' 'de' 'el' 'en-AU' 'en-GB' 'en-IN' 'es' 'es-ES' 'es-US' 'et' 'et-EE' 'eu' 'eu-ES' 'fa' 'fi' 'fr' 'fr-CA' 'gl' 'gl-ES' 'gu' 'gu-IN' 'hi' 'hr' 'hu' 'hy' 'hy-AM' 'id' 'in' 'is' 'is-IS' 'it' 'iw' 'ja' 'ka' 'ka-GE' 'kk' 'kk-KZ' 'km' 'km-KH' 'kn' 'kn-IN' 'ko' 'ky' 'ky-KG' 'lo' 'lo-LA' 'lt' 'lv' 'mk' 'mk-MK' 'ml' 'ml-IN' 'mn' 'mn-MN' 'mr' 'mr-IN' 'ms' 'ms-MY' 'my' 'my-MM' 'nb' 'ne' 'ne-NP' 'nl' 'pa' 'pa-IN' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'si' 'si-LK' 'sk' 'sl' 'sq' 'sq-AL' 'sr' 'sr-Latn' 'sv' 'sw' 'ta' 'ta-IN' 'te' 'te-IN' 'th' 'tl' 'tr' 'uk' 'ur' 'ur-PK' 'uz' 'uz-UZ' 'vi' 'zh-CN' 'zh-HK' 'zh-TW' 'zu'
densities: '120' '160' '240' '320' '480' '640' '65534'

Instant App base feature:

package: name="skyesoftware.blogspace" versionCode="1" versionName="1.0.0" platformBuildVersionName=""
sdkVersion:'18'
targetSdkVersion:'26'
uses-permission: name="android.permission.INTERNET"
uses-permission: name="android.permission.ACCESS_NETWORK_STATE"
uses-permission: name="android.permission.WAKE_LOCK"
uses-permission: name="com.google.android.c2dm.permission.RECEIVE"
uses-permission: name="skyesoftware.blogspace.permission.C2D_MESSAGE"
application: label="" icon=''
feature-group: label=""
  uses-feature: name="android.hardware.faketouch"
  uses-implied-feature: name="android.hardware.faketouch" reason='default feature for all apps'
other-activities
other-receivers
other-services
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--' 'af' 'am' 'ar' 'az' 'az-AZ' 'be' 'be-BY' 'bg' 'bn' 'bn-BD' 'bs' 'bs-BA' 'ca' 'cs' 'da' 'de' 'el' 'en-AU' 'en-GB' 'en-IN' 'es' 'es-US' 'et' 'et-EE' 'eu' 'eu-ES' 'fa' 'fi' 'fr' 'fr-CA' 'gl' 'gl-ES' 'gu' 'gu-IN' 'hi' 'hr' 'hu' 'hy' 'hy-AM' 'in' 'is' 'is-IS' 'it' 'iw' 'ja' 'ka' 'ka-GE' 'kk' 'kk-KZ' 'km' 'km-KH' 'kn' 'kn-IN' 'ko' 'ky' 'ky-KG' 'lo' 'lo-LA' 'lt' 'lv' 'mk' 'mk-MK' 'ml' 'ml-IN' 'mn' 'mn-MN' 'mr' 'mr-IN' 'ms' 'ms-MY' 'my' 'my-MM' 'nb' 'ne' 'ne-NP' 'nl' 'pa' 'pa-IN' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'si' 'si-LK' 'sk' 'sl' 'sq' 'sq-AL' 'sr' 'sr-Latn' 'sv' 'sw' 'ta' 'ta-IN' 'te' 'te-IN' 'th' 'tl' 'tr' 'uk' 'ur' 'ur-PK' 'uz' 'uz-UZ' 'vi' 'zh-CN' 'zh-HK' 'zh-TW' 'zu'
densities: '120' '160' '240' '320' '480' '640' '65534'

Instant App feature APK:

package: name="skyesoftware.blogspace" versionCode="1" versionName="1.0.0" split="blogspace_item_details" platformBuildVersionName=""
sdkVersion:'18'
targetSdkVersion:'26'
uses-permission: name="android.permission.INTERNET"
uses-permission: name="android.permission.ACCESS_NETWORK_STATE"
application: label="" icon=''
feature-group: label=""
  uses-feature: name="android.hardware.faketouch"
  uses-implied-feature: name="android.hardware.faketouch" reason='default feature for all apps'
other-activities
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--'
densities: '160'

As you can see your installable app requests the ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions which implicitly add a requirement of the android.hardware.location feature. In the same way the ACCESS_WIFI_STATE permission implied the android.hardware.wifi feature. A user who don’t have either GPS or WiFi on their device (that sounds odd but such devices exist in the wild) will not be able to upgrade your instant app to the installable one.

One more thing that limits your installable app availability is the android.hardware.screen.portrait feature, which was implied because:

one or more activities have specified a portrait orientation

To fix all those issues and make you installable app available to the all users of the instant app, add the following block to the manifest of your installable app (on the level below the <manifest> tag):

<uses-feature
    android:name="android.hardware.location"
    android:required="false" />

<uses-feature
    android:name="android.hardware.location.network"
    android:required="false" />

<uses-feature
    android:name="android.hardware.location.gps"
    android:required="false" />

<uses-feature
    android:name="android.hardware.wifi"
    android:required="false" />

<uses-feature
    android:name="android.hardware.screen.portrait"
    android:required="false" />

The android.hardware.location.network and android.hardware.location.gps features are there to comply with the following requirement:

If your app targets Android 5.0 (API level 21) or higher and uses the ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in order to receive location updates from the network or a GPS, respectively, you must also explicitly declare that your app uses the android.hardware.location.network or android.hardware.location.gps hardware features.

 
Btw, the other way to figure out what features are required by the installable app is the APK details info screen on the App releases section of the Google Play Console.

Leave a Comment