Google Play Console error - Non-upgradable to installed app

女生的网名这么多〃 提交于 2019-11-27 08:55:48

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.

I followed Idolon's advice (running aapt dump badging MyApp.apk on both apks and comparing) and added several permissions I was missing.

However, I still couldn't get it fully working until I added an OpenGLES feature to match my installed app. In my case:

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

This message makes a perfect sense. Just look at the features required by your installed app(you can use classyshark for that). If it requires phone, because you ask for dialer permissions or you just manually required it, or you ask for GSL version 2 as minimum for your installed versions, then it makes sense that part of the users who doesn't meet those criteria but have android 6+ will not be able to use your installed version but only the instant one.

Looking at your installed app's manifest, and your instant app via the gist in your comment above, you do have an issue with your minSdk. Your installed app has minSdk 18, and your instant app doesn't set a minSdk. Set minSdk 18 on instant app base manifest and see if that takes care of it.

Intuitively, this validator is protecting against a scenario that can't happen: a pre-JB user getting your instant app, and being unable to upgrade to the installed app. Because the instant apps runtime itself doesn't go that far back. The validator is indeed dumb. It's just looking at those minSdk values. But that's probably how we want it to be, since that runtime compatibility is moving steadily back to older devices, and that happens without you republishing. (It's extremely unlikely that we'll ever get as far back as sdk 17. Just preemptively justifying why we wouldn't want to make this validator "smarter".)

Simple answer: It happens if you haven't incremented your version number correctly.

Only those with a "lower" version number can upgrade - those with a higher version number can't upgrade.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!