Anteprima
Vedrai una selezione di 12 pagine su 55
Appunti Mobile Programming Pag. 1 Appunti Mobile Programming Pag. 2
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 6
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 11
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 16
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 21
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 26
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 31
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 36
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 41
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 46
Anteprima di 12 pagg. su 55.
Scarica il documento per vederlo tutto.
Appunti Mobile Programming Pag. 51
1 su 55
D/illustrazione/soddisfatti o rimborsati
Disdici quando
vuoi
Acquista con carta
o PayPal
Scarica i documenti
tutte le volte che vuoi
Estratto del documento

Struttura del progetto:

ProjFolder

|

|____ css

|​ |___ style.css ​

| ⚙️

|_____ js

|​ |___ app.js

|

|_____ index.html

|

|_____ serviceWorker.js

/js/app.js

// Il navigator rappresenta il browser​

if ("serviceWorker" in navigator) {​

navigator.serviceWorker.register("/serviceworker.js")​

.then(function(registration) {​

console.log("Service Worker registrato con scope:", registration.scope)​

}).catch(function(error) {​

console.log("Registrazione Service Worker fallita:", error);​

})​

} /serviceWorker.js

// Aggiungiamo un listener che catturi tutti gli eventi fetch.​ ​

// In questo modo, le fetch saranno indirizzate al Service Worker, non

// alle normali pagine, e racchiuderanno le richieste fatte dal browser​

self.addEventListener("fetch", function(event) {​

console.log("Richiesta fetch per:", event.request.url);​

// Intercettiamo una richiesta col Service Worker e restituiamone una nuova​

if (event.request.url.includes("style.css")) {​

event.respondWith(​

new Response(​

'h1 { color: red; font-size: 4em; }',​

{headers: {'Content-Type': 'text/css'}}​

)​

);​

}​

});​

// Creiamo un proxy identità: restituisce la risorsa richiesta​

// ma se siamo offline, viene restituita un'altra risposta​

self.addEventListener("fetch", function(event) {​

event.respondWith(​

fetch(event.request)​

.catch(function() {​

return new Response("Sei offline.")​

})​

);​

}); Ogni Service Worker ha uno scope limitato che può controllare.

Consideriamo di avere un’app in foo.com e 2 sottodomini foo.com/A e foo.com/B

Potremmo inserire un Service Worker in foo.com/A per dirottare tutte le richieste fatte verso

foo.com/B

Lo scope è dato dalla directory che ospita il Service Worker:

-​ Se è “/” → allora controlla tutte le richieste che originano in qualche parte dell’app

-​ Se è “/js/” → allora controlla le richieste che originano soltanto nella directory /js

Quando registriamo un Service Worker, possiamo passare l’attributo scope per limitare lo

scope stesso:

navigator.serviceWorker.register("/serviceWorker.js", { scope: "/A" });

Supponiamo adesso di avere una pagina index-offline.html

Vogliamo servire questa pagina quando l’utente è offline.

Idealmente scriveremmo:

self.addEventListener("fetch", function(event) {​

​ event.respondWith(​

​ ​ fetch(event.request)​

​ ​ ​ .catch(function() {​

​ ​ ​ ​ return fetch("/index-offline.html")​

})​

);​

});

Tuttavia, tale approccio non funzionerebbe:

1.​ La fetch si effettua quando si è online

2.​ Si memorizza la risorsa localmente (sul device)

3.​ Si restituisce la risorsa quando si è online

Per risolvere tale problema possiamo utilizzare la CacheStorage API.

Il CacheStorage è un layer di caching:

-​ Non è la cache del browser

-​ Non è la vecchia Application Cache

Tale API espone dei metodi di base, con cui:

-​ Creare e manipolare diverse cache

-​ Memorizzare dati nelle cache

-​ Recuperare dati dalle cache

-​ Eliminare vecchi dati

La combinazione di Service Worker e CacheStorage permette di far funzionare l’app offline.

In questo modo si ha un controllo programmatico su cosa viene memorizzato, quando viene

memorizzato, e così via.

Per fare caching, catturiamo l’evento install.

Tale evento avviene una sola volta, subito dopo il register e subito prima dell’attivazione.

Permette di fare caching di tutti i file che vogliamo rendere disponibili offline.

È utile anche per arrestare l’attivazione di un Service Worker nel caso in cui vi siano

problemi:

-​ Se qualcosa va storto durante il caching, possiamo arrestare l’attivazione

-​ Alla prossima richiesta, il browser riproverà ad attivare il Service Worker

// Memorizzazione​

self.addEventListener("install", function(event) {​

​ event.waitUntil(​

​ ​ caches.open("la-mia-cache")​

​ ​ ​ .then(function(cache) {​

​ ​ ​ return cache.add("/index-offline.html");​

})​

);​

});

-​ Il metodo waitUntil() estende il tempo di vita dell’evento fino a quando la Promise

passata come argomento non si realizza.

-​ L’oggetto caches è l’endpoint della CacheStorage API

-​ Il metodo caches.open(X) permette di accedere ad una cache col nome X (o la crea

se non esiste), restituendo una Promise che - se realizzata - ci permette appunto di

accedere alla cache

-​ Il metodo cache.add() aggiunge il file alla cache

>> La cache è a tutti gli effetti una mappa, la chiave dell’elemento sarà il nome usato nel

metodo cache.add()

// Recupero​

self.addEventListener("fetch", function(event) {​

​ event.respondWith(​

​ ​ fetch(event.request)​

​ ​ ​ .catch(function() {​

​ ​ ​ ​ return caches.match("/index-offline.html");​

})​

);​

});

