User Tools

Site Tools


doc:appunti:calendar_contacts_private

Calendari e contatti su Android, senza Google

Su uno smartphone Android è possibile avere la rubrica dei contatti e dei calendari con gli eventi senza passare per i servizi Google? Sembra di sì, anche se è tutt'altro che semplice!

In pratica è necessario installare un server che fornisca il servizio tramite i protocolli DAV, nel nostro caso abbiamo utilizzato DAViCal su Debian. Sul terminale Android si deve installare un client opportuno, la nostra scelta è caduta su DAVdroid. Infine è necessario adottare diversi accorgimenti per poter esportare i calendari e i contatti esistenti e verificare che la sincronizzazione col server remoto avvenga correttamente.

Installazione del server DAViCal

In Debian 9 Stretch esiste il pacchetto DAViCal versione 1.1.5, per convenienza esiste anche il backport della versione 1.1.7, che abbiamo preferito. Per soddisfare le dipendenze è necessario prendere dai backports anche il pacchetto libawl-php versione 0.59.

È necessario un database di supporto, nel nostro caso abbiamo utilizzato PostgreSQL. La procedura di installazione è abbastanza sui generis, in quanto richiede che venga predisposto l'accesso al database senza password (per fortuna è possibile revocarlo al termine dell'installazione). Vedere gli appunti nel paragrafo Installazione del server DAViCal.

In Apache 2.4 abbiamo definito un VirtualHost solo su HTTPS. Chi fa accesso usando HTTP viene rediretto per evitare che trasmetta password in chiaro sulla rete. Questa la configurazione da aggiungere:

<Directory /usr/share/davical/htdocs>
    DirectoryIndex index.php
    AllowOverride None
    Require all granted
</Directory>

<VirtualHost *:80>
    ServerName dav.server.org
    DocumentRoot /var/www/html/default
    # Redirect everything to https, except /.well-known/ directory.
    RedirectMatch permanent ^/((?!\.well-known).*)$ https://dav.server.org/$1
</VirtualHost>

<VirtualHost *:443>
    SSLEngine on
    ServerName dav.server.org
    SSLCertificateFile    /etc/letsencrypt/live/dav.server.org/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/dav.server.org/privkey.pem
    DocumentRoot /var/www/html/default
    ServerAdmin webmaster@server.org
    ErrorLog ${APACHE_LOG_DIR}/dav.server.org/error.log
    CustomLog ${APACHE_LOG_DIR}/dav.server.org/access.log combined
    Alias /dav /usr/share/davical/htdocs
    RewriteEngine On
    # PT is important if you are using an alias, it implies L
    # Redirect /.well-known URLs
    RewriteRule ^/\.well-known/(.*)$ /dav/caldav.php/.well-known/$1 [NC,PT]
    # Optionally: redirect /principals/users/ as well
    RewriteRule ^/principals/users/(.*)$ /dav/caldav.php/$1 [NC,PT]
    RewriteRule ^/principals/resources/(.*)$ /dav/caldav.php/$1 [NC,PT]
    RewriteRule ^/calendars/__uids__/(.*)$ /dav/caldav.php/$1 [NC,PT]
    RewriteRule ^/addressbooks/__uids__/(.*)$ /dav/caldav.php/$1 [NC,PT]
    # Redirect / requests to web login page
    RedirectMatch permanent ^/$ https://dav.server.org/dav/
</VirtualHost>

L'URL base del server sarà https://dav.server.org/dav/ e sarà accessibile sia con il protocollo WebDAV che con il protocollo HTTPS.

L'accesso in HTTPS presenta un'interfaccia minimale di amministrazione web: sarà possibile creare utenti (principals), creare address book e calendar (collections), ma per le normali operazioni di gestione contatti ed eventi si dovrà utilizzare un client dedicato. Nel nostro caso il client è rappresentato dalla app DAVdroid installata su uno smartphone Android, che darà accesso ai contatti e agli eventi di calendario a tutte le app relative.

Creazione di un utente con address book e calendar

L'amministratore del server DAViCal si collega all'URL di gestione https://dav.server.org/dav/, quindi accede alla pagina User FunctionsCreate Principal. I parametri da inserire sono:

Username È prassi abbastanza diffusa utilizzare l'indirizzo di posta elettronica come nome utente.
Password Immettere una password.
Fullname Normalmente si inserisce nome e cognome. Gli altri utenti del server DAViCal potranno vedere questa informazione.
Email Address Informazione di base richiesta per la creazione di un account, di solito coincide con lo Username. Anche questa informazione sarà pubblica per tutti gli utenti del server DAViCal.
Principal Type Selezionare Person per la creazione di un utente.

Al termine dell'operazione sarà stato attivato un utente DAViCal; automaticamente sarà stato creato anche un address book (CardDAV) e un calendario (CalDAV) a lui assegnati. Se il nome di login è user@server.org, gli URL dei rispettivi oggetti saranno del tipo:

Address book https://dav.server.org/dav/caldav.php/user@server.org/addresses/
Calendar https://dav.server.org/dav/caldav.php/user@server.org/calendar/

In generale non sarà necessario ricordare il percorso completo dei due oggetti, con l'autodiscover dovrebbe essere sempre sufficiente indicare solo l'URL base del server e gli oggetti disponibili dovrebbero essere automaticamente mostrati.

Installazione di DAVx5

Esistono diverse app per Android per la sincronizzazione di contatti ed eventi calendario verso server DAV. Purtroppo si tratta spesso di app che offrono solo una delle due funzionalità e spesso le versioni free hanno limitazioni o problemi (ad esempio continui alert se la connessione con il server fallisce). Pare invece che l'app DAVx5 (prima conosciuto come DAVdroid) abbia tutte le carte in regola per essere scelta: si tratta di software open source disponibile anche su F-Droid e sembra sufficientemente stabile e maturo.

DAVx5 Account Una volta scaricata e installata l'app, si deve creare un nuovo account sullo smartphone. Nel nostro caso si procede con l'opzione Login with URL and user name. Con l'installazione di DAViCal vista in precedenza si inserisce qualcosa del genere:

Base URL https://dav.server.org/dav/
User name email@server.org
Password ******

Lasciare attiva l'opzione predefinita Groups are separate VCards. Il server DAViCal support il formato vCard v.3.0 e quindi DAVx5 gestirà i gruppi come vCard separate (i gruppi sono usati ad esempio per creare le etichette da assegnare ai contatti). Vedere il paragrafo Contact group method nella documentazione sugli Account.

DAVx5 si collega al server e tramite l'autodiscovery sul percorso /.well-known/ si accorge che esistono già due collection collegate all'account: un addressbook e un calendar. Per impostazione predefinita infatti DAViCal crea queste due collection per ogni principal di tipo person (cioè per ogni account) che viene creato. Nella schermata che segue (vedi figura) bisogna attivare la sincronizzazione per queste due collection.

Questo è ciò che compare nello smartphone:

  • Strumenti ⇒ Utenti e account
    • Compare un nuovo account di tipo DAVx5, identificato con l'indirizzo email. Da questo account dipendono tutti i calendari e le rubriche che verranno sincronizzate col server.
    • Compare anche un nuovo account di tipo Rubrica DAVx5, identificato con il Displayname definito da DAViCal e l'indirizzo email più due lettere casuali. Questo account figlio è necessario per una limitazione di Android; la rubrica contatti infatti deve essere direttamente collegata ad uno specifico account, quindi l'account DAVx5 (padre) deve esporre un account Rubrica DAVx5 (figlio) per ogni rubrica contatti disponibile sul server. Questo non accade per i calendari: il singolo account padre è sufficiente per accederli tutti.

Maggiori dettagli nella pagina Accounts del manuale di DAVdroid.

Problema di sincronizzazione

Il sistema Android usa tecniche aggressive per il risparmi di batteria, questo affligge soprattutto le app non di sistema tipo DAVdroid. In pratica accade che viene inibita la sincronizzazione con il server: quando l'app è in background non viene mai svegliata.

Avviando l'app DAVx5 si viene avvisati di questo potenziale problema da tre pop-up:

  • Battery … ?
  • Automatic synchronization
  • OpenTasks non installata

