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 JavaScript, Standard 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