Android Things oraz Raspberry Pi 3 (3)

Podobne dokumenty
Aktualizacja modemu LTE Speed 1000

Zaawansowane aplikacje WWW - laboratorium

Wdrożenie modułu płatności eservice. dla systemu Zen Cart

Narzędzia i aplikacje Java EE. Usługi sieciowe Paweł Czarnul pczarnul@eti.pg.gda.pl

Wdrożenie modułu płatności eservice. dla systemu oscommerce 2.3.x

Fragmenty są wspierane od Androida 1.6

Synchronizator plików (SSC) - dokumentacja

Wprowadzenie do projektu QualitySpy

Tworzenie i wykorzystanie usług

Przewodnik dla użytkownika. Instrukcja korzystania z aplikacji mobilnej mtoken Asseco MAA

Currenda EPO Instrukcja Konfiguracji. Wersja dokumentu: 1.3

ibcslabel v2 Instrukcja instalacji systemu

Instalacja oprogramowania ESI oraz konfiguracja

Arkadiusz Kalicki, Lech Mankiewicz Plugin Webcam dla SalsaJ Podręcznik użytkownika

BusinessNet - Instrukcja instalacji czytników, kart procesorowych, certyfikatów kwalifikowanych oraz generowania podpisu elektronicznego.

Wdrożenie modułu płatności eservice. dla systemu Gekosale 1.4

Nowy sposób autoryzacji przelewów w Usłudze Bankowości Elektronicznej

Programowanie Urządzeń Mobilnych. Laboratorium nr 7, 8

Współpraca z platformą Emp@tia. dokumentacja techniczna

Sposoby tworzenia projektu zawierającego aplet w środowisku NetBeans. Metody zabezpieczenia komputera użytkownika przed działaniem apletu.

Instrukcja instalacji czytników, kart procesorowych, certyfikatów kwalifikowanych oraz generowania podpisu elektronicznego

PROBLEMY TECHNICZNE. Co zrobić, gdy natrafię na problemy związane z użytkowaniem programu DYSONANS

INSTRUKCJA UZYSKANIA DOŻYWOTNIEJ AKTUALIZACJI MAP (LIFETIME MAP UPDATES) W URZĄDZENIACH BECKER

Aplikacje internetowe i rozproszone - laboratorium

akademia androida Składowanie danych część VI

Instrukcja instalacji nośników USB w systemie internetowym Alior Banku

Instrukcja implementacji sterownika wirtualnego portu szeregowego dla systemu Android. Opracowanie: Elzab Soft sp. z o.o.

ZAPOZNANIE SIĘ Z TWORZENIEM

Cover sheet. WinCC (TIA Portal) FAQ Listopad 2012

Programowanie Multimediów. Programowanie Multimediów JAVA. wprowadzenie do programowania (3/3) [1]

Programowanie Urządzeń Mobilnych. Laboratorium nr 9,10

Estomed2. 1. Wstęp. 2. Instalacja Systemu Estomed Jak zainstalować Estomed2. Hakon Software sp. z o. o. Podręcznik instalacji

- 1 Laboratorium fotografii cyfrowej Foto Video Hennig

Instrukcja Instalacji

Zdalny dostęp SSL. Przewodnik Klienta

PANEL ADMINISTRACYJNY SPRZEDAWCY SZYBKI START

Instrukcja uruchomienia i korzystania z mtoken Asseco MAA na urządzeniach mobilnych oraz powiązania z Asseco CBP

Android Things oraz Raspberry Pi 3 (1)

Multimedia JAVA. Historia

Pracownia internetowa w szkole ZASTOSOWANIA

Product Update Funkcjonalność ADR dla przemienników Częstotliwości PowerFlex 750 oraz 525 6

Aktywności są związane z ekranem i definiują jego wygląd. Dzieje się to poprzez podpięcie do aktywności odpowiedniego widoku.

INSTRUKCJA UŻYTKOWNIKA Repozytorium Dokumentów Elektronicznych KS-EDE ISO 9001:2008 Dokument: Wydanie:

Windows 10 - Jak uruchomić system w trybie

Bezpieczne uruchamianie apletów wg

INSTRUKCJA KORZYSTANIA Z APLIKACJI

