Utwórz pakiet

Opcje przesyłania

Interfejs Android Over The Air API umożliwia przesyłanie danych pakietu i tworzenie nowego zasobu pakietu. Są to pakiety OTA, które można powiązać z co najmniej 1 konfiguracją, aby aktualizacja była dostarczana na urządzenia.

Udostępniamy plik binarny dla systemów Linux i Windows, który ułatwia wznowienie przesyłania pakietów. Możesz go używać zamiast poniższych protokołów. Jeśli chcesz przeprowadzić ściślejszą integrację, użyj jednego z opisanych poniżej protokołów.

Aby z niego korzystać, musisz najpierw utworzyć konto usługi i uzyskać dla niego plik klucza JSON. Tutaj znajdziesz instrukcję tworzenia konta.
Gdy masz plik binarny i plik klucza, możesz go uruchomić z użyciem opcji wiersza poleceń, aby określić plik klucza, wdrożenie i przesyłany pakiet. Użyj --help, aby wyświetlić wszystkie opcje.

Protokoły przesyłania

Prośby o przesłanie możesz przesyłać na różne sposoby. W nagłówku żądania X-Goog-Upload-Protocol określ używaną metodę.

  • Przesyłanie wieloczęściowe: X-Goog-Upload-Protocol: multipart Aby szybko przesyłać mniejsze pliki i metadane, prześlij plik wraz z opisującymi go metadanymi – wszystko w ramach jednego żądania.
  • Wznawianie przesyłania: X-Goog-Upload-Protocol: resumable. Zapewnia niezawodny transfer danych, co jest szczególnie ważne w przypadku większych plików. Ta metoda używa żądania inicjowania sesji, które opcjonalnie może zawierać metadane. Jest to odpowiednia strategia dla większości aplikacji, ponieważ sprawdza się również w przypadku mniejszych plików i kosztuje 1 dodatkowe żądanie HTTP na przesłanie.

Przesyłanie wieloczęściowe

Jest to dobry wybór, jeśli wysyłane dane są wystarczająco małe, aby można było ponownie przesłać je w całości, jeśli połączenie się nie powiedzie.

Aby korzystać z przesyłania wieloczęściowego, wyślij żądanie POST do identyfikatora URI /upload/package i ustaw X-Goog-Upload-Protocol na multipart.

Nagłówki HTTP najwyższego poziomu, których należy używać podczas tworzenia żądania przesyłania wieloczęściowego, to:

  • Content-Type. Ustaw jako wieloczęściowy/powiązany i uwzględnij ciąg granicy używany do identyfikowania części żądania.
  • Content-Length. Ustaw łączną liczbę bajtów w treści żądania.

Treść żądania ma format multipart/related [RFC2387] i zawiera dokładnie 2 części. Części są określane ciągiem określającym granice, a na końcu końcowego ciągu granicznego znajdują się 2 łączniki.

Każda część żądania wieloczęściowego wymaga dodatkowego nagłówka Content-Type:

  1. Część metadanych: musi być na pierwszym miejscu, a Content-Type musi mieć wartość application/json.
  2. Część multimediów: musi być na drugiej pozycji, a Content-Type musi mieć wartość application/zip.

Przykład: przesyłanie wieloczęściowe

Przykład poniżej przedstawia wieloczęściowe żądanie przesyłania w przypadku interfejsu 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--

Jeśli żądanie zostanie zrealizowane, serwer zwraca kod stanu HTTP 200 OK.

HTTP/1.1 200

Możesz to łatwo zrobić za pomocą narzędzi curl i oauth2l. Poniżej znajdziesz przykładowe żądanie, w którym założono, że używasz klucza usługi (więcej informacji znajdziesz w artykule o autoryzacji).

Przykładowe żądanie 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
  

Przesyłanie z możliwością wznowienia

Aby zwiększyć niezawodność przesyłania plików danych, możesz użyć protokołu przesyłania wznawiania. Protokół ten umożliwia wznowienie operacji przesyłania, gdy przepływ danych zostanie przerwany przez błąd komunikacji. Jest to szczególnie przydatne, jeśli przesyłasz duże pliki, w przypadku których prawdopodobieństwo przerw w działaniu sieci lub innych awarii transmisji jest wysokie, np. podczas przesyłania z aplikacji mobilnej. Może też zmniejszyć wykorzystanie przepustowości w przypadku awarii sieci, ponieważ nie trzeba ponownie uruchamiać dużych plików.