Se una qualunque richiesta non va a buon fine, restituiamo la versione cache di

index-offline.html

-​ Il metodo caches.match(X) verifica l’esistenza della chiave X in una qualunque cache

creata dalla nostra web app; se vogliamo accedere ad una cache specifica (ad

esempio, la-mia-cache) si utilizza il metodo caches.open():

caches.open("la-mia-cache")​

​ .then(function(cache) {​

​ ​ return cache.match("/index-offline.html");​

});

Per fare il caching di più risorse, utilizziamo il metodo cache.addAll

var CACHED_URLS = [​

​ "/index-offline.html",​

​ "/css/style.css",​

];​

self.addEventListener("install", (event) => {​

​ event.waitUntil(​

​ ​ caches.open("la-mia-cache")​

​ ​ ​ .then((cache) => {​

​ ​ ​ ​ return cache.addAll(CACHED_URLS);​

})​

);​

});

Finora abbiamo recuperato indiscriminatamente una sola risorsa.

Per recuperare la risorsa effettivamente richiesta, dobbiamo effettuare un matching

specifico.

self.addEventListener("fetch", (event) => {​

event.respondWith(​

fetch(event.request)​

.catch(() => {​

​ return caches.match(event.request)​

​ ​ ​ .then((response) => {​

​ ​ ​ if (response)​

​ ​ ​ return response;​

​ ​ ​ else if (event.request.headers.get("accept").includes("text/html"))​

​ ​ ​ return caches.match("/index-offline.html");​

})​

})​

);​

}); >> La Promise di caches.match() non viene mai rigetta, quindi controlliamo esplicitamente

se la risposta è valida.

Se non è valida, la richiesta accetta risposte con contenuto del tipo text/html, e restituiamo

quindi il nostro index-offline.html

React Native

React Native è un framework per sviluppare applicazioni mobile in JavaScript.

Utilizza la libreria React, creata da Meta e originariamente utilizzata per sviluppare UI e web

app.

React Native compila JavaScript in vere applicazioni native, che abbiano accesso a

platform-specific API e componenti.

In principio, la filosofia dietro la realizzazione delle mobile app era quella di utilizzare

JavaScript per la loro creazione, in modo da facilitare il lavoro per chi arrivava dal mondo del

web development.

L’app mobile veniva quindi scritta in JavaScript, e poi wrappata (racchiusa) in un sandbox

browser chiamato WebView, sfruttando tool come Apache Cordova, ottenendo app ibride.

In questo modo era possibile scrivere codice una sola volta ed eseguirlo ovunque (“Write

once, run everywhere”), ma le app mobile ottenute non erano altro che siti web racchiusi in

una WebView.

Col tempo la filosofia si è evoluta, fino ad arrivare alle moderne app cross-platform.

Tale approccio si basa sui seguenti punti:

-​ Utilizzare un modello fissato che permetta di creare applicazioni web

-​ Associare gli elementi di questo modello ai componenti nativi mobile

Questo è l’approccio seguito da React Native, che permette di scrivere codice usando i

componenti della libreria React (usata per le UI delle web app), per poi convertirli in

componenti nativi dei SO mobile.

>> Non possiamo trasporre direttamente una web app in React in una mobile app, ma

possiamo scriverla in React Native senza passare per altri linguaggi.

Il funzionamento di React Native si basa sul JavaScript bridge.

A runtime tutti i componenti che usiamo in React Native saranno renderizzati col

corrispettivo componente nativo della piattaforma target.

Ad esempio, il componente <View> in React Native verrà tradotto in:

-​ View in Android

-​ UIView in iOS

-​ <div> in HTML

Ciò ci permette di realizzare 3 tipologie diverse di app a partire da una singola codebase.

Pro Contro

Usato in production da moltissime realtà Immaturo rispetto a framework come Flutter

Community enorme Necessità di conoscere React

Performance È comunque un’astrazione costruita sulle API

delle piattaforme target, se queste cambiano,

Tooling React Native deve essere aggiornato d’accordo

Osserviamo come funziona il framework sotto al cofano.

La libreria React è presente nell’engine JavaScriptCore.

React Native comunica asincronicamente con l’OS mobile.

Questa comunicazione permette l’accesso alle API per i widget nativi (ad esempio, i

componenti)

React Native renderizza questi componenti tramite queste API, e questo vale per ogni

dispositivo target.

I componenti React Native vengono tradotti nei rispettivi componenti target attraverso 2

livelli:

1.​ JavaScript Thread

-​ Contiene una JavaScript virtual machine, detta Hermes

-​ Esegue il codice, invoca le API native del target, …

-​ Vi è un singolo thread, nel quale sarà eseguita la componente logica dell’app

-​ L’app è pacchettizzata in un singolo file tramite Metro, che traduce anche il

codice JSX in JS

2.​ Native Thread

-​ Qui si esegue il codice nativo

-​ React Native implementa questa parte di codice nativo per ogni piattaforma

(ad esempio, Java per Android)

-​ È composto da moduli che comunicano con l’SDK Android o iOS

-​ Espone una API che unifica le varie piattaforma, che può essere invocata

dallo JavaScript Thread

La comunicazione tra JavaScript Thread e Native Thread avviene per mezzo di un bridge

Dettagli
Publisher
A.A. 2024-2025
55 pagine
SSD Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher gaeeee02 di informazioni apprese con la frequenza delle lezioni di Mobile programming e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università degli Studi di Salerno o del prof Giaccari Francesco.