Programowanie obiektowe

INSTRUKCJA INSTALACJI OPROGRAMOWANIA MICROSOFT LYNC 2010 ATTENDEE ORAZ KORZYTANIA Z WYKŁADÓW SYNCHRONICZNYCH

KOMPUTEROWY SYSTEM WSPOMAGANIA OBSŁUGI JEDNOSTEK SŁUŻBY ZDROWIA KS-SOMED

Podręcznik Google. Cloud Print. Informacje o usłudze Google Cloud Print. Drukowanie przy użyciu usługi Google. Cloud Print.

Spis treści

IBM SPSS Statistics Wersja 25. Windows Instrukcja instalacji (licencja autoryzowanego użytkownika) IBM

Programowanie w języku Java - Wyjątki, obsługa wyjątków, generowanie wyjątków

Dokumentacja techniczna API systemu SimPay.pl

Przewodnik użytkownika dla usługi CUI Klient indywidualny (CBP)

INSTRUKCJA OBSŁUGI PEKAOTOKENA DLA UŻYTKOWNIKÓW PEKAO24

Brinet sp. z o.o. wyłączny przedstawiciel DrayTek w Polsce

emszmal 3: Automatyczne księgowanie przelewów w sklepie internetowym PrestaShop (plugin dostępny w wersji ecommerce)

Wdrożenie modułu płatności eservice. dla systemu Magento

Instrukcja użytkownika tokena mobilnego (mtokena) systemu KBI

Instrukcja użytkownika. Aplikacja dla WF-Mag

Instrukcja aktualizacji programu Integra 7

Instrukcja uruchomienia i korzystania z mtoken Asseco MAA na urządzeniach mobilnych oraz powiązania z Asseco CBP

Voicer. SPIKON Aplikacja Voicer V100

Instrukcja korzystania z aplikacji mobilnej mtoken Asseco MAA. Przewodnik dla użytkownika

Instrukcje instalacji pakietu IBM SPSS Data Access Pack dla systemu Windows

1. Pobieranie i instalacja FotoSendera

Instalacja i konfiguracji czytników kart kryptograficznych, aplikacji procertum CardManager w systemach Mac OS X

Życie aktywności Nawigując przez aplikacje poszczególne Aktywności przechodzą pomiędzy stanami. Dla przykładu gdy aktywność uruchamia się po raz

Tworzenie natywnych aplikacji na urządzenia mobilne - PhoneGap Tomasz Margalski

Ko n f i gura cja p ra cy V ISO z bazą SQL S e rve r

Kurs walut. Specyfikacja projektu. Marek Zając

Programowanie obiektowe zastosowanie języka Java SE

Instrukcja obsługi. Karta video USB + program DVR-USB/8F. Dane techniczne oraz treść poniższej instrukcji mogą ulec zmianie bez uprzedzenia.

SERWER AKTUALIZACJI UpServ

Profil pracy wariant konfiguracji programu obejmujący m.in język, walutę, konto allegro, szablon aukcji, zdefiniowane koszty wysyłki itp.

Instrukcja użytkownika. Aplikacja dla Magento

autor poradnika - KS Jak zamieszczać i edytować artykuły na szkolnej stronie internetowej

Podręcznik użytkownika dla komputera Macintosh

Instrukcja uruchomienia usługi KurJerzyAPI dla OsCommerce 2.2

Marketing Automation:

Systemy operacyjne na platformach mobilnych

Konfigurowanie sterownika CX9000 firmy Beckhoff wprowadzenie

Ćwiczenie 1. Kolejki IBM Message Queue (MQ)

Kadry Optivum, Płace Optivum. Jak przenieść dane na nowy komputer?

emszmal 3: Automatyczne księgowanie przelewów w sklepie internetowym PrestaShop (plugin dostępny w wersji ecommerce)

INSTRUKCJA AKTUALIZACJI PRZEGLĄDARKI. Wersja dokumentu 1.0

SecureDoc Standalone V6.5

1. Opis urządzenia. 1.2 Parametry techniczne. 1.3 Ułożenie interfejsów i podłączeń. Obsługiwane standardy Wi-Fi

Instrukcja obsługi SafeIT - modułu zdalnego sterowania do sterowników kotłów CO firmy Foster v1.0