Protokół przesyłania możliwego do wznowienia używa kilku poleceń:

  1. Rozpocznij sesję, którą można wznowić. Wyślij wstępne żądanie do identyfikatora URI przesyłania, które zawiera metadane i określa unikalną lokalizację przesyłania, którą można wznowić.
  2. Zapisz identyfikator URI sesji możliwej do wznowienia. Zapisz identyfikator URI sesji zwrócony w odpowiedzi na pierwsze żądanie. Będziesz go używać w pozostałych żądaniach w tej sesji.
  3. Prześlij plik. Wyślij całość lub część pliku ZIP do identyfikatora URI sesji możliwej do wznowienia.

Oprócz tego aplikacje, które używają przesyłania z możliwością wznowienia, muszą mieć kod umożliwiający wznowienie przerwanego przesyłania. Jeśli przesyłanie zostanie przerwane, sprawdź, ile danych zostało otrzymanych, a następnie wznów przesyłanie, zaczynając od tego momentu.

Uwaga: identyfikator URI przesyłania wygasa po 3 dniach.

Krok 1. Rozpocznij sesję z możliwością wznowienia

Aby zainicjować wznowienie przesyłania, wyślij żądanie POST do identyfikatora URI /upload/package i ustaw X-Goog-Upload-Protocol na resumable.

Na potrzeby zainicjowania żądania treść musi zawierać tylko metadane. W kolejnych żądaniach przesyłasz rzeczywistą zawartość pliku, który chcesz przesłać.

W początkowym żądaniu użyj tych nagłówków HTTP:

  • X-Goog-Upload-Header-Content-Type. Jest to typ treści przesyłanego pliku i musi być ustawiony na application/zip.
  • X-Goog-Upload-Command. Ustaw na start
  • X-Goog-Upload-Header-Content-Length. Ustaw liczbę bajtów przesyłanych danych, które mają być przesyłane w kolejnych żądaniach. Jeśli w momencie przesyłania żądania długość jest nieznana, możesz pominąć ten nagłówek.
  • Content-Type. To typ treści metadanych, który należy ustawić na application/json.
  • Content-Length. Ustaw liczbę bajtów w treści tego początkowego żądania.
Przykład: żądanie zainicjowania sesji możliwe do wznowienia

Z przykładu poniżej dowiesz się, jak zainicjować sesję wznawianą dla interfejsu 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" }

Następna sekcja zawiera informacje na temat postępowania z odpowiedzią.

Krok 2. Zapisz identyfikator URI sesji możliwej do wznowienia

Jeśli żądanie inicjowania sesji się powiedzie, serwer interfejsu API w odpowiedzi wyświetli kod stanu HTTP 200 OK. Dodatkowo zawiera nagłówek X-Goog-Upload-URL, który określa identyfikator URI sesji, który można wznowić. Nagłówek X-Goog-Upload-URL, widoczny w przykładzie poniżej, zawiera fragment parametru zapytania upload_id, który podaje unikalny identyfikator przesyłania używany w tej sesji. Odpowiedź zawiera też nagłówek X-Goog-Upload-Status, który zawiera wartość active, jeśli żądanie przesyłania było prawidłowe i zaakceptowane. Jeśli przesyłanie zostało odrzucone, ten stan może wynosić final.

Przykład: odpowiedź na rozpoczęcie sesji z możliwością wznowienia

Oto odpowiedź na prośbę z kroku 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

Wartość nagłówka X-Goog-Upload-URL, jak widać w przykładowej powyżej odpowiedzi, to identyfikator URI sesji, którego będziesz używać jako punktu końcowego HTTP podczas rzeczywistego przesyłania pliku lub wysyłania zapytań dotyczących stanu przesyłania.

Skopiuj i zapisz identyfikator URI sesji, aby móc go używać w kolejnych żądaniach.

Krok 3: prześlij plik

