• Programmazione Android
  • CORSI ONLINE
  • Web Agency

Logo

Corsi di programmazione web e mobile online
Navigation
  • Home
  • CORSI ONLINE
  • Tutorial Pratici
  • GUIDE COMPLETE
    • Corso completo di C
    • Corso videogame con Cocos2d
    • Programmazione Cocoa Touch
  • Sezioni
    • Libri e manuali
    • Tips & Tricks
    • Risorse utili
    • Strumenti di Sviluppo
    • Materiale OpenSource
    • Framework
    • Guide Teoriche
    • Guide varie
    • Grafica e Design
    • iPad
    • News
    • Video Tutorial
    • Windows Phone
  • Pubblicità
  • About
    • Chi siamo
    • Pubblicazioni
    • Collabora
    • Sostieni devAPP

Come integrare Google Calendar nelle applicazioni Android

By Giuseppe Maggi | on 7 Marzo 2016 | 2 Comments
Senza categoria

Google Calendar è probabilmente uno dei servizi di Mountain View più utilizzati al mondo, non solo dall’utenza Android. Si tratta di uno dei primi strumenti che ha permesso a chiunque – anche se dotato di capacità informatiche praticamente nulle – di memorizzare in maniera dettagliata i propri impegni, esperienze e attività in una banca dati remota, sicura e utilizzabile in qualunque luogo.

Non a caso, una delle curiosità che anima i programmatori Android, ad ogni livello di esperienza, è proprio apprendere come integrare una semplice app Android con questo servizio in modo da renderlo un vero e proprio backend finalizzato allo scopo.

In questo articolo vedremo come farlo, ne capiremo gli strumenti fondamentali e ne otterremo una dimostrazione con un semplice esempio.

Primo passo: impostiamo un progetto Google

Molti concetti che incontreremo nel corso del tutorial rappresentano i fondamenti comuni per l’accesso a tutti i servizi Google. Uno di questi è la configurazione di un “progetto”, la controparte remota con cui la nostra app dialogherà. Questo deve essere fatto all’interno di un pannello web chiamato Google Developers Console cui potremo accedere con un normalissimo account Gmail che probabilmente già stiamo usando da tempo per la posta elettronica.

L’interfaccia che ci ospiterà serve a gestire l’insieme dei progetti Google che fanno da backend alle nostre applicazioni e se saremo al nostro primo accesso alla console probabilmente sarà vuoto. Creeremo il progetto tramite il pulsanse Create Project e la finestra di dialogo che si aprirà non chiederà altro che il nome da assegnargli. Tale identificativo è esclusivamente per uso “interno” alla console pertanto possiamo sceglierlo liberamente purchè abbia per noi un significato preciso.

Fatto ciò avremo accesso direttamente ad un pannello in cui potremo gestire le risorse che fanno parte del singolo progetto. Abbiamo bisogno di fare due cose qui:

  • abilitare le API per Google Calendar;
  • definire una chiave di accesso che permetterà alla nostra app il dialogo.

Per abilitare le API, apriremo una sezione denominata API Manager e cercheremo, come mostrato in figura, le Calendar API. Una volta trovate sarà sufficiente cliccarvi sopra e poi il tasto Enable API che apparirà immediatamente.

android-integrare-app-con-google-calendar_01

Per creare le chiavi di accesso apriremo il pannello Credentials dal menu laterale sinistro e chiederemo di avere un OAuth Client ID che fornirà un tipo di autenticazione in grado di concedere l’accesso agli account Google.

android-integrare-app-con-google-calendar_02

Osservando la figura vediamo che i dati da fornire sono:

  • il tipo di client ID che desideriamo: ovviamente, nel nostro caso sarà di tipo Android;
  • una chiave SHA1 che come spiegato nel pannello stesso potrà essere richiesta con il comando keytool fornendo come password android. L’output del programma conterrà una chiave etichettata con il nome SHA1 e quello sarà il valore da copiare nel campo di testo:android-integrare-app-con-google-calendar_03
  • il package Java che useremo nella nostra app Android.

A questo punto potrà essere creato il nostro client ID. Fondamentale ricordare che qualora il package realmente usato nel codice Java dell’app fosse diverso da quello inserito nella definizione delle credenziali Google, sarà necessario cambiarlo o creare un altro client ID OAuth2.

Configurazione del progetto Android