VinCent Administrator

Certyfikat kwalifikowany

Instalacja NotifySync

Instrukcja użytkownika

Programowanie Urządzeń Mobilnych. Część II: Android. Wykład 2

Instrukcja korzystania z aplikacji mobilnej mtoken Asseco MAA klient korporacyjny

akademia androida Http i AsyncTask część VII

Pierwsze kroki w systemie

INSTRUKCJA UZYSKANIA DOŻYWOTNIEJ AKTUALIZACJI MAP (LIFETIME MAP UPDATES) W URZĄDZENIACH BECKER DLA SERII SL

Transkrypt:

Android Things oraz Raspberry Pi 3 (3) Obrazy spersonalizowane. Aktualizacja oprogramowania przez Android Things Console System Android Things jest dopiero wczesną wersją deweloperską, jednak już w obecnej fazie rozwoju dostarcza wielu funkcjonalności, które mogą pozytywnie wpłynąć na sukces tego projektu. Ciekawym i wartym przybliżenia rozwiązaniem jest platforma Android Things Console, która umożliwia niezwykle łatwe i szybkie budowanie spersonalizowanych obrazów oraz przeprowadzanie zdalnych aktualizacji OTA (Over The Air). W tej części cyklu poświęconej systemowi Android Things oraz płytce Raspberry Pi, zbudujemy spersonalizowany obraz systemu z własnym logo startowym oraz domyślnie zainstalowaną aplikacją użytkownika, której zadaniem będzie obsługa modułu kamery. Następnie za pomocą narzędzia Android Things Console przeprowadzona zostanie zdalna aktualizacja aplikacji. Zaczynajmy! Obsługa modułu kamery Raspberry Pi Zanim przystąpimy do budowy obrazu systemu z preinstalowaną aplikacją użytkownika, niezbędne jest uprzednie przygotowanie samej aplikacji. Aby nadać temu artykułowi pewien scenariusz oraz większy walor dydaktyczny, załóżmy, że postawionym przed nami zadaniem jest budowa systemu inteligentnego dzwonka dla jednego z naszych klientów. W systemie tym po wciśnięciu przycisku dzwonka za pomocą dołączonego modułu kamery [1] wykonujemy zdjęcia odwiedzających nas gości. Jednym z wymagań stawianych przez naszego fikcyjnego klienta jest to, aby poprzez dołączony do urządzenia wyświetlacz, prezentowana była lista dziesięciu ostatnich zdjęć, wraz z datą i godziną ich wykonania. Po zapełnieniu listy (wykonaniu serii 10 fotografii) lista powinna być czyszczona, a cały proces zostanie powtórzony od początku. Mając tak przedstawiony zarys wymagań, przystąpmy do realizacji zdania. Proces przygotowania nowej aplikacji rozpoczynamy od podłączenia modułu kamery, wykonania połączeń sprzętowych dla przycisku (rysunek 1) oraz utworzenia nowego projektu, zgodnie Rysunek 1. Schemat połączeń sprzętowych z wytycznymi dla systemu Android Things, co opisano w pierwszym artykule opublikowanym w Elektronice Praktycznej 11/2017. Tworzenie kodu obsługi modułu kamery rozpoczynamy od zdefiniowania uprawnień, wymaganych do uzyskania dostępu do podłączonego sprzętu i sieci Internet. W tym celu w pliku AndroidManifest.xml, definiujemy poniższe uprawnienie: <uses-permission android:name= android.permission. CAMERA /> <uses-permission android:name= android.permission. INTERNET /> Uprawnienie dające nam dostęp do zasobów kamery jest zaliczane do kategorii uprawnień niebezpiecznych, stąd przy pierwszej instalacji aplikacji niezbędne jest ponowne uruchomienie urządzenia (w odróżnieniu od uprawnień bezpiecznych, które są przyznawane aplikacji na etapie jej instalacji). Operacje związane z dostępem i obsługą urządzeń peryferyjnych są operacjami blokującymi, dlatego też, aby uniknąć problemów z brakiem responsywności interfejsu użytkownika, bardziej złożone i czasochłonne działania na sprzęcie, powinny być wykonane w osobnym wątku. W tym celu, w głównej klasie aplikacji (MainActivity.java), utwórzmy nowy wątek tła oraz powiązany z nim Handler [2], jak pokazano na listingu 1. Listing 1. Utworzenie wątku na potrzeby obsługi modułu kamery public class MainActivity extends Activity private Handler camerahandler; private HandlerThread camerathread; protected void oncreate(bundle savedinstancestate) super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); create new handler and associated thread for camera camerathread = new HandlerThread( CameraBackground ); camerathread.start(); camerahandler = new Handler(cameraThread.getLooper()); * ondestroy protected void ondestroy() super.ondestroy(); camerathread.quitsafely(); 87