Ci si può accorgere che qualcosa non va dal menu StrumentiUtenti e accountDAVdroidSincronizzazione account. Sebbene l'opzione sincronizzazione sia attiva e si scelga l'azione Sincronizza ora dal menu in alto a destra, l'orario di sincronizzazione non si aggiorna!

Nel nostro caso Android 8.1.0 Oreo su Xiaomi Mi A1, è stato necessario … FIXME

Creazione di un calendario aggiuntivo

DAVdroid: calendari In genere la via più comoda per aggiungere un calendario è utilizzare il client CalDAV preferito. Anche DAVdroid ha questa funzione agendo dalla app DAVdroid, AccountCalDAVHamburger menuCrea nuovo calendario.

Il calendario può essere di tipo Calendario oppure Elenco attività o meglio ancora la combinazione dei due. Tale impostazione viene registrata nel database nella colonna property_value della tabella property. Le attività (task in inglese), a differenza degli eventi di calendario, di solito sono associati ad una data senza l'orario e sono pensati per potersi sovrapporre gli uni con gli altri (molte attività vengono portate avanti in parallelo. L'app calendario stock di Android non consente di visualizzare i task.

In alternativa l'utente (anche non amministratore) può effettuare login alla pagina di amministrazione web di DAViCal, quindi sceglie l'opzione User FunctionsView My DetailsPrincipal CollectionsCreate Collection. Nella pagina di creazione si deve attivare l'opzione Is a Calendar. Il calendario creato in questo modo sarà di tipo combinato Calendario ed Elenco attività.

Per attivare il nuovo calendario nello smartphone si accede alla app DAVdroid, dopo aver selezionato l'account opportuno, si effettua tap sull'Hamburger menu di CalDAV, quindi si sceglie l'azione Aggiorna lista calendari.

Per poter disporre del nuovo calendario sullo smartphone è necessario:

  • Dalla app DAVdroid si sceglie l'account relativo, quidni dall'hamburger menu si sceglie l'azione Aggiorna lista calendari.
  • Dalla app SistemaUtenti e accountAccount DAVdroidSincronizzazione accountMenuSincronizza ora.
  • Dalla app Calendario si inserisce un nuovo evento, che generalmente provoca la sincronizzazione con il server.

Esportazione dei contatti da Google

Per fortuna è possibile esportare in formato aperto tutti i contatti che abbiamo associato al nostro account Google. È sufficiente autenticarsi su Gmail all'url https://mail.google.com/, quindi aprire l'url https://contacts.google.com/. Aprendo il menù Di più è possibile scegliere l'opzione Esporta. Nel dialog-box è possibile indicare Esporta come vCard. Al termine sul PC avremo il file contacts.vcf che deve essere trasferito sullo smartphone, ad esempio con il tool adb push e il cavetto USB.

L'importazione va fatta dall'app Contatti, noi abbiamo usato quella stock di Android Oreo 8.1.0. Anzitutto dal menu Impostazioni abbiamo indicato come Account predefinito per i nuovi contatti quello aggiunto con DAVdroid, quindi, sempre da Impostazioni, si è scelto la voce ImportaFile .vcf.

Non ha funzionato l'import delle foto associate ai contatti, infatti Google le include nel formato vCard come link ad un indirizzo web esterno (eventualmente da scaricare a parte), non come allegato JPEG.

L'app Contatti può mostrare i contatti provenienti dall'account Google, dall'account DAVdroid, oppure da tutti e due; dall'hamburger menu vi è un menu a tendina per la scelta. Fare attenzione a quando si rimuove un account, perché non è chiaro se lo stiamo rimuovendo anche dall'account Google e/o DAVdroid. Per sicurezza conviene rimuovere gli account Google facendo accesso con il browser all'url https://contacts.google.com/.

Esportazione degli eventi calendario da Google

Per l'esportazione è necessario fare accesso con un PC e un browser alla pagina https://calendar.google.com/, ovviamente dopo aver effettuato il login ad esempio alla casella Gmail. Dall'icona ingranaggio si sceglie ImpostazioniImportazione ed esportazioneEsporta. Viene fatto scaricare un file zip che contiene un file .ics per ogni calendario esistente nell'account Google.