La configurazione del nostro progetto in Android Studio passerà invece per una corretta definizione del file build.gradle. Creando un nuovo progetto andrà benissimo quello fornito dall’IDE ma il blocco delle dipendenze dovrà richiedere il corretto set di librerie per la connessione ai servizi Google:

...
...
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.google.android.gms:play-services-identity:7.8.0'
    compile('com.google.api-client:google-api-client-android:1.20.0') {
        exclude group: 'org.apache.httpcomponents'
    }
    compile('com.google.apis:google-api-services-calendar:v3-rev125-1.20.0') {
        exclude group: 'org.apache.httpcomponents'
    }

}
...
...

Anche il file AndroidManifest.xml sarà piuttosto semplice ma dovremo fare attenzione a rispettare due regole:

  • al di fuori del nodo <application> predisporremo le giuste permission per l’accesso a Internet, la consultazione dello stato di Rete e la gestione di credenziali e account;
  • all’interno del nodo <application> inseriremo un blocco di tipo <meta-data> in cui sarà specificata, tramite una costante, la versione dei Google Play Services che stiamo utilizzando.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="it.devapp.googlecalendarintegration" >

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Struttura dell’esempio

Lo scopo del nostro esempio è vedere le fasi di accesso al Google Calendar da app Android. Lo faremo inserendo degli eventi in un calendario manualmente, ad esempio tramite il nostro smartphone, e recuperando dall’app gli eventi di un dato periodo e mostrandoli in una normale ListView. Non mostreremo nell’esempio le fasi dell’inserimento tramite codice ma, come accenneremo, useranno gli stessi strumenti della lettura.

Queste le fasi dell’esperimento:

  • nel metodo onCreate inizializzeremo Adapter e ListView che ci serviranno per mostrare i risultati dell’elaborazione e, successivamente, invocheremo la classe GoogleAccountCredential per l’accesso tramite OAuth2;
  • in onResume verificheremo la disponibilità dei Google Play Services nel dispositivo ed in caso affermativo invocheremo un Intent che mostrerà all’utente una finestra di dialogo per la scelta dell’account che possiede il calendario da gestire. Ovviamente se l’account non fosse ancora configurato sul dispositivo verrà richiesto all’utente di inserire le corrette credenziali;
  • effettuato l’accesso potremo svolgere la vera interrogazione a Google Calendar e lo faremo in background creando una derivazione della classe AsyncTask.

La query che effettueremo sul calendario restituirà una lista di oggetti Event ognuno dei quali contenente i soliti dati che siamo abituati ad inserire registrando a mano i nostri impegni.

Il nostro Adapter

Per visualizzare gli eventi, creeremo un nostro adapter che estende la classe ArrayAdapter. Di ogni evento verranno visualizzati solo due campi: il summary e la data di inizio dell’evento. Ovviamente sulla falsa riga di quanto faremo qui insieme l’esempio può essere espanso a volontà.

Questa la classe EventAdapter:

public class EventAdapter extends ArrayAdapter<Event>
{
    private List<Event> events;
    private Context context;
    private int layoutId;
    private SimpleDateFormat simple=new SimpleDateFormat("dd/MM/yyyy");

    public EventAdapter(Context context, int resource) {
        super(context, resource);
        this.context=context;
        layoutId=resource;
    }

    @Override
    public void addAll(Collection<? extends Event> collection) {
        clear();
        super.addAll(collection);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Event e=getItem(position);
        
        View v= LayoutInflater.from(context).inflate(layoutId, null);
        TextView txt_event= (TextView) v.findViewById(R.id.event);
        TextView txt_date= (TextView) v.findViewById(R.id.date);

        Calendar cal=Calendar.getInstance();
        DateTime dt=e.getStart().getDateTime();
        if (dt==null)
            dt=e.getStart().getDate();
        cal.setTimeInMillis(dt.getValue());

        txt_event.setText(e.getSummary());
        txt_date.setText(simple.format(cal.getTime()));
        return v;
    }
}

Il metodo getView presente in ogni Adapter è stato sottoposto a override per personalizzare la visualizzazione. Si noti che si controlla se il metodo getDateTime ha restituito un valore null in quanto ciò si verifica quando l’evento copre l’intera giornata e non solo alcune ore.

Il layout che da forma alle singole righe della ListView è molto semplice – due TextView in un LinearLayout – e verrà posto nel file di risorse /res/layout/row.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="15dp"
    android:background="#48B1F7"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF"
        android:textSize="20dp"
        android:textStyle="bold"
        android:id="@+id/event"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF"
        android:textSize="15dp"
        android:id="@+id/date"/>