Aby przesłać plik, wyślij żądanie POST na identyfikator URI przesyłania uzyskany w poprzednim kroku. Takie żądanie ma format:

POST session_uri

Nagłówki HTTP używane przy tworzeniu żądań wznowienia przesyłania plików obejmują:

  1. Content-Length. Ustaw tę wartość na liczbę bajtów przesyłanych w ramach tego żądania – zwykle jest to rozmiar przesyłanego pliku.
  2. X-Goog-Upload-Command. Ustaw wartość upload i finalize.
  3. X-Goog-Upload-Offset. Określono przesunięcie, przy którym mają być zapisywane bajty. Pamiętaj, że klienty muszą przesyłać bajty szeregowo.
Przykład: prośba o wznawianie przesłania pliku

Oto możliwe do wznowienia żądanie przesłania całego pliku ZIP o pojemności 2 000 000 bajtów z bieżącego przykładu.

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

Jeśli żądanie się powiedzie, serwer w odpowiedzi wysyła żądanie HTTP 200 Ok.

Jeśli żądanie przesyłania zostało przerwane lub otrzymasz z serwera odpowiedź HTTP 503 Service Unavailable lub inną odpowiedź 5xx, wykonaj czynności opisane w sekcji Wznawianie przerwanego przesyłania.


Przesyłanie pliku partiami

Przesyłanie z możliwością wznowienia pozwala podzielić plik na fragmenty i wysłać serię żądań o przesłanie poszczególnych fragmentów. Nie jest to preferowane podejście, ponieważ dodatkowe żądania wiążą się z kosztami wydajności i zasadniczo nie są potrzebne. Zalecamy, aby klienty przesyłały wszystkie pozostałe bajty ładunku i dołączali polecenie finalize do każdego polecenia upload.

Może być jednak konieczne użycie podziału na fragmenty, aby zmniejszyć ilość danych przesyłanych w jednym żądaniu. Pozwala też na przykład wyświetlać wskaźniki postępu przesyłania w starszych przeglądarkach, które domyślnie nie obsługują tego procesu.


Wznawianie przerwanego przesyłania

Jeśli żądanie przesyłania zostanie zakończone przed otrzymaniem odpowiedzi lub jeśli otrzymasz z serwera odpowiedź HTTP 503 Service Unavailable, musisz wznowić przerwane przesyłanie. Aby to zrobić:

  1. Stan żądania. Sprawdź bieżący stan przesyłania, wysyłając żądanie do identyfikatora URI przesyłania z parametrem X-Goog-Upload-Command ustawionym na query.

    Uwaga: możesz poprosić o stan między poszczególnymi fragmentami, nie tylko wtedy, gdy przesyłanie zostało przerwane. Jest to przydatne na przykład wtedy, gdy chcesz wyświetlać wskaźniki postępu przesyłania w starszych przeglądarkach.

  2. Sprawdzanie liczby przesłanych bajtów. Przetwarzanie odpowiedzi z zapytania o stan. Serwer w odpowiedzi używa nagłówka X-Goog-Upload-Size-Received, aby określić, ile bajtów otrzymał do tej pory.
  3. Prześlij pozostałe dane. Teraz, gdy wiesz już, gdzie wznowić żądanie, wyślij pozostałe dane lub bieżący fragment. Pamiętaj, że w obu przypadkach pozostałe dane musisz traktować jako osobny fragment, więc po wznowieniu przesyłania musisz ustawić odpowiednie przesunięcie nagłówka X-Goog-Upload-Offset.
Przykład: wznawianie przerwanego przesyłania

1) Poproś o stan przesyłania.

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

Tak jak w przypadku wszystkich poleceń, klient musi sprawdzić nagłówek X-Goog-Upload-Status w odpowiedzi HTTP polecenia zapytania. Jeśli nagłówek jest obecny, a jego wartość nie jest ustawiona na active, przesyłanie zostało już zakończone.

2) Wyodrębnij liczbę bajtów przesłanych do tej pory z odpowiedzi.

Odpowiedź serwera używa nagłówka X-Goog-Upload-Size-Received do wskazania, że odebrał pierwsze 43 bajty pliku.

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

3) Wznów przesyłanie od miejsca, w którym zostało przerwane.

