L’SDK Android di Hooky
La conversazione Hooky, nativa nella tua app Android: scritta con Jetpack Compose (Material 3), senza WebView, con i colori del tuo sito. Funziona in un’app Compose come in un’app con viste XML, in Kotlin come in Java.
Requisiti
- Android 6.0 o successivo (
minSdk 23). - L’SDK è compilato con
compileSdk 36(Android 16): compila la tua app con la stessa versione o con una più recente. - Kotlin o Java. La tua app non deve per forza usare Compose: l’SDK lo porta con sé per la sua schermata.
- Dipendenze: AndroidX (Activity, Core, Compose), le coroutine Kotlin e OkHttp. Nessuna libreria di immagini, di JSON o di analisi.
- Un account Hooky e un sito: la sua chiave pubblica è in Siti › Installa, la stessa del
data-site-keydella bolla web.
Installazione
L’SDK è servito dal suo repository GitHub, come repository Maven (GitHub Pages). Aggiungilo al tuo progetto, in settings.gradle.kts:
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://defdjamel.github.io/hooky-android")
}
}poi la dipendenza al modulo della tua app:
// app/build.gradle.kts
dependencies {
implementation("com.heyhooky:hooky-android:1.0.0")
}In Groovy: maven { url 'https://defdjamel.github.io/hooky-android' } e implementation 'com.heyhooky:hooky-android:1.0.0'. Le dipendenze dell’SDK (AndroidX, Compose, OkHttp, coroutine) arrivano da google() e mavenCentral(). Il codice sorgente è sotto licenza MIT: github.com/Defdjamel/hooky-android.
Iniziare in 3 righe
// 1. Una volta, all’avvio (Application.onCreate è il posto migliore)
Hooky.configure(context, "LA_TUA_CHIAVE_PUBBLICA")
// 2. La bolla già pronta, in un angolo della tua schermata (Compose)
HookyBubble(Modifier.align(Alignment.BottomEnd).navigationBarsPadding().padding(20.dp))
// 3. O la conversazione dal tuo pulsante
Hooky.open(context)configure carica il nome, il colore e il messaggio di benvenuto del sito, riprende la conversazione salvata e tiene aperta la connessione in diretta finché l’app è in primo piano.
class MiaApp : Application() {
override fun onCreate() {
super.onCreate()
Hooky.configure(this, "LA_TUA_CHIAVE_PUBBLICA")
}
}
// AndroidManifest.xml: <application android:name=".MiaApp" …>Tutte le chiamate avvengono sul thread principale e non generano mai errori. configure accetta anche translation = false, per rimuovere la traduzione dei messaggi del team (vedi Traduzione dei messaggi), e apiUrl, che serve solo per fare test sul tuo server.
La bolla
Un pulsante del colore del tuo sito (64 dp), con il logo Hooky e un badge per le risposte non ancora lette. Toccandolo si apre la conversazione. Compare appena l’aspetto del sito è caricato.
Jetpack Compose
Box(Modifier.fillMaxSize()) {
MiaSchermata()
HookyBubble(Modifier.align(Alignment.BottomEnd).navigationBarsPadding().padding(20.dp))
}
// Con la tua azione
HookyBubble(onClick = { mostraAiuto = true })Viste XML
<FrameLayout …>
<!-- la tua schermata -->
<com.heyhooky.sdk.HookyBubbleView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="20dp" />
</FrameLayout>L’activity che la mostra deve essere una AppCompatActivity o una ComponentActivity.
Aprire e chiudere la conversazione
Hooky.open(context) // a schermo intero (una Activity), da qualsiasi Context
Hooky.close() // la richiudeLa schermata della conversazione, HookyActivity, è dichiarata dall’SDK: non devi aggiungere nulla al tuo manifest.
Messaggi non letti
La bolla mostra già il suo badge. Per i tuoi pulsanti, il numero di risposte del team non ancora viste si segue in diretta; torna a 0 quando la conversazione si apre.
// Compose: uno StateFlow<Int>
val nonLetti by Hooky.unreadCount.collectAsState()
BadgedBox(badge = { if (nonLetti > 0) Badge { Text("$nonLetti") } }) { Icon(Icons.Default.Email, null) }
// Viste o Java: un listener (il valore attuale, poi ogni modifica)
val ascolto: Closeable = Hooky.addUnreadCountListener { n -> badge.isVisible = n > 0 }
ascolto.close() // per fermarloIn Java:
Hooky.configure(this, "LA_TUA_CHIAVE_PUBBLICA");
Closeable ascolto = Hooky.addUnreadCountListener(n -> badge.setText(String.valueOf(n)));Le risposte arrivano in diretta finché l’app è in primo piano; quando torna attiva, l’SDK recupera ciò che si è perso. La versione 1.0.0 non invia notifiche push ai tuoi utenti. Hooky.isConfigured e Hooky.VERSION completano l’API.
Identificare l’utente
La tua app sa chi ha effettuato l’accesso: dillo a Hooky. Nella scheda della conversazione, il tuo team legge il nome, l’email, il tuo identificativo dell’utente, il dispositivo e i dati che aggiungi. Con un’email, la conversazione non chiede più né il nome né l’email.
// Dopo l’accesso
Hooky.identify(
name = "Lou",
email = "lou@example.com",
userId = "u_1042", // il tuo identificativo
attributes = mapOf("piano" to "Pro", "carrello" to 49.9, "beta" to true),
)
// Più tardi: uniti ai precedenti
Hooky.setAttributes(mapOf("carrello" to 12, "ultima_schermata" to "Pagamento"))
Hooky.setAttributes(mapOf("beta" to null)) // null cancella una chiave
// All’uscita
Hooky.reset()In Java: Hooky.identify("Lou", "lou@example.com", "u_1042");, oppure con una Map<String, Object> di dati come quarto parametro.
Come funziona
- Nessuna conversazione ancora: tutto resta in memoria (anche prima di
configure) e parte con il primo messaggio. Dopo, ogni modifica parte subito, raggruppata (un solo invio per tutto ciò che cambia nello stesso secondo). Offline, riparte con il messaggio successivo o quando l’app torna in primo piano. nameedemailsostituiscono quelli della conversazione (nullli cancella sul dispositivo);userId = nulllo lascia invariato.- Lo
userIdviene conservato con il token della conversazione. UnouserIddiverso significa un altro account sullo stesso dispositivo: la conversazione viene dimenticata, come conreset(). Il nuovo utente non vede la conversazione del precedente. Hooky.reset()chiude la conversazione e dimentica i messaggi, l’identità e i dati. Chiamalo all’uscita.
Le regole dei dati
| Campo | Regola |
|---|---|
| Dati liberi | Una Map piatta: 50 chiavi al massimo, 8 KB in tutto. Le nuove chiavi sostituiscono le vecchie, le altre restano. |
| Chiave | Da 1 a 64 caratteri: lettere, cifre, spazi, _, . e -. Altrimenti viene ignorata. |
| Valore | Un testo (tagliato a 500 caratteri), un numero o un booleano. null cancella la chiave. Liste e mappe vengono ignorate, gli altri oggetti inviati come testo. |
userId | 200 caratteri al massimo. |
name, email | Il nome: 100 caratteri al massimo. L’email: un indirizzo valido, altrimenti viene ignorata. |
Hooky ripulisce ciò che supera i limiti, senza mai rifiutare il messaggio del tuo utente.
Questi dati sono dichiarativi: la chiave del sito è pubblica, e chiunque può usarla per inviare un nome, un’email o uno userId a sua scelta. Aiutano il tuo team a inquadrare la persona, non provano chi è. Non metterci mai segreti (password, token, numero di carta) e non usarli mai per concedere un accesso o agire su un account: verifica sempre dalla tua parte.
Statistiche
Conta quello che succede nella tua app, come Hooky.track sul web: le schede compaiono in Statistiche, insieme a quelle del sito. Chiamalo subito dopo che l’azione è andata a buon fine.
Hooky.track("iscrizione")
Hooky.track("ordine", 49.9, mapOf("piano" to "pro", "posti" to 3, "prova" to false))- Il secondo parametro,
value: un importo o una quantità, sommato nella scheda. Le proprietà sono piatte (testi, numeri, booleani). - Chiama prima
configure: prima,tracknon fa nulla. Gli errori sono silenziosi; offline, l’evento va perso. - Stesse regole del web (nome, 20 proprietà al massimo, limite): vedi Statistiche nella pagina.
Non inviare mai dati personali (email, nome, telefono) in un evento. Conta le azioni, non le persone.
Cosa fa la conversazione
- Il primo messaggio, con nome ed email facoltativi (o quelli di
identify), poi una conversazione come quella della bolla web: separatori dei giorni, nomi del team, link, emoji in grande, «Letto», «… sta scrivendo…», messaggi precedenti su richiesta. - Fino a 4 allegati per messaggio, 10 MB ciascuno, con una barra di avanzamento: foto dal selettore di sistema (nessuna autorizzazione da chiedere), dalla fotocamera (tramite l’app fotocamera del telefono) e PDF da File.
- Le foto ricevute si aprono a schermo intero (pizzica o tocca due volte per lo zoom); i file nell’app che sa leggerli, o si condividono.
- La bozza sopravvive alla chiusura della schermata e dell’app. La tastiera non copre mai il campo di testo.
- Errori chiari: offline, troppi messaggi insieme, file troppo pesante o rifiutato.
Cosa aggiunge l’SDK alla tua app
- L’autorizzazione
INTERNET, e nessun’altra. HookyActivitye unFileProvider(autorità<tuo.package>.hooky.fichiers, limitato alla cartellahooky/della cache della tua app) per le foto della fotocamera e i file ricevuti.- Delle
<queries>per le app che scattano foto o aprono i PDF (Android 11 e successivi).
Se la tua app dichiara lei stessa l’autorizzazione CAMERA, Android la richiede anche per aprire l’app fotocamera: in quel caso l’SDK la chiede prima.
Traduzione dei messaggi
Il tuo utente e il tuo team scrivono ognuno nella propria lingua, come con la bolla web (vedi Traduzione dei messaggi).
- Sotto un messaggio del team scritto in una lingua diversa da quella della conversazione (quella del dispositivo), un link discreto Traduci. Una volta tradotto, il messaggio compare nella lingua dell’utente, con «Tradotto dall’inglese · Mostra l’originale» per tornare al testo di partenza.
- Il pulsante di traduzione nell’intestazione propone Traduci sempre: i messaggi del team arrivano allora già tradotti. La scelta viene conservata sul dispositivo, per ogni chiave del sito.
- Una traduzione non riuscita mostra un breve errore con Riprova. I messaggi dell’utente non vengono mai tradotti dalla sua parte; il tuo team ha il suo pulsante Traduci, nella dashboard e nell’app Hooky.
- Si traduce solo il testo, non gli allegati. La traduzione è attiva per impostazione predefinita; per toglierla dalla tua app:
Hooky.configure(context, "LA_TUA_CHIAVE_PUBBLICA", translation = false).
Cosa invia l’SDK
Quello che invia la bolla web, e nient’altro. Nessun identificativo pubblicitario, nessun identificativo del dispositivo, nessuna libreria di analisi. Per compilare la sezione Sicurezza dei dati della tua scheda Google Play:
| Dato | Quando | Sicurezza dei dati |
|---|---|---|
| Messaggi | Quando l’utente scrive | Messaggi: Altri messaggi in-app |
| Foto e PDF | Quando li allega | Foto e video: Foto; File e documenti |
| Nome ed email | Se li fornisce, o se li passi a identify | Informazioni personali: Nome, Indirizzo email |
Il tuo userId | Se lo passi a identify | Informazioni personali: ID utente |
| Dati liberi | Quello che passi a identify e setAttributes | Secondo quello che ci metti |
Eventi track | Quando li invii, senza identificativo della persona | Attività nelle app: Altre azioni (analisi) |
| Dispositivo, lingua, fuso orario, app | Con la conversazione | Informazioni tecniche per il tuo team (vedi sotto) |
- Questi dati servono al funzionamento dell’app (l’assistenza clienti), e le statistiche alla tua analisi. Sono criptati in transito (HTTPS e WebSocket sicuro). Hooky li tratta per tuo conto: nel senso di Google Play, non è una condivisione con terze parti.
- Il dispositivo è leggibile: «Samsung SM-S918B · Android 15» (produttore, modello e versione di Android). La pagina della conversazione è
android-app://<tuo.package>. Ogni richiesta portaX-Hooky-Client: hooky-android/1.0.0eX-Hooky-App: <package> <versionName> (<versionCode>): il tuo team vede che la conversazione arriva da «Android · com.example.app 2.3.1 (231)». - Sul dispositivo: il token della conversazione (l’unica chiave dell’utente), lo
userIde la bozza, per chiave del sito, in un file privato della tua app sottonoBackupFilesDir: mai salvato nel cloud né ripristinato su un altro dispositivo. Una traduzione invia solo l’identificativo del messaggio e la lingua della conversazione. - Hooky è responsabile del trattamento ai sensi del GDPR: vedi l’informativa sulla privacy. Resti responsabile della tua scheda: dichiara ciò che la tua app invia davvero.
Lingua, modalità scura, accessibilità
- Lingua
- L’interfaccia esiste in francese, inglese, spagnolo, portoghese, italiano e tedesco. Segue la lingua del dispositivo al momento di
configure, l’inglese per impostazione predefinita. La lingua parte con il primo messaggio, perché il tuo team risponda nella lingua giusta e all’ora giusta (con il fuso orario). - Modalità scura
- La conversazione e la bolla seguono il tema chiaro o scuro del sistema, con il colore del tuo sito. Niente da impostare.
- Accessibilità
- Etichette TalkBack su ogni controllo (la bolla: «Apri la chat con …», e il numero di non letti), dimensione del testo di sistema rispettata.
R8 e ProGuard
Niente da aggiungere. L’SDK non usa la reflection e include le sue regole: R8 può ridurre tutto nella tua build di produzione.
Risoluzione dei problemi
- Il mio sito ha dichiarato i suoi indirizzi: l’app viene rifiutata?
- No. Un’app non ha un indirizzo: si presenta con la sua intestazione
X-Hooky-Cliente funziona anche quando il sito ha dichiarato i suoi domini. Non aggiungere nulla in Siti. - La bolla non compare
- Aspetta l’aspetto del sito. Verifica che
configurevenga chiamato, con la chiave pubblica del sito (non la chiave segretahks_…, né una chiave APIhka_…). Senza rete all’avvio, compare la prossima volta che l’app torna in primo piano. - Crash con
HookyBubbleView - L’activity deve essere una
AppCompatActivityo unaComponentActivity. - Offline
- Il messaggio mostra l’errore e resta nel campo;
identifyesetAttributesripartono più tardi. Gli eventitrackinviati offline vanno persi. - Un altro utente vede la vecchia conversazione
- Chiama
Hooky.reset()all’uscita, e passa unouserIdaidentify: un identificativo diverso riparte da una conversazione vuota.
Cronologia delle versioni
- 1.0.0
- Prima versione:
configure, la bolla Compose e XML,openeclose,identify(conuserIde dati liberi),setAttributes,track,reset, i non letti in diretta (StateFlowe listener Java), foto e PDF, la traduzione dei messaggi del team, sei lingue, modalità scura e TalkBack.