建立套件

上傳選項

Android Over The Air API 可讓你上傳套件資料來建立新的套件資源。這些 OTA 套件可與一或多項設定建立關聯,以便將更新推送到裝置。

我們為 Linux 和 Windows 提供二進位檔,方便您免費使用支援續傳的套件,而非實作以下所述的通訊協定。如要進行更深入的整合,請使用下方說明的其中一個通訊協定。

如要使用,您必須先建立服務帳戶,並取得該帳戶的 JSON 金鑰檔案。請參閱這裡建立帳戶指南。
取得二進位檔和金鑰檔案後,您就可以使用指令列選項執行該檔案,指定金鑰檔案、部署作業和您要上傳的套件。如要查看所有選項,請使用 --help

上傳通訊協定

您可以透過下列任一方式提出上傳要求。 利用 X-Goog-Upload-Protocol 要求標頭指定您要使用的方法。

  • 多部分上傳作業X-Goog-Upload-Protocol: multipart。適合快速傳輸小型檔案和中繼資料;傳輸檔案以及描述該檔案的中繼資料,所有作業都在單一要求中完成。
  • 支援續傳的上傳作業X-Goog-Upload-Protocol: resumable。可靠的傳輸作業,對於大型檔案特別重要。透過這個方法,您可以使用工作階段啟動要求,其中可以選擇是否包含中繼資料。對於大多數應用程式來說,這也是一種不錯的策略,因為這也適用於較小的檔案,因為每次上傳額外收取一次 HTTP 要求的費用。

多部分上傳

如果您要傳送的資料小到足以在連線失敗時重新完整上傳,這會是一個理想的選擇。

如要使用多部分上傳作業,請向 /upload/package URI 發出 POST 要求,並將 X-Goog-Upload-Protocol 設為 multipart

提出多部分上傳要求時,要使用的頂層 HTTP 標頭包括:

  • Content-Type:請設定為 multipart/related,並加入辨識各個要求部分使用的邊界字串。
  • Content-Length:請設定為要求主體中的位元組總數。

要求主體的格式為 multipart/related 內容類型 [RFC2387],且包含兩個部分。這些部分是靠邊界字串來辨識的,而緊接在最後一個邊界字串後面會有兩個連字號。

多部分要求的每個部分都需要一個額外的 Content-Type 標頭:

  1. 中繼資料部分:您必須先撰寫這個部分,且 Content-Type 必須是 application/json
  2. 媒體部分:必須是第二次,Content-Type必須是 application/zip

範例:多部分上傳作業

以下範例顯示 Android Over The Air API 的多部分上傳要求。

POST /upload/package HTTP/1.1
Host: androidovertheair.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=BOUNDARY
Content-Length: number_of_bytes_in_entire_request_body

--BOUNDARY
Content-Type: application/json; charset=UTF-8

{"deployment": "id", "package_title": "title" }
--BOUNDARY
Content-Type: application/zip; charset=UTF-8

Package ZIP
--BOUNDARY--

如果要求成功,伺服器會傳回 HTTP 200 OK 狀態碼

HTTP/1.1 200

這時最簡單的方法就是使用 curloauth2l。以下是範例要求範例,假設您使用的是服務金鑰 (詳情請參閱我們的授權方式)。

curl 要求範例
    JSON={"deployment": "id", "package_title": "title" }
    SERVICE_KEY_FILE=path to your service key json file
    curl \
    -H "$(./oauth2l header --json $SERVICE_KEY_FILE android_partner_over_the_air)" \
    -H "Host: androidovertheair.googleapis.com" \
    -H "X-Goog-Upload-Protocol: multipart" \
    -H "Content-Type: multipart/form-data" \
    -F "json=$JSON;type=application/json" \
    -F "data=@update.zip;type=application/zip" \
    androidovertheair.googleapis.com/upload/package
  

支援續傳的上傳作業

如要更可靠地上傳資料檔案,可以使用支援續傳的上傳通訊協定。此通訊協定可讓您在通訊問題導致上傳作業的資料傳輸過程中斷之後,能夠繼續執行上傳作業。如果您要傳輸大型檔案,而且發生網路中斷或其他傳輸問題的可能性很高 (例如從行動裝置用戶端應用程式上傳時),這種方法就特別有用。這方法也能在網路發生問題時降低頻寬用量,因為您不需要從頭開始上傳大型檔案。

支援續傳的上傳通訊協定會使用多個指令:

  1. 啟動可續傳的工作階段。對包含中繼資料的上傳 URI 發出初始要求,並建立可續傳的上傳位置。
  2. 儲存可續傳工作階段 URI。儲存初始要求回應中傳回的工作階段 URI,這將用於這個工作階段的其餘要求。
  3. 上傳檔案。將 ZIP 檔案的所有或部分資料傳送至可續傳的工作階段 URI。

此外,使用可續傳上傳功能的應用程式,必須擁有繼續執行中斷的上傳作業小節中的程式碼。如果上傳作業中斷,請找出已成功接收多少資料,然後從那一點開始續傳。