To żądanie wznowi przesyłanie, wysyłając pozostałe bajty pliku (począwszy od 43 bajtów).

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

Sprawdzone metody

Podczas przesyłania multimediów warto znać sprawdzone metody postępowania z błędami.

  • Wznów lub ponów próbę przesyłania, jeśli nie uda się je przesłać z powodu przerw w połączeniu lub błędów 5xx, w tym:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Użyj strategii wykładniczego ponowienia, jeśli podczas wznawiania lub ponawiania żądań przesłania zwracany jest dowolny błąd serwera 5xx. Te błędy mogą wystąpić, gdy serwer jest przeciążony. Wykładnicze opóźnienie może pomóc złagodzić tego typu problemy w okresach dużej liczby żądań lub dużego ruchu w sieci.
  • Żądania innych rodzajów nie powinny być obsługiwane przez wykładniczy okres ponowienia, ale nadal można ponawiać próby wykonania kilku z nich. Ogranicz liczbę ponownych prób. Kod może na przykład ograniczyć do 10 ponownych prób przed zgłoszeniem błędu.
  • Podczas wznawiania przesyłania możesz naprawić błędy 404 Not Found, rozpoczynając cały proces od początku.

Wykładniczy czas ponowienia

Wykładniczy czas ponowienia to standardowa strategia obsługi błędów w aplikacjach sieciowych, w której klient przez dłuższy czas ponawia próbę nieudanego żądania. Jeśli duża liczba żądań lub duży ruch w sieci powoduje, że serwer zwraca błędy, dobrym rozwiązaniem w przypadku tych błędów może być wykładnicze ponawianie. Nie sprawdza się natomiast w przypadku błędów niezwiązanych z liczbą sieci lub czasem odpowiedzi, takich jak nieprawidłowe dane uwierzytelniające lub błędy „Nie znaleziono pliku”.

Poprawne wykorzystanie wykładniczego ponowienia zwiększa wydajność wykorzystania przepustowości, zmniejsza liczbę żądań wymaganych do uzyskania pomyślnej odpowiedzi i maksymalizuje przepustowość żądań w środowiskach równoczesnych.

Proces implementacji prostego wykładniczego ponowienia jest następujący:

  1. Wyślij żądanie do interfejsu API.
  2. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  3. Zaczekaj 1 sekundę + random_number_milliseconds i spróbuj ponownie.
  4. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  5. Zaczekaj 2 sekundy + random_number_milliseconds i spróbuj ponownie wysłać żądanie.
  6. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  7. Zaczekaj 4 sekundy + random_number_milliseconds i spróbuj ponownie.
  8. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  9. Zaczekaj 8 sekund + random_number_milliseconds i spróbuj ponownie.
  10. Otrzymasz odpowiedź HTTP 503, co oznacza, że musisz ponowić żądanie.
  11. Zaczekaj 16 sekund + random_number_milliseconds i spróbuj ponownie.
  12. Zatrzymaj. Zgłoś lub zarejestruj błąd.

W powyższym procesie random_number_milliseconds to losowa liczba milisekund mniejszą lub równą 1000. Jest to konieczne, ponieważ wprowadzenie niewielkiego opóźnienia losowego pomaga bardziej równomiernie rozłożyć obciążenie i uniknąć możliwości oznaczenia serwera. Wartość random_number_milliseconds musi być ponownie zdefiniowana po każdym oczekiwaniu.

Uwaga: czas oczekiwania zawsze wynosi (2 ^ n) + losowa_liczba_milisekund, gdzie n to monotonicznie rosnąca liczba całkowita zdefiniowana jako 0. Liczba całkowita n zwiększa się o 1 przy każdej iteracji (każdym żądaniu).

Algorytm kończy działanie, gdy wartość n wynosi 5. Ten limit zapobiega nieskończonemu ponawianiu prób klientów i powoduje całkowite opóźnienie (około 32 sekundy) przed uznaniem żądania za „nieodwracalny błąd”. Można użyć większej liczby ponownych prób, zwłaszcza jeśli trwa przesyłanie długiego czasu. Pamiętaj tylko, by ustawić rozsądną wartość opóźnienia na mniej niż minutę.