diff --git a/IcarusAndroid/.idea/misc.xml b/IcarusAndroid/.idea/misc.xml index dc3456943dbacb713d82d860da5b81f41a83a44e..cc51e58ed3ffa8f4eb67f5573f5a2729daeb0264 100644 --- a/IcarusAndroid/.idea/misc.xml +++ b/IcarusAndroid/.idea/misc.xml @@ -25,7 +25,7 @@ - + diff --git a/README.md b/README.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0b6a9c51439f31bc4b8f9f98364650521dc652ba 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,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("")` -> 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 `/build/outputs/aar/` dovrei trovare un file libreria del tipo `-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("")` 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` (con prima lettera maiuscola dopo "add" per esempio: `addBoolean(String nomePreferenceCambiata, 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"); + } +``` \ No newline at end of file