GCM Google Cloud Messaging con Android Server/Client side CCS (XMPP)

Ciao a tutti ragazzi, anche se sono impegnato in nuovi progetti cerco sempre di essere presente. Attualmente ringrazio tutti quelli che provano i codici sorgenti che inserisco e che mi chiedono informazioni per eventuali bug.

Il progetto su cui sto lavorando riguarda il Google Cloud Messaging, non con il normale protocollo HTTP bensì con il protocollo XMPP (eXtensible Message and Presence Protocol) usando CCS( Cloud Connection Server).  Questo stesso acronimo identifica il motivo per il quale userò questo protocollo, perché mette a disposizione la possibilità da parte del Client di inviare file al Server.

Questo sarà un blog lungo perchè accompagnerà man mano il mio progetto, quindi errori, soluzioni, strategie saranno all’ordine del giorno…

Inizio col dirvi che importantissimo per creare la vostra applicazione che usi GCM dovete prima di tutto comunicare al Signor Google la vostra intenzione di usare il Suo cloud, a meno che non avete un vostro cloud personale (cosa figa da gestire).

Quindi iniziamo:

Google Cloud Messaging (GCM) consente di comunicare rapidamente con i dispositivi mobili Android. GCM consente di inserire i comandi direttamente per i dispositivi Android.

Quindi impostare GCM :

Bisogna creare un nuovo progetto sul sito di Google API, ottenere il numero di progetto ID, e generare una chiave del server API di Google.

Per creare un nuovo progetto e di ottenere il numero di server e API chiave del progetto ID

Vai a https://code.google.com/apis/console, accedi al tuo account Google e fare clic su Crea progetto.

Sul lato sinistro della pagina Dashboard API, fare clic sul menu a discesa e selezionare Crea.

Digitare un nome per il progetto, e fare clic su Crea progetto.

Il browser si aggiorna e visualizza un nuovo URL.

Nel URL, individuare l’elemento #project.

Registrare il numero che segue #project.

Per esempio:

https://console.google.com/apis/console/#project:1066916068160

Questo numero è chiamato il “Google Project ID”, ed è necessario per utilizzare GCM.

Selezionare il progetto dall’elenco a discesa API progetto, e nel riquadro a sinistra selezionare Servizi.

Scorrere la pagina di Google Cloud Messaging per Android, e impostare l’ON / OFF widget per ON.

Su Google API Condizioni di pagina servizio, accettare e accettare i termini del contratto.

Nel riquadro a sinistra, selezionare API Access e quindi fare clic su Crea nuova chiave Server.

Per impostare in modo esplicito i server che possono utilizzare GCM, digitare l’indirizzo IP di ogni server.

Digitare un solo indirizzo IP per riga. Se non si aggiunge un indirizzo IP, viene utilizzato l’indirizzo del computer che si utilizza per accedere al sito web di Google API. Controllare la documentazione di Google per ulteriori informazioni.

Fare clic su Crea.

La chiave del server viene visualizzato nella pagina di accesso API sotto chiave per le applicazioni server (con bloccaggio IP) come API Key. Registrare la stringa chiave del server da utilizzare nella procedura successiva. Questa API Key è necessario quando si configura il proprio progetto per utilizzare GCM e quindi effettuare il collegamento al cloud.

Quanto prima proseguirò

Android: Connessione a MySQL usando PHP

Il motivo principale per l’adozione di un linguaggio di scripting come PHP è dovuto all’interazione con i database.

In questo tutorial vi mostrerò come utilizzare PHP e database MySQL per recuperare informazioni dal server. Per effettuare il collegamento a script PHP, utilizzeremo il protocollo HTTP dal sistema android. Inutile dirvi che comunque per implementare questo tutorial si dovrebbe avere una conoscenza di base di come eseguire script PHP e avviare il server. Se parliamo di architettura client-server, il dispositivo client è l’Android e lato server vi è una combinazione di script PHP e MySQL.