Ponieważ kod obsługi modułu kamery jest generyczny i może zostać ponownie wykorzystany do budowy innych aplikacji, zostanie on umieszczony w ramach osobnej klasy RPiCamera (plik RPiCamera.java). Do zadań metody initializecamera() (listing 2), utworzonej w ramach klasy RPiCamera, należeć będzie: A. Wykorzystanie serwisu systemowego CameraManager [3] oraz funkcji getcameraidlist() do pobrania listy identyfikatorów wszystkich kamer dostępnych w systemie. B. Utworzenie instancji ImageReader a [4], której zadaniem będzie odczyt danych z modułu kamery oraz przetworzenie ich na obraz w formacie JPEG (o wielkości 640 480 pikseli). Przetwarzanie będzie realizowane w sposób asynchroniczny, a o jego zakończeniu i dostępności gotowego obrazu do dalszego przetwarzania, użytkownik będzie informowany poprzez wskazaną w inicjalizacji funkcję obsługi zdarzenia OnImage- AvailableListener [5]. C. Uzyskanie dostępu do kamery poprzez wywołanie opencamera() z określeniem numeru identyfikacyjnego urządzenia oraz obiektu wywołań zwrotnych związanych ze zmianą stanu pracy urządzenia. W ramach klasy RPiCamera zdefiniujmy również obiekt wywołań zwrotnych, informujących nas o poprawnym uzyskaniu dostępu do modułu kamery (onopened), jej odłączeniu (ondisconnected), wystąpieniu błędu (onerror) oraz zamknięciu urządzenia (onclosed), co zaprezentowano na listingu 3. Tym samym przygotowano szkielet klasy RPiCamera, który umożliwia nam poprawną inicjalizację modułu. Do wykorzystania funkcjonalności kamery, zatem brakuje metody umożliwiającej wyzwolenie przechwytywania obrazu z urządzenia. Funkcjonalność ta została zaimplementowana w metodzie takepicture() pokazanej na listingu 4. Proces przechwytywania obrazu z modułu kamery rozpoczynamy od utworzenia sesji CameraCaptureSession [6], poprzez wywołanie metody createcapturesession(). W wywołaniu tym określamy powierzchnię (Surface), do której będzie realizowany zapis (w omawianym przypadku jest to powierzchnia uprzednio skonfigurowanego obiektu ImageReader) oraz wskazujemy obiekt wywołań zwrotnych informujący nas Listing 2. Inicjalizacja modułu kamery private static fi n a l int IMAGE_WIDTH = 640; private static fi n a l int IMAGE_HEIGHT = 480; private CameraDevice mcameradevice; private CameraCaptureSession mcapturesession; private ImageReader mimagereader; public void initializecamera(context context, Handler backgroundhandler, ImageReader.OnImageAvailableListener imageavailablelistener) [A] Discover the camera instance CameraManager manager = (CameraManager) context.getsystemservice(camera_service); String[] camids = ; try camids = manager.getcameraidlist(); catch (CameraAccessException e) Log.d(TAG, Cam access exception getting IDs, e); if (camids.length < 1) Log.d(TAG, No cameras found ); return; String id = camids[0]; Log.d(TAG, Using camera id + id); (B) Initialize the image processor mimagereader = ImageReader.newInstance(IMAGE_WIDTH, IMAGE_HEIGHT, ImageFormat.JPEG, 1); mimagereader.setonimageavailablelistener(imageavailablelistener, backgroundhandler); (C) Open the camera resource try manager.opencamera(id, mstatecallback, backgroundhandler); catch (CameraAccessException cae) Log.d(TAG, Camera access exception, cae); Czytelnicy którzy mają za sobą doświadczenia z oprogramowaniem obsługi kamery w systemie Android na urządzenia mobilne, mogą czuć się uprzywilejowani dzięki pełnej integracji sterowników, obsługa dedykowanego modułu kamery Raspberry Pi w systemie Android Things jest analogiczna do obsługi kamer w urządzeniach mobilnych. Listing 3. Obiekt wywołań zwrotnych do monitorowania stanu modułu kamery private fi n a l CameraDevice.StateCallback mstatecallback = new CameraDevice.StateCallback() public void onopened(cameradevice cameradevice) Log.d(TAG, Opened camera. ); mcameradevice = cameradevice; public void ondisconnected(cameradevice cameradevice) Log.d(TAG, Camera disconnected, closing. ); cameradevice.close(); public void onerror(cameradevice cameradevice, int i) Log.d(TAG, Camera device error, closing. ); cameradevice.close(); public void onclosed(cameradevice cameradevice) Log.d(TAG, Closed camera, releasing ); mcameradevice = null; ; Listing 4. Obiekt wywołań zwrotnych do monitorowania stanu modułu kamery public void takepicture() if (mcameradevice == null) Log.w(TAG, Cannot capture image. Camera not initialized. ); return; try mcameradevice.createcapturesession( Collections.singletonList(mImageReader.getSurface()), msessioncallback, null); catch (CameraAccessException cae) Log.d(TAG, access exception while preparing pic, cae); Listing 5. Kod funkcji triggerimagecapture() private void triggerimagecapture() try fi n a l CaptureRequest.Builder capturebuilder = mcameradevice.createcapturerequest(cameradevice.template_still_capture); capturebuilder.addtarget(mimagereader.getsurface()); capturebuilder.set(capturerequest.control_ae_mode, CaptureRequest.CONTROL_AE_MODE_ON); Log.d(TAG, Session initialized. ); mcapturesession.capture(capturebuilder.build(), mcapturecallback, null); catch (CameraAccessException cae) Log.d(TAG, camera capture exception ); 88