注意: 上傳 URI 會在 3 天後失效。

步驟 1:啟動可續傳的工作階段

如要啟動支援續傳的上傳作業,請向 /upload/package URI 發出 POST 要求,並將 X-Goog-Upload-Protocol 設為 resumable

這個初始要求的主體只能包含中繼資料;您將在後續的要求中,傳輸您要上傳檔案的實際內容。

請搭配初始要求使用下列 HTTP 標頭:

  • X-Goog-Upload-Header-Content-Type。這是正在上傳檔案的內容類型,必須設為 application/zip
  • X-Goog-Upload-Command。設為 start
  • X-Goog-Upload-Header-Content-Length:請設定為要在後續要求中傳輸的上傳資料位元組數。如果提出這項要求時無法得知長度,您可以省略這個標頭。
  • Content-Type。這是中繼資料的內容類型,必須設為 application/json
  • Content-Length:請設定為這個初始要求的主體中提供的位元組數。
範例:可續傳工作階段啟動要求

以下範例說明如何為 Android Over The Air API 啟動可續傳的工作階段。

POST /upload/package HTTP/1.1
Host: android/over-the-air.googleapis.com
Authorization: Bearer your_auth_token
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Goog-Upload-Command: start
X-Goog-Upload-Header-Content-Type: application/zip
X-Goog-Upload-Header-Content-Length: 2000000

{"deployment": "id", "package_title": "title" }

下一節將說明如何處理回應。

步驟 2:儲存可續傳的工作階段 URI

如果工作階段啟動要求成功,API 伺服器就會傳回 HTTP 200 OK 狀態碼。此外,API 還提供 X-Goog-Upload-URL 標頭,用於指定可續傳工作階段 URI。如以下範例所示,X-Goog-Upload-URL 標頭包含 upload_id 查詢參數,可提供這個工作階段所用的專屬上傳 ID。回應中還包含 X-Goog-Upload-Status 標頭,如果上傳要求有效且已接受,則為 active。如果上傳作業遭拒,可能是 final 狀態。

範例:可續傳工作階段啟動作業的回應

以下是步驟 1 中要求的回應:

HTTP/1.1 200 OK
X-Goog-Upload-Status: active
X-Goog-Upload-URL: androidovertheair.googleapis.com/?upload_id=xa298sd_sdlkj2
Content-Length: 0

如以上回應範例所示,X-Goog-Upload-URL 標頭的值,就是您將做為 HTTP 端點的工作階段 URI,且這個 HTTP 端點將用於執行實際檔案上傳作業或查詢上傳狀態。

請複製並儲存工作階段 URI,好讓您能夠在後續的要求中使用。

步驟 3:上傳檔案

如要上傳檔案,請傳送 POST 要求至您在上一個步驟中取得的上傳 URI。上傳要求的格式如下:

POST session_uri

提出續傳檔案上傳要求時,要使用的 HTTP 標頭包括:

  1. Content-Length。請將這個欄位設為您要在這個要求中上傳的位元組數,這通常是上傳檔案大小。
  2. X-Goog-Upload-Command。請設為 uploadfinalize
  3. X-Goog-Upload-Offset:指定應寫入位元組的偏移值。請注意,用戶端必須依序上傳位元組。
範例:可續傳檔案上傳要求

以下是在目前範例中,上傳整個 2,000,000 位元組 ZIP 檔案的續傳要求。

POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1
Host: androidovertheair.googleapis.com
X-Goog-Upload-Protocol: resumable
X-Goog-Upload-Command: upload, finalize
X-Goog-Upload-Offset: 0
Content-Length: 2000000
Content-Type: application/zip

bytes 0-1999999

如果要求成功,伺服器會回應 HTTP 200 Ok

如果上傳要求中斷,或是您從伺服器收到 HTTP 503 Service Unavailable 或任何其他的 5xx 回應,請按照「繼續執行中斷的上傳作業」一文所述的程序進行。


將檔案以區塊的形式上傳

透過續傳上傳作業,您可將檔案切割為片段,然後傳送一系列要求來依序上傳每個片段。我們不建議您這麼做,因為必須承擔與額外的要求相關聯的效能成本,而且通常不需要此步驟。我們建議用戶端上傳酬載的所有剩餘位元組,並為每個 upload 指令加入 finalize 指令。

然而,您可能需要使用區塊化功能,減少在任何單一要求中傳輸的資料量。還可以讓您執行其他操作,例如讓預設不支援上傳進度的舊版瀏覽器顯示上傳進度。


繼續執行中斷的上傳作業