Nei file .ics esportati è opportuno modificare il tag X-WR-CALNAME, impostando la descrizione breve che identificherà il calendario nell'interfaccia di DAVdroid.

È possibile caricare ogni singolo file .ics in un calendario DAViCal dall'interfaccia web. Dopo aver fatto login come utente proprietario del calendario, si clicca View My DetailsPrincipal CollectionsIDLoad From File. L'opzione Append consente di aggiungere gli eventi a quelli già esistenti, altrimenti il file caricato sostituisce del tutto il contenuto esistente.

Per altri dettagli vedere la pagina How can I migrate to DAViCal using already generated .ics files?.

Impostazione del colore predefinito di un calendario

Dall'interfaccia di amministrazione web di DAViCal non è possibile impostare il colore predefinito di un calendario. Né la app calendario di AOSP stock (Android Open Source Project) né DAVdroid consentono di impostare il colore di un calendario esistente. È possibile tuttavia agire direttamente sul database di DAViCal per impostare il colore predefinito.

Anzitutto verificate nella app DAVdroid, aprendo l'account interessato, che nelle Impostazioni (icona ingranaggio) l'opzione Cambia il colore del calendario sia attiva; in questo modo DAVdroid gestirà i colori dei calendari forniti dal server. Anche l'opzione Supporto colore dell'evento può essere attivata; in questo modo ogni singolo evento potrà essere colorato in modo diverso rispetto al calendario di appartenenza (funzione con alcuni problemi: non funziona con la app Calendario stock, manda in crash l'app calendario Etar, ecc.).

Dopo essersi collegati al database come amministratore, si cerca l'utente proprietario del calendario:

davical=# SELECT principal_id, user_no, displayname FROM principal;
 principal_id | user_no |      displayname      
--------------+---------+-----------------------
            1 |       1 | DAViCal Administrator
         1001 |    1001 | Niccolo Rigacci

quindi si cerca il dav_name del calendario desiderato:

davical=# SELECT user_no, dav_name, is_calendar FROM collection WHERE user_no = 1001;
 user_no |            dav_name             | is_calendar 
---------+---------------------------------+-------------
    1001 | /niccolo@rigacci.org/addresses/ | f
    1001 | /niccolo@rigacci.org/calendar/  | t
    1001 | /niccolo@rigacci.org/famiglia/  | t

Infine si aggiunge una riga alla tabella property:

INSERT INTO property
    (dav_name, property_name, property_value, changed_by) VALUES
    ('/niccolo@rigacci.org/famiglia/', 'http://apple.com/ns/ical/:calendar-color', '#F8BE14', 1);

Sullo smartphone è necessaria una sincronizzazione per vedere l'effetto:

  • Dalla app DAVx5 ⇒ Tap su account ⇒ CalDAV ⇒ Hamburger buttonRefresh calendar list.
  • Chiudere l'app Calendario.
  • Da ImpostazioniUtenti e accountDAVx5Sincronizzazione accountSincronizza ora.

Disattivazione App Calendario Google

A margine di questa esperienza vorrei segnalare un comportamento poco evidente e rischioso della app Calendario di Google. Su uno smartphone con CyanogenMod v.12.1 (basato on Android 5.1 Lollipop) era stata installata la app Etar; poiché il Calendario di Google non veniva più utilizzato, la app era stata disattivata dal menu ImpostazioniApp.

La app Etar e le altre app di tipo calendario continuavano a mostrare gli eventi di calendario come associati all'account Google, permettendo anche di inserirne di nuovi. In realtà la sincronizzazione con l'account Google non funzionava più: tutti gli eventi erano salvati solo in locale sul device Android e non erano presenti sui server Google. Il tutto accadeva in modo silente, senza alcun messaggio di errore o di warning. Due circostanze potevano evidenziare il problema:

  • Gli eventi aggiunti dalla app Android non comparivano nel calendario web https://calendar.google.com/ e viceversa.
  • Dal menu ImpostazioniAccountGoogleSincronizzazione era sparita la voce Calendario.

Per effettuare la corretta esportazione dei calendari è stato necessario riattivare la App Google e forzare la sincronizzazione.

Creazione di un calendario di gruppo

Scenario: si vuole creare un calendario e condividerlo con due o più utenti.

Creazione di un Principal di tipo Group

Il principal di tipo group avrà il suo login e la sua password, ma le credenziali non verranno condivise con gli utenti che avranno accesso al calendario. Il calendario (in effetti una collection) sarà creato come appartenente a questo gruppo.

  • User Functions ⇒ Create Principal
    • Username: caldavtest@domain.tld
    • Password: ******
    • Fullname: Gruppo per calendario condiviso
    • Email Address: caldavtest@domain.tld
    • Principal Type: Group

Aggiunta degli User al Group

FIXME Serve davvero? Oppure è sufficiente creare il Ticket (vedi avanti)?

  • User Functions ⇒ List Groups ⇒ (click su ID)
    • Group Members ⇒ (select the user) ⇒ Add
    • Group Members ⇒ (select the user) ⇒ Add

Creazione di un Calendar Collection nel Group

  • User Functions ⇒ List Groups ⇒ (click su ID)
    • Principal Collections ⇒ Create Collection
      • DAV Path: /dav/caldav.php/caldavtest@domain.tld/calendar/
      • Displayname: Calendario condiviso
      • Is a Calendar: [x]
      • Default Privileges: [x]
      • alendar Timezone: Europe/Rome
      • Collection Grants:
        • (select the user): ALL (FIXME Serve davvero? O basta il ticket?)
        • (select the user): ALL (FIXME Serve davvero? O basta il ticket?)

L'URL completo del calendario è https://dav.domain.tld/dav/caldav.php/caldavtest@domain.tld/calendar/, ma non si userà questo per l'accesso. La risorsa verrà ricollocata (bind) come risorsa di ciascun utente.

Creazione di un Access Ticket per la Collection

  • User Functions ⇒ List Groups ⇒ (click su ID)
    • Access Tickets
      • Ticket ID: Nfe5wq0Y
      • Target: /caldavtest@domain.tld/calendar/
      • Expires: 2029-12-29
      • Privileges: ALL

Binding della Calendar Collection allo User

Con questa operazione, il calendario condiviso (che ha URL /caldavtest@domain.tld/calendar/) verrà mappato come risorsa dell'utente (con URL /user1@domain.tld/boundcalendar/):

  • User Functions ⇒ List Users ⇒ (click su ID)
    • Bindings to other collections
      • ID Bounds As: /user1@domain.tld/boundcalendar/
      • Display Name: Calendario condiviso
      • To Collection: /caldavtest@domain.tld/calendar/
      • Ticket ID: Nfe5wq0Y

L'URL completo del calendario diventa quindi https://dav.domain.tld/dav/caldav.php/user1@domain.tld/boundcalendar/. In generale non si dovrà indicare l'URL per esteso, perché il client (es DAVx5 su Android) elencherà il nuovo calendario nell'elenco di quelli disponibili, con l'etichetta impostata in Displayname.

Aggiornamento del database di backend

Dopo l'aggiornamento da Debian 9 Stretch a Debian 10 Buster, quando ci si collega all'interfaccia web di Davical (nella nostra installazione è qualcosa del tipo https://dav.host.tld/dav/), si legge il seguente warning:

Database schema needs upgrading. Current: 1.3.2, Desired: 1.3.3

Si è deciso di agire da riga di comando. Anzitutto si crea un file /etc/davical/administration.yml con le credenziali per accedere al database (proteggere il file con mode 600):

admin_db_user: davical_dba
admin_db_pass: MySecret
admin_db_host: 127.0.0.1

Quindi si esegue lo script /usr/share/davical/dba/update-davical-database che provvede ad applicare tutte le patch incrementali allo schema del database. Ovviamente si consiglia di fare un backup del database prima di eseguire la procedura.

doc/appunti/calendar_contacts_private.txt · Last modified: 2021/08/27 15:47 by niccolo