o stanie utworzonej sesji. Poprawność utworzenia, aktywność i gotowość sesji do rozpoczęcia procedury przechwytywania obrazu, jest sygnalizowana poprzez wywołanie onconfigured(). Finalna postać funkcji konfigurującej i wyzwalającej przechwytywanie obrazu triggerimagecapture() została przedstawiona na listingu 5. Posiadając kompletny kod klasy RPiCamera, możemy uzupełnić implementację głównej aktywności MainActivity o inicjalizację i realizację przechwytywania obrazu. Inicjalizacja kamery zostanie przeprowadzona w metodzie oncreate(), natomiast wywołanie metody takepicture(), nastąpi po przyciśnięciu dołączonego do wyprowadzenia BCM23 przycisku. Korzystając z informacji przedstawionych w poprzednich częściach artykułu, dodajmy do klasy MainActivity obsługę przycisku i wyzwolenie przechwytywania obrazu, jak na listingu 6. Wciśnięcie przycisku BCM23 rozpoczyna sesję przechwytywania obrazu, podczas której dane z kamery przesyłane są do ImageReader a. Zakończenie tego procesu oraz dostępność przechwyconych danych w postaci pliku JPEG jest sygnalizowana poprzez wywołanie metody OnImageAvailableListener. Przechwycony obraz jest przekazywany do funkcji updategui(), której zadaniem jest aktualizacja interfejsu użytkownika, według zleconych przez klienta założeń (funkcje związane z budową GUI nie będą omawiane w tym artykule pełny kod źródłowy projektu jest dostępny do pobrania pod linkiem umieszczonym na końcu artykułu). Finalny efektu działania projektu został przedstawiony na filmie dostępnym pod adresem https:// goo.gl/6ezmq1. Personalizowana animacja startowa Po wygenerowaniu pliku aplikacji APK, możemy przystąpić do personalizacji obrazu systemu Android Things. Jednym z elementów tej personalizacji, będzie zamiana animacji startowej wyświetlającej domyślne logo systemu Android Things (rysunek 2), na statyczny obraz z pliku graficznego w formacie PNG. Format animacji startowej został ściśle zdefiniowany przez dokumentację systemu operacyjnego Android [7]. Plik z animacją w postaci archiwum ZIP (bootanimation.zip), powinien zawierać plik desc.txt (z określonym formatem opisu animacji) oraz katalogi od part0 do partn, zawierające kolejne klatki animacji zapisanych w postaci plików PNG. Pierwsza linia opisu zawarta w pliku desc.txt definiuje następujące parametry animacji: WIDTH HEIGHT FPS gdzie: WIDTH szerokość animacji wyrażona w pikselach, HEIGHT wysokość animacji wyrażona w pikselach, FPS liczba klatek na sekundę z jaką będzie wyświetlana animacja. Rysunek 2. Domyślna animacja startowa systemu Android Things Kolejne linie pliku desc.txt definiują poszczególne animacje, jakie będą wyświetlane na ekranie startowym (z uwzględnieniem kolejności zawartej w pliku). Pojedyncza linia opisuje przyjmuje następującą postać TYPE COUNT PAUSE PATH [#RGBHEX] gdzie: pole TYPE określa sposób wyświetlania danej animacji. Pole to może przyjmować jedną z dwóch wartości literowych: p wyświetlanie animacji może zostać przerwane w momencie gdy zakończony zostanie proces startu systemu, c animacja nie zostanie przerwana przez zakończony proces startu systemu, pole COUNT określa ile razy ma zostać odtworzona dana animacja wartość 0 określa odtwarzanie animacji w pętli, PAUSE pole określa liczbę klatek pauzy po zakończeniu danej animacji, PATH pole wskazuje ścieżkę do katalogu zawierającego odpowiednio posortowane pliki PNG z animacją np. part0, part1, itd. RGBHEX opcjonalny parametr określający kolor tła (w formacie #RRGGBB). Listing 6. Kod klasy MainActivity uzupełniony o obsługę modułu kamery public class MainActivity extends Activity private Gpio button; private RPiCamera camera; private Handler camerahandler; private HandlerThread camerathread; protected void oncreate(bundle savedinstancestate) super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); configure button PeripheralManagerService service = new PeripheralManagerService(); try button = service.opengpio( BCM23 ); button.setdirection(gpio.direction_in); button.setedgetriggertype(gpio.edge_falling); button.registergpiocallback(buttoncallback); catch (IOException e) Log.e(TAG, PeripheralIO API ERROR, e); create new handler and associated thread for camera camerathread = new HandlerThread( CameraBackground ); camerathread.start(); camerahandler = new Handler(cameraThread.getLooper()); initialize camera camera = RPiCamera.getInstance(); camera.initializecamera(this, camerahandler, monimageavailablelistener); * Button Callback private GpioCallback ButtonCallback = new GpioCallback() public boolean ongpioedge(gpio gpio) ; camera.takepicture(); return true; * Listener for new camera images private ImageReader.OnImageAvailableListener monimageavailablelistener = new ImageReader.OnImageAvailableListener() public void onimageavailable(imagereader reader) ; Image image = reader.acquirelatestimage(); ByteBuffer imagebuf = image.getplanes()[0].getbuffer(); fi n a l byte[] imagebytes = new byte[imagebuf.remaining()]; imagebuf.get(imagebytes); image.close(); updategui(imagebytes); 89

