當我將專案從 Eclipse 遷移至 Android Studio 並將 application 上線後,發現有小部分的使用者無法安裝。
使用者表示在 Google Play 安裝時會跳出錯誤訊息: 代碼 -505

遇到問題可以先思考兩件事:

  1. 該版更新有更改了什麼?其中又有哪部分可能影響到安裝?
  2. 這些使用者有什麼共通點

才發現是 AndroidManifests.xml 中的 applicationId 出了差錯,導致安裝失敗。
接下來將使用「寄包裹」來進行舉例說明:

環境

  • Mac @Mojave
  • Homebrew @2.2.17
  • Android Studio
  • Android SDK 23

前提

如果你還不知道 Android 裡 Provider 的用途,最好先摸懂會比較好理解:
點此
可以把它想像成「發言人」,也就是對外的溝通窗口。

角色

device ☞ 郵局
provider ☞ 包裹
authority ☞ 寄件人

前提

☞ 一個人(authority)只能寄一個包裹(provider)
☞ 郵局認名不認人,若兩人姓名相同會被視為同一人
☞ 先寄先贏
☞ 全台只有一間郵局

故事

「台北 周支支」(authority)來到台中旅行
將要寄給周媽媽的「太陽餅」及「鳳梨酥」分成了兩個包裹(provider)
抵達郵局後「台北 周支支」將太陽餅順利寄出

當「台北 周支支」打算再寄出鳳梨酥時被郵局拒絕(因為一人只能寄一個包裹)
於是鳳梨酥被貼上退件通知(-505)後,退回給「台北 周支支」

接著郵局又來了位「台南 周支支」
打算寄生活費要給爸爸
但因為「周支支」的發送櫃已有太陽餅包裹
所以郵局一樣在生活費貼上了退件通知(-505),退回給「台南 周支支」

狀況

就在「台北 周支支」的太陽餅等待寄出時

【問題一】
周媽媽打來說她不想要太陽餅,比較想吃鳳梨酥,怎麼辦?

【問題二】
「台南 周支支」急著寄生活費給爸爸怎麼辦?

【解答】
「台北 周支支」必須先撤銷他原先的太陽餅

問題

「台南 周支支」很確定自己並沒有寄過任何東西,為什麼郵局會退回包裹?
於是跑到郵局問個清楚
請郵局查詢寄送紀錄(android studio log):

  Can't install because provider
  name com.google.android.gms.measurement.google_measurement_service
  (in package com.test) is already used by com.test2.app

我們可以發現郵局屬於 周支支 的發送櫃已有一個包裹等待被寄出,但寄件者不是「台南 周支支」本人
而是「台北 周支支」更早到郵局寄了包裹
對應到專案裡,已被註冊的 provider 稱為:com.google.android.gms:play-services-gcm

奇怪,郵局真的這麼笨嗎?
那同名同姓的人又該怎麼辦?
「台南 周支支」重新詢問了郵局審核包裹流程,發現其中一段寫著:

  <provider
    tools:replace="android:authorities"
    android:name="com.google.android.gms.measurement.AppMeasurementContentProvider"
    android:authorities="${applicationId}.google_measurement_service"
    android:exported="false" />

果然,流程中有留一手可以略過這種同名同姓的情況。

可以看到在姓名處有個亮點:
android:authorities=”${applicationId}.google_measurement_service”

${applicationId} 可以視為是屬於自己的 id
意指我們可以主動建立屬於自己的 id(例如案例中的台北、台南)
這樣郵局審核寄件人時,就會把 id 加在寄件人名字前

舉例:
id 寫上台南,包裹寄件人就會變成是 台南.支支
如此一來即可處理掉姓名重複的問題

問題又來了,id 要寫在哪呢?
「台南 周支支」檢查包裹紙箱(AndroidManifests.xml)發現上面寫著:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tainan">

奇怪?
台南郵局買的紙箱上,已在 package 上印了「台南」呀,那為何郵局還是不收呢?
立刻前往郵局拿取新的寄送人填寫單(可使用 android studio 建立專案)
才發現原來事有蹊蹺

  defaultConfig {
    applicationId "tainan"
    minSdkVersion 21
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
  }

看出來了嗎?

原來新版寄送單上需要添加 applicationId,但舊版寄送單沒有這一個欄位,難怪郵局不收。

備註

其實目前直接使用郵局給的寄送填寫單(請用 android studio 建立專案)都不會有這個問題
因為 applicationId 預設會被填好
但把程式碼從 eclipse(舊版寄送單)土炮轉到 android studio 時
需要自行添加上這一欄
才不會產生 provider 衝突