Durante il tutorial useremo un formato importantissimo per lo scambio leggero dei dati, ossia il formato JSON (JavaScript Object Notation).

Piccola premessa sul JSON:

Si basa su un sottoinsieme del Linguaggio di Programmazione JavaScriptStandard ECMA-262 Terza Edizione – Dicembre 1999 (testo sito json). JSON è un formato di testo completamente indipendente dal linguaggio di programmazione, ma utilizza convenzioni conosciute dai programmatori di linguaggi della famiglia del C, come C, C++, C#, Java, JavaScript, Perl, Python, e molti altri. Questa caratteristica fa di JSON un linguaggio ideale per lo scambio di dati.

JSON è basato su due strutture:

  • Un insieme di coppie nome/valore. In diversi linguaggi, questo è realizzato come un oggetto, un record, uno struct, un dizionario, una tabella hash, un elenco di chiavi o un array associativo.
  • Un elenco ordinato di valori. Nella maggior parte dei linguaggi questo si realizza con un array, un vettore, un elenco o una sequenza.

Come farà la nostra applicazione ad usare json?

Quando l’applicazione Android effettuerà la richiesta alla pagina PHP e rimarrà in attesa. Lo script PHP, si connetterà al DB, invierà la query, recupererà la risposta, inserirà la risposta in un oggetto json e lo darà come output. Questo output sarà codificato in formato JSON e inviato al dispositivo. L’applicazione Android otterrà questi dati codificati, li analizzerà e li visualizzerà sul dispositivo Android.

Implementiamo il tutto:

In MySQL creare il database TSA_Evolution, creare tabella Stock. Questa tabella consiste di due colonne. In primo luogo è Stock_id, che è auto_increment e primary_key e avere tipo di dati INT. Seconda colonna è Stock_name, che ha tipo di dati VARCHAR (20).

La query sarà: Vogliamo SELEZIONARE il tutti gli IDENTIFICATIVI delle azioni DALLA nostra TABELLA Stock CHE INIZINO con la lettera A (in maiuscolo ho praticamente evidenziato la query che andremo ad effettuare, ossia:

SELECT Stock_id

FROM Stock

WHERE Stock_name= A

)

Il codice PHP sarà molto semplice:

  • connessione al database
  • esecuzione della query SQL, con il WHERE  a seconda dei dati da POST / GET
  • output in formato JSON

Per esempio avremo questa funzionalità in city.php:

<?

/*ci colleghiamo al database(attenti perchè se lavorate in locale 
l'host è 10.0.2.2 e non 127.0.0.1)*/
php mysql_connect("host","username","password"); 
//selezioniamo il db a cui ci vogliamo connettere
mysql_select_db("TSA_Evolution");
//creamo al query
$sql=mysql_query("select Stock_id from Stock where STOCK_name like 'A%'"); 
/*Il metodo "mysql_fetch_assoc" restituisce un array in base alla query 
fatta e incrementa il dato*/
while($row=mysql_fetch_assoc($sql)) 
//inseriamo tutto nella variabile output
$output[]=$row;
/*stampiamo l'oggetto json, miraccomando a non stampare a video altri commenti, 
altrimenti quando andremo ad eseguire l'app android si bloccherà in quanto non 
riconoscerà i commenti come caratteri json*/
 print(json_encode($output)); 
//chiudiamo la connessione
mysql_close();

?>

Nella nostra applicazione Android dobbiamo:

  • usare un HttpPost per ottenere i dati,
  • convertire la risposta alla stringa JSON
  • analizzare i dati e usarli

Il codice per recuperare dati dal server per la nostra applicazione Android sarà:

package com.list; 

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.ArrayList;

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair; 
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;import android.app.ListActivity; 
import android.net.ParseException;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast; 
public class AndroidPhp extends Activity { /*qualcuno qui ha esteso ad una 
ListActivity ma io preferisco gestirmi da me la risposta*/
JSONArray jArray;
String result = null; 
InputStream is = null; 
StringBuilder sb=null; 

@Override
public void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.android_php);
final TextView textviewDariRicevuti = (TextView) findViewById(R.id.datiRicevuti);
Button buttonInviaDati = (Button) findViewById(R.id.buttonInviaDati);
buttonInviaDati.setOnClickListener(new View.OnClickListener() { 
@Override
public void onClick(View v) {
//invio richiesta
textviewDariRicevuti.setText(inviaDati());
}
});
}
public String inviaDati(){
String result="";
String stringaFinale="";
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
//Sotto scrivo come si chiama il campo che invio(azione1) e il suo valore (1)
nameValuePairs.add(new BasicNameValuePair("Stock_name","azione1"));
/*queste due righe di codice che vedete qui sotto sono un piccolo trucchetto per ovviare
 (solo per il momento
 all'eccezione “NetworkOnMainThreadException", questa eccezione è importantissima in quanto
 ci dice che siccome stiamo effettuando una connessione nel thread principale avremo dei 
problemi in quanto tutto ciò che riguarda le connessioni o tutto ciò che comporta il 
superamento del limite di tempo massimo tra richiesta/risposta superiore a 5secondi la nostra 
applicazione Android la metterà in pausa appunto perchè stiamo programmando per uno smartphone
 e non possiamo attendere processi che impegnino per troppo tempo la nostra app. Ricordatevi
 una volta testato tutto, create nella classe i thread e gestite tutto dal thread.*/
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
//http post 
try { 
HttpClient httpclient = new DefaultHttpClient(); 
HttpPost httppost = new HttpPost("http://10.0.2.2/interroga.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
result = EntityUtils.toString(entity, HTTP.UTF_8);
}
catch(Exception e){ 
Log.e("log_tag", "Error in http connection"+e.toString());
} 
//convert response to string 
try{ 
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8); 
sb = new StringBuilder();
sb.append(reader.readLine() + "\n"); 
String line=null; 
while ((line = reader.readLine()) != null) 
{ sb.append(line + "\n");
} 
is.close();
result=sb.toString(); 
}
catch(Exception e){ 
Log.e("log_tag", "Error converting result "+e.toString());
}
//paring data 

try{ 
jArray = new JSONArray(result); 
/*Quando vi dicevo di non inserire commenti nella pagina php era perchè l'app si
 bloccava proprio su questa
riga, in quanto "result" NON comprendeva caratteri json e il parsing non poteva 
essere effettuato */
JSONObject json_data=null;
for(int i=0;i<jArray.length();i++){
Log.i("TEST","id: "+json_data.getInt("Stock_id")+
", name: "+json_data.getString("Stock_name")+
", cliente: "+json_data.getString("Stock_Client_id")+
", industria: "+json_data.getString("Stock_Industry_id")
);
stringaFinale = json_data.getInt("Stock_id")+ ""+ json_data.getString("Stock_name")+
""+ json_data.getString("Stock_Client_id")+
""+ json_data.getString("Stock_Industry_id")+"\n\n";
}
} catch(JSONException e1){ 
Toast.makeText(getBaseContext(), "Titolo Azionario non trovato" ,Toast.LENGTH_LONG).show();
} catch (ParseException e1) { e1.printStackTrace();
}
}
else { //is è null e non ho avuto risposta
}
return stringaFinale;
}
}

Non me ne vogliano i più esperti ma preferisco fornire una guida completa inserendo anche il Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/buttonInviaDati"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Invia dati" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Dati ricevuti:"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/datiRicevuti"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Per ora nessun dato ricevuto" />

</LinearLayout>

Non dimenticatevi di inserire il permesso alla connessione internet in AndroidManifest.xml:

<uses-permission android:name=”android.permission.INTERNET”></uses-permission>

Provateci e fatemi sapere come è andata, aspetto i vostri commenti..

😉 Good Luck

Alessio Scannicchio