如果上傳要求在收到回應之前終止,或是您從伺服器收到 HTTP 503 Service Unavailable 回應,則必須繼續執行中斷的上傳作業。步驟如下:

  1. 要求狀態:X-Goog-Upload-Command 設為 query 的上傳 URI 發出要求,查詢上傳作業的目前狀態。

    附註:您可以在不同區塊的上傳作業之間提出狀態要求,而不是只能在上傳中斷時提出要求。舉例來說,如果要讓舊版瀏覽器顯示上傳進度指示,這項功能就能派上用場。

  2. 取得已上傳的位元組數:請處理狀態查詢的回應。伺服器會在自己的回應中使用 X-Goog-Upload-Size-Received 標頭,指定當下已接收到多少位元組。
  3. 上傳剩餘的資料:最後,既然您已經知道要從哪裡繼續要求,請傳送剩餘的資料或目前的區塊。請注意,無論如何,您都必須要把剩餘的資料當做單獨的區塊來處理,因此您必須在繼續執行上傳作業時,將 X-Goog-Upload-Offset 標頭設為適當的偏移值。
範例:繼續執行中斷的上傳作業

1) 要求上傳狀態。

POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1
Host: androidovertheair.googleapis.com
X-Goog-Upload-Command: query

如同所有指令,用戶端必須檢查查詢指令 HTTP 回應中的 X-Goog-Upload-Status 標頭。 如果標頭存在,且值不是 active,表示上傳作業已經終止。

2) 從回應擷取當下已經上傳的位元組數。

伺服器的回應會使用 X-Goog-Upload-Size-Received 標頭,指出伺服器當下已經收到檔案的前 43 個位元組。

HTTP/1.1 200 OK
X-Goog-Upload-Status: active
X-Goog-Upload-Size-Received: 42

3) 從上次離開的位置續傳上傳作業。

以下要求透過傳送檔案的剩餘位元組 (從位元組 43 開始) 續傳上傳作業。

POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1
Host: androidovertheair.googleapis.com
X-Goog-Upload-Command: upload, finalize
Content-Length: 1999957
X-Goog-Upload-Offset: 43

bytes 43-1999999

最佳做法

當您要上傳媒體時,瞭解幾個與錯誤處理相關的最佳做法是很有用的。

  • 請繼續或重新執行因連線中斷或因任何 5xx 錯誤導致失敗的上傳作業,這些錯誤包括:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • 如果您在繼續或重試上傳要求時,收到任何 5xx 伺服器錯誤,請使用指數輪詢策略。如果伺服器超載,就可能發生這些錯誤。在發生大量要求或存在繁重網路流量期間,指數輪詢可協助減輕這一類問題。
  • 其他類型的要求不應透過指數輪詢來處理,但您仍可重試其中一些要求。重試這些要求時,請限制重試的次數。舉例來說,程式碼可能會限制為重試次數最多 10 次,然後才會回報錯誤。
  • 執行支援續傳的上傳作業時,請從從頭開始完整的上傳作業,以處理 404 Not Found 錯誤。

指數輪詢

指數輪詢是網路應用程式的標準錯誤處理策略,用戶端可透過這種策略,以逐漸增加的次數定期重試失敗的要求。如果大量要求或繁重的網路流量導致伺服器傳回錯誤,指數輪詢就是處理這類錯誤的一種不錯的策略。相反地,處理與網路流量或回應時間相關的錯誤 (例如授權憑證無效或找不到檔案的錯誤) 並不是很有意義的策略。

在正確的使用之下,指數輪詢可以提升頻寬使用的效率,減少取得成功回應所需的要求數,並最大化並行環境中的要求總處理量。

實作簡單指數輪詢的流程如下:

  1. 對 API 提出要求。
  2. 收到指出您應該要重試要求的 HTTP 503 回應。
  3. 等待 1 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  4. 收到指出您應該要重試要求的 HTTP 503 回應。
  5. 等待 2 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  6. 收到指出您應該要重試要求的 HTTP 503 回應。
  7. 等待 4 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  8. 收到指出您應該要重試要求的 HTTP 503 回應。
  9. 等待 8 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  10. 收到指出您應該要重試要求的 HTTP 503 回應。
  11. 等待 16 秒鐘 + random_number_milliseconds 毫秒,然後重試要求。
  12. 停止。報告或記錄錯誤。

在以上流程中,random_number_milliseconds 是小於或等於 1000 的隨機毫秒數。這是必要的,因為使用較小的隨機延遲有助於更平均地分散負載,並避免對伺服器產生衝擊的可能性。必須在每次等待之後重新定義 random_number_milliseconds 的值。

注意:等待時間一律是 (2 ^ n) + random_number_milliseconds,其中 n 是一開始定義為 0 的單調遞增整數。對於每個疊代 (每次要求),整數 n 會遞增 1。

演算法已設定為會在 n 等於 5 時終止。這個上限可以防止用戶端一直重試下去,導致要求在總延遲時間達到約 32 秒之後,才會被視為「無法復原的錯誤」。您可以把重試次數的上限設高一點,尤其是在大型上傳作業執行的過程中;但請確保要把重試延遲時間的上限設定在合理的地方,例如短於一分鐘。