Google Play Console错误 - 无法升级到已安装的应用

时间:2017-08-31 07:02:54

标签: android android-instant-apps google-play-console

我基于谷歌教程和样本开发了一个即时应用程序apk。当我尝试开始生产时,我看到一个错误: 不可升级到已安装的应用

问题

此即时应用APK的某些用户将无法使用您已安装的应用中的任何APK。

解决方案

确保您的即时应用APK定位与您的APK定位相匹配。

项目结构: 有两种情况,第一种:

base - baseFeature,minSdk 18,targetSdk 26

application project(':apk')
feature project(':item-details')

项目详细信息功能 - minSdk 18,targetSdk 26

api project(':base')

ui - 即时模块中未包含的功能,minSdk 18,targetSdk 26,模块包含所有视图

implementation project(':base')
other modules like customcomponents, shared etc

即时 - 即时应用模块minSdk 18或23,targetSdk 26

implementation project(':base')
implementation project(':item-details')

apk - apk模块,minSdk 18,targetSdk 26

implementation project(':ui')
implementation project(':shared')

第二个场景在baseFeature中有项目详细信息代码。

即时应用程序正在从Android Studio和Google Play开发和预发布中运行。此外,当我尝试升级到已安装的应用程序时,一切正常。 在我看来,定位是正确的,但谷歌Play控制台的思维方式不同。

您是否知道如何推出即时应用?请帮忙 :( 我已经在这个版本上工作了3天,我无法推出应用程序。

更新10.09.2017 APK详细信息:

Supported Android devices 8448 devices 
API levels 18+ 
Target SDK 26 
Screen layouts 4 screen layouts 
Localizations default + 113 languages 
Features 2 features 
Required permissions 12 permissions 
OpenGL ES versions 1.0+ 
OpenGL textures all textures 
Uploaded Sep 9, 2017, 7:57:11 AM PDT 

5 个答案:

答案 0 :(得分:7)

根据Android documentation

  

您可以使用Android SDK中包含的aapt工具,根据其声明的功能和权限,确定Google Play将如何过滤您的应用。为此,请使用aapt命令运行dump badging。这会导致 aapt 解析您的应用程序的清单,并应用与Google Play使用的相同规则来确定您的应用程序所需的功能。

通过在可安装和即时应用程序上运行该命令,可以打印以下信息。

可安装应用(版本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'

即时应用基础功能:

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'

即时应用功能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'

正如您所看到的,您的可安装应用请求ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION android.hardware.location ACCESS_WIFI_STATE功能的android.hardware.wifi权限。以同样的方式android.hardware.screen.portrait权限暗示了<manifest>功能。在他们的设备上没有GPS或WiFi的用户(听起来很奇怪,但这些设备在野外存在)将无法将您的即时应用升级到可安装的应用程序。

限制您的可安装应用可用性的另一个因素是<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" /> 功能,暗示是因为:

  

一项或多项活动指定了纵向方向

要修复所有这些问题并让即时应用的所有用户都可以使用可安装应用,请将以下块添加到可安装应用的清单中(位于android.hardware.location.network标记下方的级别):

android.hardware.location.gps

ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION功能符合以下implicitly add a requirement

  

如果您的应用定位到Android 5.0(API级别21)或更高级别,并使用android.hardware.location.networkandroid.hardware.location.gps权限分别从网络或GPS接收位置更新,您还必须明确声明您的应用使用// cc -g -Wall ntime.c -o ntime -lrt #include <inttypes.h> #include <stdint.h> #include <stdio.h> #include <time.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char* argv[]) { struct timespec spec; printf("CLOCK_REALTIME - \"Systemwide realtime clock.\":\n"); clock_getres(CLOCK_REALTIME, &spec); printf("\tprecision: %ldns\n", spec.tv_nsec); clock_gettime(CLOCK_REALTIME, &spec); printf("\tvalue : %010ld.%-ld\n", spec.tv_sec, spec.tv_nsec); printf("CLOCK_MONOTONIC - \"Represents monotonic time. Cannot be set.\":\n"); clock_getres(CLOCK_MONOTONIC, &spec); printf("\tprecision: %ldns\n", spec.tv_nsec); clock_gettime(CLOCK_MONOTONIC, &spec); printf("\tvalue : %010ld.%-ld\n", spec.tv_sec, spec.tv_nsec); return 0; } CLOCK_REALTIME - "Systemwide realtime clock.": precision: 999848ns value : 1504781052.328111000 CLOCK_MONOTONIC - "Represents monotonic time. Cannot be set.": precision: 999848ns value : 0026159205.299686941 硬件功能。


顺便说一句,另一种了解可安装应用所需功能的方法是Google Play控制台的应用发布部分的requirement信息屏幕。

答案 1 :(得分:2)

我遵循了Idolon的建议(在apks和比较上运行aapt dump badging MyApp.apk)并添加了我缺少的几个权限。

但是,在我添加OpenGLES功能以匹配我安装的应用程序之前,我仍然无法完全正常工作。就我而言:

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

答案 2 :(得分:0)

此消息非常有意义。只需查看已安装应用程序所需的功能(您可以使用classyshark)。如果它需要电话,因为您要求拨号器权限或者您只是手动需要它,或者您要求GSL版本2作为已安装版本的最低要求,那么部分不符合这些条件的用户是有道理的但安卓6+将无法使用您安装的版本,只能使用即时版本。

答案 3 :(得分:0)

通过上述评论中的要点查看已安装的应用清单以及您的即时应用,您的minSdk确实存在问题。您安装的应用程序的minSdk为18,而您的即时应用程序未设置minSdk。在即时应用程序基础清单上设置minSdk 18,看看是否可以处理它。

直观地说,这个验证器可以防止不可能发生的情况:前JB用户获取您的即时应用程序,并且无法升级到已安装的应用程序。因为即时应用程序运行时本身并没有那么久。验证者确实很愚蠢。它只是看着那些minSdk值。但这可能就是我们想要它的方式,因为运行时兼容性正稳步回到旧设备,而这种情况在没有您重新发布的情况下发生。 (我们不太可能像sdk那样回到17岁。只是先发制人地证明为什么我们不想让这个验证器更“聪明”。)

答案 4 :(得分:0)

简单回答: 如果您没有正确增加版本号,就会发生这种情况。

只有那些&#34;更低&#34;版本号可以升级 - 具有更高版本号的版本号无法升级。