README.md 9.11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
#Icarus guida all'uso

###Importare Icarus in un'app:
1. Trovare il file .aar di icarus (attualmente icarus-debug.aar, vedi più avanti per guida alla compilazione)
2. da Android Studio: File -> new -> new Module -> selezionare "Import .JAR/.AAR Package" -> selezionare il file del punto 1, dare un nome a come si vuole che venga chiamata la libreria all'interno dell'applicazione e fare finish.
3. Andare nel `settings.gradle` del progetto e guardare se è apparso il nome della libreria importata dato al punto 2.
4. Andare nel `build.gradle(module:app)` e inserire sotto `dependencies` la voce `implementation project("<nome libreria nel settings.gradle>")` -> per es `:icarus` se come nome al punto 2 abbiamo dato come nome `icarus`
5. Importare nell'app anche le librerie usate da icarus per fare le chiamate di rete: `implementation 'com.android.volley:volley:1.1.0'` (cercare di tenere aggiornato questo numero di versione) e `implementation 'com.google.code.gson:gson:2.8.3'` sempre nel `build.gradle(module:app)` del punto 4. Questo è necessario perchè le librerie non sono transitive da un modulo all'altro (bisognerebbe pubblicarle su Maven con un file pom.xml per poter avere un effetto di import automatico)
6. Nella parte sx di Android Studio dove vedo la mia struttura del progetto dovrebbe essere apparso il modulo appena importato.
7. Sync gradle and fun!

###Eliminare dipendenza da icarus in un'app
1. Il modulo apparso nella struttura di progetto al punto 6 di "Importare Icarus in un'app" è una normale cartella eliminabile dal file system. Eliminarla dunque. *Tip: selezionare il modulo da Android Studio -> tasto dx del mouse -> reveal in finder (su Mac) -> eliminarla.*
2. Andare nel `build.gradle(module:app)` dell'app dalla quale si vuole eliminare la dipendenza a icarus e togliere le righe aggiunte ai punti 4 e 5 di "Importare Icarus in un'app"
3. Andare nel `settings.gradle` del progetto ed eliminare dagli `include` quello che si riferisce alla libreria che si vuole eliminare (in questo caso icarus).
4. Sync gradle and fun!

###Creare da un progetto libreria di Android studio un file .aar
1. Seguire innanzitutto [questa guida](https://developer.android.com/studio/projects/android-library.html?#AddDependency) per creare un modulo di Android Studio esportabile come libreria .aar
2. Nel progetto di Android Studio selezionare il modulo corrispondente alla libreria
3. Nella barra degli strumenti di Android Studio -> Build -> Rebuild Project
4. Cambiando vista da quella di "Android" a quella di "Project" dove vedo la struttura del progetto in `<nome_lib>/build/outputs/aar/` dovrei trovare un file libreria del tipo `<nome_lib>-debug.aar`

###Aggiornare la versione della libreria in un'app
1. Consiglio: eliminarla come nella sezione "Eliminare dipendenza da hermes in un'app", ma dal file `build.gradle(module:app)` commentare solo `implementation project("<nome libreria nel settings.gradle>")` e nel `settings.gradle` lasciare tutto così com'è.
2. Quando si procede all'"Importare Icarus in un'app" dare la path del file .aar aggiornato e avere l'accortezza di dargli lo stesso nome di prima. Basterà decommentare la riga commentata nel punto 1 e il gioco è fatto.
3. Questo anche per prevenire una cosa che spero venga fixata nelle successive versioni di Android Studio: nell'eliminazione del modulo libreria dal file system, esso resta visibile ancora nella struttura del progetto.. Chiamando allo stesso modo il modulo aggiornato, quello rimasto nel progetto si aggiornerà in automatico.

###Usare Icarus all'interno di un'app
Con Icarus è possibile tracciare eventi generici, cambio di Activity e cambio di preference (settaggi). Icarus è un Singleton, perciò ogni metodo potrà essere invocato solo dopo aver chiamato `Icarus.getInstance(Context)` dove il Context è quello dell'Avtivity chiamante. Per ogni tracciamento si deve specificare, inoltre un flag che indica se si stanno facendo chiamate da un'app in debug o no.

####Tracciare cambio di Activity
`Icarus.getInstance(Context).trackScreen(ScreenTrackResource res boolean debug)`
dove ScreenTrackResource è un'`enum` che permette di specificare se si sta tracciando un ingresso in un'Ativity o un'uscita. Dal `Context` Icarus è in grado di capire che Activity è stata chiamata

####Tracciare cambio di Preference
Pensato per le `SharedPreference` è possibile tracciare i cambi di preferenze dei seguenti tipi:

1. `int`
2. `boolean`
3. `float`
4. `long`
5. `String`

Si usa nel seguente modo:

1. Creare un'istanza di `UserSettingsResource(SharedPreferences,Context)`. è necessario passargli un riferimento alle `SharedPreferences` usate nell'app chiamante perchè questa libreria crea una "storia a breve termine" delle `SharedPreferences` memorizzando all'interno delle `SharedPreferences` stesse gli ultimi settaggi loggati.
2. Quando si ha una preferenza di cui fare logging aggiungerla all'istanza di `UserSettingsResource` creata al punto 1 attraverso il metodo `add<tipo_tra_quelli_sopra>` (con prima lettera maiuscola dopo "add" per esempio: `addBoolean(String nomePreferenceCambiata, <tipo> nuovoValore)`).
3. è possibile invocare metodi `add...` tutte le volte che si vuole. In automatico Icarus scarta le preference duplicate e quelle che dall'ultimo log non sono cambiate (per esempio se un utente con uno switch fa ON-OFF-ON e il log venisse chiamato dopo l'ultimo ON Icarus non loggherebbe quel cambio di settaggio)
4. `Icarus.getInstance(Context).logUserSettings(UserSettingsResource res, boolean debug)` per loggare al server

