应用内更新报错ERROR_APP_NOT_OWNED,版本号低于Play商店版本
问题描述
我已在Google Play商店发布应用,当前本地版本的versionCode为2405141(versionName 2.1.6),低于商店已发布的版本(versionCode 2405221,versionName 2.1.9)。使用AppUpdateManager实现应用内版本检测与更新时,出现Install Error(-10): ERROR_APP_NOT_OWNED错误,提示应用未被设备上的用户“拥有”(需从Play获取)。
实现代码
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(this); Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo(); appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> { final String log = "packageName :" + appUpdateInfo.packageName() + ", " + "availableVersionCode :" + appUpdateInfo.availableVersionCode() + ", " + "updateAvailability :" + appUpdateInfo.updateAvailability() + ", " + "installStatus :" + appUpdateInfo.installStatus(); FirebaseCrashlytics.getInstance().recordException(new Throwable(log)); if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) { FirebaseCrashlytics.getInstance().recordException(new Throwable("On Updating")); update(); } else { FirebaseCrashlytics.getInstance().recordException(new Throwable("Success but Update Unavailable " + log)); permCheck(); } }); appUpdateInfoTask.addOnFailureListener(e -> { final String log = "Update Failure " + e.getMessage(); final String log2 = "Update Failure " + e.getLocalizedMessage(); FirebaseCrashlytics.getInstance().recordException(new Throwable(log + " " + log2)); permCheck(); });
Gradle配置
android { signingConfigs { release { storeFile file(**) storePassword '**' keyAlias '**' keyPassword '**' } } compileSdk = 34 buildToolsVersion = "30.0.3" flavorDimensions "2.1.6" defaultConfig { applicationId "id.**.android" minSdkVersion 19 targetSdkVersion 34 versionCode 2405141 versionName "2.1.6" multiDexEnabled true vectorDrawables.useSupportLibrary = true testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { manifestPlaceholders = [ activityLabel:"APP NAME NEW"] proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } debug { manifestPlaceholders = [ activityLabel:"APP NAME.Debug"] applicationVariants.all { variant -> variant.outputs.each { output -> def appName = "APP NAME" def fileName = appName + "-v" + defaultConfig.versionName + "-" + variant.buildType.name + ".apk" output.outputFileName = fileName } } } } productFlavors { def addActivityLabelSuffix = { placeholders, suffix -> def appName = placeholders.get("APP NAME") placeholders.put("APP NAME", appName + suffix) } dev { applicationId "APP NAME.dev" ext.betaDistributionGroupAliases = "APP NAME.dev" addActivityLabelSuffix getManifestPlaceholders(), ".Dev" } staging { applicationId "APP NAME.stg" addActivityLabelSuffix getManifestPlaceholders(), ".Staging" } production { applicationId "APP NAME.new" } } compileOptions { sourceCompatibility = 1.8 targetCompatibility = 1.8 } buildFeatures { viewBinding true } namespace 'APPNAME' }
解决方案
1. 确保应用签名与Play商店完全匹配
ERROR_APP_NOT_OWNED的核心原因是本地安装的应用签名与Google Play商店发布的应用签名不一致,Play会判定当前应用不是从商店获取的正版应用:
- 测试时必须安装从Play商店获取的版本(包括正式版、内部测试版、封闭测试版),不能直接安装本地debug签名的APK。
- 核对gradle中
signingConfigs的配置,确认release构建使用的签名文件、密钥别名、密码等信息,与上传到Play商店的签名完全一致。如果使用了Google Play应用签名服务,要确保本地的上传证书与Play后台配置匹配。
2. 验证applicationId一致性
Google Play通过applicationId识别应用,必须保证:
- production flavor的
applicationId与Play商店后台的应用包名完全一致,检查是否存在拼写错误或后缀差异。 - 避免在测试flavor(dev/staging)中测试应用内更新,除非这些flavor的包名也已在Play后台配置为测试应用。
3. 修正flavor维度配置
gradle中flavorDimensions设置为"2.1.6"是不合理的,维度应该是标识环境的字符串(比如"environment"),版本号作为维度会导致构建逻辑混淆,建议修改为:
flavorDimensions "environment"
4. 代码层面补充错误处理
捕获ERROR_APP_NOT_OWNED错误时,引导用户跳转至Play商店手动更新:
appUpdateInfoTask.addOnFailureListener(e -> { if (e instanceof ApiException) { ApiException apiException = (ApiException) e; if (apiException.getStatusCode() == UpdateAvailability.ERROR_APP_NOT_OWNED) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())); startActivity(intent); return; } } // 原有错误日志记录逻辑 final String log = "Update Failure " + e.getMessage(); final String log2 = "Update Failure " + e.getLocalizedMessage(); FirebaseCrashlytics.getInstance().recordException(new Throwable(log + " " + log2)); permCheck(); });
5. 测试账号与环境验证
- 确保测试设备登录的Google账号已被添加到Play商店的测试列表中(如果使用测试渠道)。
- 不要在未登录Google账号的设备上测试应用内更新功能。
内容的提问来源于stack exchange,提问作者Rijal Khalik
相关产品推荐
相关产品推荐