Rysunek 3. Utworzenie nowego produktu w ramach Android Things Console Poprzez odpowiednią konfigurację pliku desc.txt, użytkownik mam możliwość tworzenia bardziej rozbudowanych, kilku etapowych animacji, złożonych z animacji startowej (wyświetlanej raz) oraz animacji odtwarzanej w pętli, aż do zakończenia procesu uruchamiana systemu. Przykład takiej konfiguracji pliku desc.txt, został przedstawiony poniżej: 800 480 30 p 1 0 part0 p 0 0 part1 (animacja o parametrach 800 480@30 jest dwuetapowa pierwszy etap, na który składają się pliki PNG z katalogu part0, jest wyświetlany raz, następnie w nieskończonej pętli aż do momentu zakończenia procesu startu systemu wyświetlana jest animacja z katalogu part1). W realizowanym projekcie wykorzystany zostanie statyczny obraz z pliku PNG o rozdzielczości 1200 500 pikseli. Konfiguracja z pliku desc.txt, będzie wówczas prezentowała się następująco: 1200 500 1 p 0 0 part0 Ważnym zagadnieniem przy tworzeniu własnej animizacji startowej jest również sposób utworzenia archiwum bootanimation.zip. Pliki umieszczone w ramach pliku ZIP nie mogę być Rysunek 4. Konfiguracja nowego produktu w Android Things Console skompresowane, lecz powinny być umieszczone w archiwum w tzw. trybie store only. Utworzenie takiego archiwum z linii poleceń systemu Linux, może zostać zrealizowane następująco (gdzie flaga -0 wymusza tryb store only ) zip -0qry -i \*.txt \*.png \*.wav @../bootanimation.zip *.txt part*. Budowa obrazu systemu z Android Things Console Mając przygotowany plik aplikacji użytkownika APK oraz animację startową w postaci pliku bootanimation.zip, czas przystąpić do budowy obrazu. Do tego celu firma Google przygotowała narzędzie Android Things Console, dostępne pod adresem https:// goo.gl/dhvahg. Narzędzie Android Things Console umożliwia: budowę personalizowanych obrazów systemu Android Things, zawierających zintegrowaną aplikację użytkownika, zdalną aktualizację oprogramowania aplikacji użytkownika i wersji systemu operacyjnego. Po zalogowaniu się do aplikacji Android Things Console (z wykorzystaniem konta Google) i zaakceptowania warunków świadczenia usługi, użytkownik uzyska możliwość utworzenia nowego produktu, jak przedstawiono to na rysunku 3. W oknie konfiguracji nowego produktu (rysunek 4) użytkownik zostanie poproszony o: określenie nazwy produktu (jest to nazwa wewnętrzna projektu, która nie będzie widoczna dla użytkownika końcowego), wybranie platformy sprzętowej (z listy aktualnie wspieranych zestawów deweloperskich), włączenia/wyłącznie wsparcia dla usług Google Play, określenia wielkości partycji OEM na której będzie instalowana aplikacja użytkownika, opcjonalne podanie opisu nowo utworzonego produktu. Po wybraniu przycisku CREATE, aplikacja przeniesie nas do zakładki PRODUCT SETTINGS, zawierającej podsumowanie konfiguracji utworzonego produktu. Zakładka FACTORY IMAGES (rysunek 5) domyślnie podzielona została na dwie części: Bundles zawierającą informacje o utworzonych pakietach użytkownika, przeznaczonych do personalizacji systemu, Android Things Versions umożliwiająca użytkownikowi wybranie wersji systemu operacyjnego Android Things. W domyślnej konfiguracji (bez utworzonego pakietu personalizującego system), po wybraniu przycisku CREATE BUILD CONFI- GURATION, użytkownik ma możliwość zbudowania podstawowej wersji obrazu systemu w postaci, którą można również pobrać pod adresem https://goo.gl/8nq5gp. Naszym zadaniem jest przygotowanie wersji systemu, która będzie domyślnie zawierała przygotowaną aplikację użytkownika Rysunek 5. Zakładka Factory Images 90

