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