Azure DevOps构建Xamarin.Android签名APK安装报无证书错误
Azure DevOps Pipeline构建Xamarin.Android APK签名后安装报INSTALL_PARSE_FAILED_NO_CERTIFICATES问题
问题现象
- 本地通过Visual Studio for Mac、Rider的归档发布功能生成的APK可正常安装运行
- Azure Pipeline完成构建、签名流程后,从构建产物drop目录下载的APK拖拽到安卓模拟器安装失败,报错信息如下:
The APK failed to install. Error: INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed collecting certificates for /data/app/vmdl810687574.tmp/base.apk: Failed to collect certificates from /data/app/vmdl810687574.tmp/base.apk: Attempt to get length of null array
当前使用的Pipeline YAML配置
# Xamarin.Android # Build a Xamarin.Android project. # Add steps that test, sign, and distribute an app, save build artifacts, and more: trigger: - master pool: vmImage: 'macos-latest' variables: buildConfiguration: 'Release' droidOutputDirectory: '$(build.binariesDirectory)/$(buildConfiguration)/Droid' iOSOutputDirectory: '$(build.binariesDirectory)/$(buildConfiguration)/iOS' steps: - task: JavaToolInstaller@0 inputs: versionSpec: '11' jdkArchitectureOption: 'x64' jdkSourceOption: 'PreInstalled' - task: NuGetToolInstaller@1 - task: NuGetCommand@2 inputs: restoreSolution: '**/*.sln' - task: XamarinAndroid@1 inputs: projectFile: '**/*droid*.csproj' outputDirectory: '$(droidOutputDirectory)' configuration: '$(buildConfiguration)' - task: AndroidSigning@3 inputs: apksign: true apkFiles: '**/*.apk' apksignerKeystoreFile: 'GuardianAngel360.keystore' apksignerKeystorePassword: 'XXXX' apksignerKeyPassword: 'XXXX' apksignerKeystoreAlias: 'GuardianAngel360' zipalign: true - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(droidOutputDirectory)' ArtifactName: 'drop' publishLocation: 'Container' - task: DownloadBuildArtifacts@1 inputs: buildType: 'current' downloadType: 'specific' itemPattern: 'GA360-APP-Android' downloadPath: '$(System.ArtifactsDirectory)' - task: Bash@3 inputs: targetType: 'inline' script: | echo '******************ls -Step******************' ls $(droidOutputDirectory) - task: AppCenterDistribute@3 inputs: serverEndpoint: 'ProductionAndroid' appSlug: 'GuardianAngel360/GA360-APP.Android' appFile: '$(droidOutputdirectory)/com.guardianangel360.ga360.apk' buildVersion: '1' symbolsOption: 'Android' releaseNotesOption: 'input' releaseNotesInput: 'Here they are' destinationType: 'groups'
异常线索
- AndroidSigning任务执行日志显示签名校验成功、操作返回Signed状态,对应日志片段:
26474765 META-INF/proguard/androidx-annotations.pro (OK - compressed) 26475012 META-INF/maven/com.google.guava/listenablefuture/pom.xml (OK - compressed) 26476005 META-INF/maven/com.google.guava/listenablefuture/pom.properties (OK - compressed) Verification succesful /Users/runner/Library/Android/sdk/build-tools/32.0.0/apksigner sign --ks /Users/runner/work/_temp/GuardianAngel360.keystore --ks-pass pass:*** --ks-key-alias GuardianAngel360 --key-pass pass:*** --verbose /Users/runner/work/1/s/GeoFenceCandidate/GA360.Android/obj/Release/android/bin/com.guardianangel360.ga360.apk Signed Finishing: AndroidSigning
- 任务执行截图:

根因定位
从签名日志可以明确核心问题:
- 实际被apksigner签名的APK路径是项目
obj/Release/android/bin/中间编译目录下的产物,不是配置的$(droidOutputDirectory)输出目录下的最终发布包 - AndroidSigning任务配置的
apkFiles: '**/*.apk'会递归匹配工作目录下所有APK文件,由于通配符匹配顺序问题,先命中了中间目录的未打包完成的APK执行了签名操作,最终拷贝到drop发布目录的APK没有被签名 - 额外配置错误:AppCenterDistribute任务中引用的变量
$(droidOutputdirectory)存在大小写错误(正确变量名为$(droidOutputDirectory),Directory首字母大写),Azure Pipeline变量大小写敏感,该错误会导致分发步骤找不到APK文件;冗余的DownloadBuildArtifacts任务匹配规则错误,无实际作用。
修复方案
- 修改AndroidSigning任务的APK匹配规则,去掉全目录递归通配,明确指定只签名输出目录下的最终发布包,修改后配置片段:
- task: AndroidSigning@3 inputs: apksign: true apkFiles: '$(droidOutputDirectory)/*.apk' apksignerKeystoreFile: 'GuardianAngel360.keystore' apksignerKeystorePassword: 'XXXX' apksignerKeyPassword: 'XXXX' apksignerKeystoreAlias: 'GuardianAngel360' zipalign: true
- 修正AppCenterDistribute任务中的变量名拼写错误,将
$(droidOutputdirectory)改为$(droidOutputDirectory) - 删除冗余的DownloadBuildArtifacts任务,该任务匹配规则与发布产物名不一致,无实际作用
- 可选加固:在XamarinAndroid@1任务中增加
createAppPackage: true配置,确保构建阶段输出完整的正式发布包,避免生成中间调试包。
内容的提问来源于stack exchange,提问作者Mark Wardell
相关产品推荐
相关产品推荐

