Android (Client) – PHP (Server) Kommunikation
So gut wie jede App braucht heutzutage eine Verbindung zu einem Server. Apps die nur lokal am Gerät laufen sind einfach nicht mehr zeitgerecht. Man möchte ja seine Daten in irgend einer Art und Weise mit der Welt (oder anderen Geräten) teilen. Das geht von Cloud Diensten bei denen man Dokumente über verschiedene Geräte hinweg bearbeiten kann (man denke an Google Drive) oder einer einfachen Highscore Liste eines Spiels die auch global sein soll. Wie komplex das ganze auch sein mag. Es macht immer das Android Gerät zu einem Client und irgendwo steht ein Server mit dem man sich über das Internet verbindet und Daten austauscht.
Android (Client) – PHP (Server) Kommunikation
Wie funktioniert nun so ein Datenaustausch?
Funktionsweise
Für die Kommunikation verwenden wir ganz einfach das HTTP Protokoll. Damit können wir einfach Daten schicken. Im einfachsten Fall rufen wir eine URL auf und übergeben die Parameter als GET Parameter.
Die Kommunikation mit dem Server sieht schematisch so aus:
- erstellen des Requests (URL + Parameterliste)
- über HTTP den Request abschicken
- am Server wird dieser Request bearbeitet
- je nach Parameter wird ein Respons generiert und zurückgeschickt
- die Parameter müssen wir aus dem Response auslesen
Um hier nicht immer komplizierte Parameterlisten basteln zu müssen sollte man die Daten in einem üblichen Format schicken (sowohl an den Server als auch wieder zurück an den Client). Dafür gibt es mehrere Möglichkeiten. Am besten ist natürlich, man verwendet dafür einen Standard, für diesen es auch Funktionen gibt die dieses Format lesen und die Werte parsen können. Am besten eignen sich hier XML oder JSON. JSON ist vermutlich sogar einfacher, da es für uns Entwickler lesbarer ist.
Code
Server
Zuerst müssen wir auf unserem Server ein Script erstellen, dass über die URL aufgerufen wird. Dies ist im einfachsten Fall ein PHP Script, welches gar keine Parameter erwartet und einfach eine JSON formatierte Ausgabe zurückgibt. In diesem Fall einfach das Ergebnis einer SQL Abfrage einer MySQL Datenbank auf dem Server:
<?php mysql_connect("localhost","USERNAME","PASSWORD"); mysql_select_db("DATABASE"); $sql=mysql_query("SELECT * FROM TABLENAME"); while($row=mysql_fetch_assoc($sql)) $output[]=$row; print(json_encode($output)); mysql_close(); ?>
Im Code habe ich 4 Platzhalter stehen (USERNAME; PASSWORD; DATABASE und TABLENAME) die man durch die entsprechenden Werte der eigenen Datenbank ersetzen muss. Also Den Username und Passwort des Datenbankbenutzers, den Namen der Datenbank und den Namen der Tabelle, welche man abfragen will. Das Ergebnis ist eine JSON Formatierte Version des SQL Statements.
Android Client
Nachdem der Servercode nun steht fehlt noch der entsprechende Client Code.
public class TestActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String result = null; InputStream is = null; StringBuilder sb=null; //http post try{ HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("http://domain.com/AndroidTest/index.php"); HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); is = entity.getContent(); }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,"utf-8"),8); sb = new StringBuilder(); sb.append(reader.readLine() + "\n"); String line="0"; 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 int fd_id = 0; String fd_name = ""; try{ JSONArray jArray = new JSONArray(result); JSONObject json_data=null; for(int i=0;i<jArray.length();i++) { json_data = jArray.getJSONObject(i); fd_id = json_data.getInt("id"); fd_name = json_data.getString("login"); } }catch(JSONException e1){ Toast.makeText(getBaseContext(), "No Data Found", Toast.LENGTH_LONG).show(); }catch (ParseException e1){ e1.printStackTrace(); } //print received data TextView t = (TextView)findViewById(R.id.text); t.setText("ID: "+fd_id+" Name: "+fd_name); } }
Das ist eine automatisch generierte Activity eines Standard Android Projekts. Ich habe die onCreate Methode mit dem Code für die Abfrage der Daten vom Server erweitert. Das ganze erfolgt in 3 Schritten:
- HTTP Post
Zuerst fragen wie die Daten über ein HttpPost Objekt vom Server ab. Das Ergebnis speichern wir in einem InputStream. - String parsen
Wir erzeugen uns aus dem InputStream einen String. - JSON parsen
Der String entspricht dem Inhalt der JSON Datei. Diese parsen wir nun und holen uns die gewünschten Werte.
Zu guter letzt geben wir noch ID und Name einer Zeile der abgefragten Tabelle im TextView aus, welches im Standard Android Projekt mit erzeugt wird. Damit wir die TextView ansprechen können müssen wir diese im Layout noch durch eine ID ergänzen:
<TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"/>
vielen dank für dein Blog. hat echt weiter geholfen.
Genau das was ich gesucht habe – danke.
Vielen Danke für diesen Post, der hilft mir echt weiter.
Bin gerade in der Vorbereitungsphase zur Matura, und muss deswegen Android usw. lernen (aber auch aus eigenem Interesse ;)).
Du erklärst die Themen sehr gut, und fängst nicht ganz bei Null an, was ich persönlich gut finde, da dies immer wieder das selbe ist.
Auch die anderen Themen sind sehr interessant und gut erklärt 🙂
Du triffst den Nagel auf den Kopf
MfG Marco
Vielen Dank! Das motiviert mich natürlich, dass ich noch weitere Artikel zu meiner Android Tutorial Serie schreibe.
Hallo Werner Ziegelwanger,
Ich bin Android Anfänger und Suche nach genau solchen beispielen wie diesem Hier, ich möchte mein Webseiten Projekt gerne auf Android Portieren.
Ich bedanke mich für den Guten Anfang.
Konnte es noch nicht Testen, hoffe aber bald so ein paar anfragen an meinen Server senden zu können.
Jörg
P.S. hat du noch weitere Beispiele mit Zugriffen und Ausgaben von Webinhalten?
Hallo,
bei mir funktioniert die App nicht. Beim Start der App stürzt sie ab und es steht: „Test“ wurde beeendet.
Was habe ich falsch gemacht?
gute Frage! Welche Android Version nutzt du denn am Testgerät? Funktioniert die App im Simulator? Was sagen die Logs?
Gut erklärt, soweit funktioniert es bei mir, aber wie kann man mit der Android App Sachen auf einem Webserver speichern? (Z.B. nimmt man einen Wert aus einer Datenbank im Internet verarbeitet ihn und speichert ihn anschließend wieder in dieser Datenbank.)
Servus,
ich habe es genauso probiert, wie du. Jedoch erfolgslos 🙁
Mein Programm bricht in dem try{} ab:
//http post
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(„http://192.168.2.111/AndroidApp/MYSQL-VERSUCH/index.php“);
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
}
Weiß jemand was ich da falsch mache?
was gibt denn im Catch Block ein e.getMessage() aus?
05-13 13:54:53.110: E/log_tag(9195): Error in http connectionandroid.os.NetworkOnMainThreadException
Kannst du deine import-liste zeigen?
kann man dieses Script verwenden um ein bestimmtes Handy zu identifizieren.
das Skript dient dazu Daten vom Handy auf einem Server zu speichern. Ich habe aber einen anderen Artikel dazu geschrieben. Man kann ein Handy eindeutig durch seine Id identifizieren: Android Gerät eindeutig identifizieren. Kombiniert könnte man aus beiden Artikeln mitloggen, wann auf welchem Gerät die App aufgemacht wird…
Wie würde das nun aussehen wenn der Server nur SSL akzeptiert?
in der App statt http:// https:// verwenden und in der .htaccess eine http -> https Weiterleitung setzen.
Funktioniert nicht, a) http gibt es auf dem Server nicht nur https. Geb ich in der App https:// an erhalte ich ein Zertifikatsfehler.
dann dürfte es am SSL Zertifikat liegen
SSL Zertifikat ist sauber und kein selbstsigniertes.
In dem Fall wird es schwierig. Da müsste man prüfen was das für ein Zertifikat ist…also welche Version TLS und ob die Android Bibliothek dieses unterstützt. Zertifikatsfehler hatte ich bis jetzt nur bei selbst signierten bzw. abgelaufenen Zertifikaten.
In dem Fall wird es schwierig. Da müsste man prüfen was das für ein Zertifikat ist…also welche Version TLS und ob die Android Bibliothek dieses unterstützt. Zertifikatsfehler hatte ich bis jetzt nur bei selbst signierten bzw. abgelaufenen Zertifikaten.
Android gefällt mir im Grunde sehr, aber die verschiedenen Versionen nerven, gibt es irgendwo eine Auflistung, welche Klassen in welchen Versionen durch welche ersetzt wurden?
Hier geht nun HttpClient nicht, obwohl ich das Projekt vorsorglich für Lollipop (5.0) erstellt habe. Die Frage wäre, welche Version muss ich nehmen, um dieses Beispiel lauffähig zu bekommen? Klar kann ich die Klasse durch Android Studio ersetzen lassen, aber ….
Das ist ein schönes einfaches Beispiel. Es fehlt leider der Hinweis, dass das Beispiel für die Übertragung von sensiblen Daten ungeeignet ist. Alle Informationen werden als plain text übertragen und sind damit potentiell ohne größere Schwierigkeiten auslesbar. Zudem ist auch die PHP Seite nicht weiter geschützt. Selbstverständlich dient dieses Beispiel sehr gut als Einstieg, aber ein Warnhinweis sollte nicht fehlen.
Stimmt. Ist aber in der Tat ein Anfängertutorial in dem ich den Leser nicht mit HTTPS, Crypto und sonst was erschlagen möchte. Ein „Hallo Welt“ ist auch doof und fernab jeglichem Praxisbezug.