</LinearLayout>

 

L’Activity

Infine arriviamo alla nostra Activity:

public class MainActivity extends ListActivity {
    static final int REQUEST_ACCOUNT_PICKER = 101;
    static final int REQUEST_GOOGLE_PLAY_SERVICES = 102;

    GoogleAccountCredential login;

    private static final String[] SCOPES = { CalendarScopes.CALENDAR_READONLY };

    private EventAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        adapter=new EventAdapter(this, R.layout.row);
        setListAdapter(adapter);
        getListView().setDividerHeight(10);

        login = GoogleAccountCredential.usingOAuth2(
                getApplicationContext(), Arrays.asList(SCOPES))
                .setBackOff(new ExponentialBackOff())
                .setSelectedAccountName(null);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (isGooglePlayServicesAvailable()) {
            if (login.getSelectedAccountName() == null) {
                startActivityForResult(login.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
            } else {
                if (isConnected()) {
                    new CalendarQueryTask(login).execute();
                }
            }
        }
    }

    @Override
    protected void onActivityResult(
            int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch(requestCode) {
            case REQUEST_GOOGLE_PLAY_SERVICES:
                if (resultCode != RESULT_OK) {
                    isGooglePlayServicesAvailable();
                }
                break;
            case REQUEST_ACCOUNT_PICKER:
                if (resultCode == RESULT_OK && data != null &&
                        data.getExtras() != null) {
                    String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                    if (accountName != null) {
                        login.setSelectedAccountName(accountName);
                    }
                }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    private boolean isConnected() {
        ConnectivityManager connMgr =
                (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        return (networkInfo != null && networkInfo.isConnected());
    }

    private boolean isGooglePlayServicesAvailable() {
        final int connectionStatusCode =
                GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
            GooglePlayServicesUtil.getErrorDialog(
                    connectionStatusCode,
                    this,
                    REQUEST_GOOGLE_PLAY_SERVICES).show();
            return false;
        } else if (connectionStatusCode != ConnectionResult.SUCCESS ) {
            return false;
        }
        return true;
    }

    private class CalendarQueryTask extends AsyncTask<Void, Void, List<Event>> {
        private com.google.api.services.calendar.Calendar mService = null;
        private ProgressDialog progress=null;

        public CalendarQueryTask(GoogleAccountCredential credential) {
            HttpTransport client = AndroidHttp.newCompatibleTransport();
            JsonFactory json = JacksonFactory.getDefaultInstance();
            mService = new com.google.api.services.calendar.Calendar.Builder(
                    client, json, credential)
                    .build();
        }

        @Override
        protected List<Event> doInBackground(Void... params) {
            try {
                DateTime now = new DateTime(System.currentTimeMillis());

                Events events = mService.events()
                        .list("primary")
                        .setMaxResults(10).setTimeMin(now).setOrderBy("startTime")
                        .setSingleEvents(true)
                        .execute();
                return events.getItems();
            } catch (Exception e) {
                // gestione dell'errore
                return null;
            }
        }

        @Override
        protected void onPreExecute() {

            progress=ProgressDialog.show(MainActivity.this,"Google Calendar", "Collegamento in corso...",true);
            progress.show();
        }

        @Override
        protected void onPostExecute(List<Event> output) {
            if (progress!=null)
                progress.dismiss();
            adapter.addAll(output);
        }
    }
}

Buona parte del funzionamento gira attorno al metodo onResume. In esso si controlla se è già stato associato un nome di account all’oggetto di classe GoogleAccountCredential che si occuperà del login presso il servizio. Se è ancora nullo si farà apparire una finestra con cui Android chiederà di selezionare un account presente nel sistema o di registrarne uno nuovo. Pronte le credenziali si eseguirà il task in background rappresentato dalla classe CalendarQueryTask. Questo richiederà i dati nel metodo doInBackground che agisce su un thread secondario mentre i metodi onPreExecute e onPostExecute si occuperanno, rispettivamente, di far apparire la finestra con la barra di progresso e di farla scomparire con contestuale aggiornamento dell’adapter.

Da notare che all’interno del costruttore di CalendarQueryTask viene allocato un oggetto Calendar che costituirà il nostro collegamento al servizio. Tramite questo potremo fare varie operazioni. Noi effettueremo una query con il metodo list invocato sulla collezione di eventi events e nello specifico chiederemo dieci eventi a partire dalla data di oggi.

I passi indicati nel codice come l’accesso tramite credenziali e la verifica della disponibilità dei Google Play Services nel terminale (metodo isGooglePlayServicesAvailable) incontrati nell’esempio sono utili sia in altri tipi di interazione con Calendar API sia nel dialogo con altri servizi di Big G.

Per effettuare la vera sperimentazione, potremo aprire l’app Calendar nel nostro dispositivo Android ed inserire manualmente un paio di eventi.

Uno per il 31 dicembre:

android-integrare-app-con-google-calendar_04

e l’altro per l’8 gennaio:

android-integrare-app-con-google-calendar_05

La nostra app mostrerà il seguente layout:

android-integrare-app-con-google-calendar_06

 

Conclusioni

Quello che abbiamo visto in questo tutorial ha una sua utilità ma non è che l’inizio. Consultando la documentazione delle API si potrà vedere come aggiungere tante altre funzionalità partendo comunque dagli stessi fondamenti: creazione di un progetto Google, gestione delle credenziali, collegamento al servizio ed infine invocazione dei metodi necessari.

Share this story:
  • tweet

Tags: android developersapi googlegoogle calendar androidgoogle play servicesprogrammatori AndroidTutorial Pratici

Recent Posts

  • Parte il percorso programmatori iOS in Swift su devACADEMY.it

    20 Dicembre 2017 - 0 Comment
  • Android, crittografare dati velocemente con Encryption

    24 Settembre 2018 - 0 Comment
  • Sql2o, accesso immediato ai database tramite Java

    3 Settembre 2018 - 0 Comment
  • Okio, libreria per ottimizzare l’input/output in Java

    27 Agosto 2018 - 0 Comment

Related Posts

  • Android: come risolvere l’errore del superamento del limite dei 64K metodi

    23 Febbraio 2017 - 0 Comment
  • Come fare il login su facebook dalle applicazioni Android

    11 Ottobre 2016 - 0 Comment
  • Glide, un image loader per Android

    26 Maggio 2016 - 0 Comment

Author Description

2 Responses to “Come integrare Google Calendar nelle applicazioni Android”

  1. 24 Gennaio 2017

    Nicola

    Ciao, la guida è veramente ottima…ma ho un problema! Quando avvio l’applicazione mi solleva questo errore net.apispark.webapi.googlecalendarapiexample.EventAdapter.addAll(EventAdapter.java:37)
    Sapresti darmi una mano?
    Saluti

  2. 28 Gennaio 2017

    Giuseppe Maggi

    Ciao, grazie dell’apprezzamento. Sull’errore sapresti darci qualche indicazione in più, magari riportando una porzione maggiore del testo restituito da Android Studio così da avere più informazioni sull’eccezione? Grazie

Leave a Reply

Your email address will not be published. Required fields are marked *


*
*

Corso online di programmazione android e java

SEZIONI

  • Android
  • Comunicazioni
  • Contest
  • Corsi ed Eventi
  • Corso completo di C
  • Corso programmazione videogiochi
  • Framework
  • Grafica e Design
  • Guida rapida alla programmazione Cocoa Touch
  • Guide Teoriche
  • Guide varie
  • iPad
  • Le nostre applicazioni
  • Libri e manuali
  • Materiale OpenSource
  • News
  • Pillole di C++
  • Progetti completi
  • Risorse utili
  • Strumenti di Sviluppo
  • Swift
  • Tips & Tricks
  • Tutorial Pratici
  • Video Tutorial
  • Windows Phone

Siti Amici

  • Adrirobot
  • Allmobileworld
  • Apple Notizie
  • Apple Tribù
  • Avvocato360
  • Blog informatico 360°
  • bubi devs
  • fotogriPhone
  • GiovaTech
  • iApp-Mac
  • iOS Developer Program
  • iPodMania
  • MelaRumors
  • Meritocracy
  • SoloTablet
  • TecnoUser
  • Privacy & Cookie Policy
©2009-2018 devAPP - All Rights Reserved | Contattaci
devAPP.it è un progetto di DEVAPP S.R.L. - Web & Mobile Agency di Torino
Str. Volpiano, 54 - 10040 Leini (TO) - C.F. e P.IVA 11263180017 - REA TO1199665 - Cap. Soc. € 10.000,00 i.v.

devACADEMY.it

Vuoi imparare a programmare?

Iscriviti e accedi a TUTTI i corsi con un’unica iscrizione.
Oltre 70 corsi e migliaia di videolezioni online e in italiano a tua disposizione.

ISCRIVITI SUBITO