Rysunek 6. Utworzenie nowego pakietu w sekcji Bundles Rysunek 7. Lista obrazów utworzonych za pomocą narzędzia Android Things Console oraz personalizowaną animację startową. Po wybraniu przycisku UPLOAD w sekcji Bundles, użytkownik zostanie poproszony o wskazanie archiwum ZIP zawierającego dane dla partycji OEM. Archiwum ZIP służące do personalizacji systemu powinno zawierać następujące pliki: bootanimation.zip [plik nieobowiązkowy] animacja użytkownika przygotowana zgodnie z wytycznymi z podrozdziału Personalizowana animacja startowa, <user-space driver.apk> [plik nieobowiązkowy] sterowniki działające w przestrzeni użytkownika jako serwis systemowy, <main.apk> [plik obowiązkowy] aplikacja użytkownika definiująca główny punkt wejścia (action=main, category=iot_launcher), <sub.apk> [plik nieobowiązkowy] dowolne inne aplikacje użytkownika, które mogą zostać uruchomione przez aplikację główną. Utwórzmy zatem nowe archiwum ZIP (tym razem jest to standardowy plik ZIP w odróżnieniu od trybu store only dla animacji startowej) zawierające plik APK oraz bootanimation.zip. Po załadowaniu nowego pakietu, sekcja Bundles zostanie zaktualizowana, jak przedstawiono to na rysunku 6. W ostatnim kroku wybierając z sekcji Bundles nasz nowo utworzony pakiet, a następnie z sekcji Android Things Versions ostatnią dostępną wersje systemu utwórzmy spersonalizowany obraz dla naszego urządzenia. Lista wszystkich zbudowanych obrazów oraz odnośników do ich pobrania, zostanie wyświetlona w sekcji Build configuration list rysunek 7. Aktualizacje OTA W naszym hipotetycznie realizowanym scenariuszu, udało nam się dostarczyć 100 urządzeń inteligentnych dzwonków dla naszego klienta. Nie trudno wyobrazić sobie jednak sytuację, gdzie przygotowane oprogramowania posiada błąd, który udało się odtworzyć dopiero po kilku miesiącach ciągłego działania urządzenia. W takich przypadkach, bardzo często koszty związane z dostarczeniem urządzeń do producenta i wgraniem nowego oprogramowania mogą okazać się bardzo wysokie. Z pomocą mogą przyjść aktualizacje OTA (Over The Air), czyli mechanizm aktualizacji zdalnych. Dla obrazów zbudowanych z wykorzystaniem Android Things Console, firma Google udostępnia infrastrukturę umożliwiającą przeprowadzenie zdalnej aktualizacji urządzeń (pakietu użytkownika i wersji systemu Android Things). Aby przeprowadzić zdalną aktualizację, w systemie Android Things Console, przechodzimy do zakładki OTA UPDATES. Rysunek 8. Aktualizacja systemu poprzez Android Things Console i mechanizm OTA Klikając przycisk START A NEW UPDATE, zostaniemy poproszeni o konfigurację nowo przygotowywanej aktualizacji. Panel konfiguracji jest tożsamy z zakładką FACTORY IMAGES. Użytkownik ma możliwość utworzenia nowego pakietu ze zaktualizowaną wersją aplikacji lub wgrania najnowszej wersji systemu Android Things (obie operacje mogą zostać przeprowadzone w ramach jednej aktualizacji). Proces aktualizacji rozpoczyna wybranie przycisku PUSH UPDATE. Od tego momentu, nowa aktualizacja jest dostępna do pobrania dla wszystkich urządzeń końcowych. Serwis update_engine uruchomiony w systemie Android Things sprawdza dostępność zdalnych aktualizacji co 300 minut, tak więc proces aktualizacji nie odbędzie się na wszystkich urządzeniach jednocześnie i może potrwać kilka godzin. Android Things Console udostępnia informacje o aktualnym postępie aktualizacji wszystkich urządzeń, jak pokazano na rysunku 8. Linki zewnętrzne: https://goo.gl/qn2yrv https://goo.gl/e5gp6s https://goo.gl/y7dobf https://goo.gl/63bf3l https://goo.gl/pz3zu7 https://goo.gl/wgnweo https://goo.gl/fnuqmv W czasie powstawania ostatniego odcinka z serii poświęconej systemowi Android Things, zgodnie z przyjętą polityką (regularne aktualizacje systemu w odstępach 6-8 tygodni), firma Google udostępniła najnowszą aktualizację systemu o numerze 5 (oznaczenie kodowe: OIR1.170720.015). Do najważniejszych zmian należą: zmiana wersji bazowej systemu do Android O (API 26), wsparcie dla nowej platformy deweloperskiej NXP SprIoT i.mx6ul, włączenie wsparcia dla OpenGL ES 2.0, sprzętowe wsparcie dla platform wyposażonych w GPU (w tym Raspberry Pi 3), dodanie nowego API DeviceManager, możliwość dynamicznej konfiguracji zadań pełnionych przez wyprowadzenia GPIO (Dynamic Pin Muxing). Wraz z najnowszą aktualizacją, obrazy systemu dostępne są do pobrania wyłączenie poprzez narzędzie Android Things Console. Opis pełnej listy zmian dostępny jest pod adresem https://goo. gl/6aw2jv. Łukasz Skalski 91