####Tracciare un evento
Pensato per loggare eventi app specific e invocabile in un qualunque punto dell'app richiede l'implementazione di un metodo ausiliario (per semplicità e per evitare di riscrivere mille volte le stesse cose) all'interno dell'app chiamante che aiuti nella creazione dell'oggetto `EventTrackResource` che conterrà tutte le informazioni relative all'evento da tracciare (che sono tante e tutte da passare all'interno del costruttore perchè tutte obbligatorie).
Altro pre-requisito è implementare l'`ActivityRecognition`, per esempio [quella di Google](https://www.androidhive.info/2017/12/android-user-activity-recognition-still-walking-running-driving-etc/) all'interno dell'app chiamante.

Terminato questo preambolo, l'utilizzo vero e proprio del tracciamento degli eventi con Icarus è semplice:

`Icarus.getInstance(Context).logEvent(EventTrackResource res, boolean debug)` 

dove un'istanza di `EventTrackResource` si costruisce così:

`new EventTrackResource(String eventName, EventCategory category, EventLabel lbl, int heading, int course, int speed, String mostProbableActivityName, int confidence, boolean accessibilityEnabled)`

dove `eventName` è un nome qualunque dato dal creatore dell'app per riconoscere l'evento specifico tracciato,

`category` è la categoria dell'evento e si può scegliere un valore da un `enum`. Per ora è possibile scegliere `APPLICATION, NOTIFICATION,ACTION`.

`lbl` segue la stessa logica dell'`enum` di `category` e permette di specificare se quell'evento che si sta tracciando è avvenuto mentre l'app era in foreground o in background.

I parametri seguenti, a patto di averli calcolati all'interno dell'app chiamante (se no si sarà obbligati a metterli a caso per poter loggare un evento) sono l'orientamento del dispositivo (`heading`), la rotta nella quale si sta camminando (`course`) ed è quindi necessario usare il GPS o altro metodo di localizzazione. Relativamente all'attività è richiesto dal server che gli vengano mandati nomi specifici di attività per cui in ogni app è necessario implementare questo metodo:

```java
private String getActivityNameFromActivityCode(int activityCode){

        switch (activityCode){

            case DetectedActivity.IN_VEHICLE:
                return "automotive"
            case DetectedActivity.ON_BICYCLE:
                return "cycling"
            case DetectedActivity.ON_FOOT:
                return "walking"
            case DetectedActivity.RUNNING:
                return "running"
            case DetectedActivity.STILL:
                return "stationary"
            case DetectedActivity.TILTING:
                return "unknown"
            case DetectedActivity.UNKNOWN:
                return "unknown"
            case DetectedActivity.WALKING:
                return "walking"
            default:
                return "unknown"
        }
    }
```
dove `activityCode` è il codice dell'attività più probabile tra quelle ritornate dall'`ActivityRecognition` di Google di cui il link sopra. (trovare con un sort per `DetectedActivity.getConfidence()`) l'attività considerata più probabile secondo Google. Sia `activityCode`, sia `confidence` sono attributi di `DetectedActivity` accessibili attraverso metodi. `accessibilityEnabled` indica invece se il Talkback è attivo su quel dispositivo al momento del log. Si può sapere attraverso questo snippet:

```java
AccessibilityManager am=(AccessibilityManager)c.getSystemService(Context.ACCESSIBILITY_SERVICE);
        boolean accessibilityEnabled=false;
        try {

            accessibilityEnabled=am.isTouchExplorationEnabled();

        } catch (NullPointerException npe){

            Log.d("TAG","error taking AccessibilityManager");
        }
```