kosmus
Erfahrenes Mitglied
- 62
Da es in letzter Zeit häufig Fragen zum Thema Zugriff auf Daten im Internet gab, habe ich mal eine kleine App erstellt um ein paar Basics zu vermitteln.
Der Quellcode kann nach Belieben weiterverwendet werden, die App ist jedoch nur für das Tutorial entwickelt und aus verschiedenen Gründen nicht für den Echtbetrieb geeignet.
Wie die Überschrift schon vermuten lässt werde ich hier vier Sachen zeigen:
- Zugriff auf eine MySQL Datenbank mittels PHP (Select, Insert, Update und Delete).
- HTTP Verbindung in einem ASync Task
- Verarbeiten einer Antwort im JSON Format
- Darstellung in einer ListView mit eigenem Adapter
Ich unterstelle dabei, dass ihr Grundkenntnisse in SQL und Java habt.
Die App greift auf eine in einer MySQL DB abgelegten To Do Liste zu. Sie kann alle Einträge anzeigen, neue Einträge anlegen, Einträge ändern und Einträge löschen. Eine Vorschau wie die App mit dem ListView aussieht habe ich mal angehängt.
Die Serverseite:
Ihr braucht einen Server (bzw. Platz auf einem Server) der PHP verarbeiten kann und eine MySQL Datenbank. Zum Entwickeln und Testen könnt ihr XAMPP benutzen (einfach mal Google fragen).
Die App erwartet eine Tabelle mit zwei Spalten (ID und Eintrag):
Zoopa hat mir noch den Tipp gegeben, dass ihr für ID noch AUTO_INCREMENT mitgeben könnt, dann könnt ihr euch im Insert Skript (siehe unten) auch das ermitteln der nächsten freien ID sparen
Als nächsten braucht man ein paar PHP Scripte. Die Ausgaben der Skripte sind im JSON Format und können später von der App gelesen werden. Jede Antwort in meinen PHP Skripten hat ein JSON Array mit Namen Status, dieses besteht aus einer Zahl und einem String.
-1 steht für Fehlermeldungen,
0 für einen erfolgreichen Select Befehl
1 für einen erfolgreichen Insert Befehl
2 für einen erfolgreichen Update Befehl
3 für einen erfolgreichen Delete Befehl
So kann die App dann zur Laufzeit entscheiden, wie sie die Antwort weiterverarbeiten soll. Diese Werte entsprechen keinem mir bekannten Standard, je nachdem wie ihr die Weiterverarbeitung gestaltet braucht ihr mehr oder weniger Status Meldungen oder könnt sogar ganz darauf verzichten.
Dieses erste Skript stellt eine Verbindung zur Datenbank her:
Servername, User und Passwort müssen natürlich entsprechend angepasst werden.
ui_3k1 hat mich darauf hingewiesen, dass es Fehler mit Sonderzeichen geben könnte, deshalb ist es Sinnvoll mit mysql_query("SET NAMES 'utf8'"); die Zeichensatzkodierung einzustellen.
Mit include kann dieses Skript in die anderen eingebunden werden, sodass man nicht immer alles neu doppelt und dreifach schreiben muss.
Das nächste Skript setzt einen Select Befehl ab und gibt die Antwort im JSON Format zurück. Der Antwort enthält neben dem Status Array ein zweites Array mit dem Namen Liste. Hier drin befinden sich alle Einträge aus der To Do Liste.
Achtet darauf, dass die Datenbank Verbindung am Ende auch getrennt wird.
In diesem Skript wird der JSON String mit json_encode() erzeugt, sodass man ihn nicht mühsam von Hand zusammen bauen muss.
Das nächsten drei Skripte sind sehr ähnlich, sie verbinden sich mit der DB setzen eine Query ab und trennen die Verbindung danach wieder. Sie liefern alle eine Antwort mit dem oben erläuterten Status Array.
Die benötigten Variablen werden über HTTP dabei mit der POST Methode übermittelt, man kann natürlich auch GET verwenden denn findet man die Variablen nicht in $_POST[] sondern in $_GET[]. Die Skripten prüfen vor dem Verbindungsaufbau mit der DB ob alle benötigten Variablen auch übermittelt wurden.
Insert für einen neuen Eintrag in der Liste:
Update um einen Eintrag zu bearbeiten:
Und Delete zum Löschen eines Eintrags:
Damit ist die Serverseite fertig.
Die Android App:
Der XML Teil
Ich fange mal mit den XML Dateien an, diese sind sehr einfach:
Eine XML Datei für das Layout der MainActivity. Diese besteht nur aus einem ListView:
Dann braucht man noch eine Layout-Datei für einzelnen Listeneinträge. Diese besteht bei mir aus einem TextView und zwei ImageButtons.
Beachtet, dass ich den Button bereits in der XML-Datei onClick Methoden zuweise.
Es ist natürlich kein schöner Stil die Größe des Textes und die Beschreibung für ScreenReader direkt in die XML zu schreiben, aber für dieses kleine Tutorial, lass ich es mal so stehen.
In der XML für das Menü habe ich einen Button für die ActionBar zum Erzeugen eines neuen Eintrags in die To Do Liste.
Im Manifest braucht man noch die Erlaubnis zum Zugriff aus Internet, damit man mit dem Server kommunizieren kann:
Der Java Teil:
Fangen wir mit den leichten Sachen an. Eine Klasse für einen Datenbankeintrag mit Gettern und Settern:
Als nächstes kommt der Adapter um die Einträge in einer ListView darzustellen. Mein Adapter erbt vom BaseAdapter und hat als zusätzliches Attribut eine ArrayList mit den Datenbankeinträgen. Man kann alternativ auch einen ArrayAdapter verwenden, doch mir persönlich gefällt es so besser.
Das Wichtigste findet in der getView Methode statt. Deshalb möchte ich diese kurz erläutern. Sofern von Listeneinträge vorhanden sind, befindet sich im parameter convertView ein View mit dem weiter gearbeitet werden kann. Ist der ListView bisher leer, der convertView null. In diesem Fall muss mit dem LayoutInflator ein neuer View erzeugt werden. Beachtet, dass ich den Button an dieser Stelle mit setTag() den konkreten Eintrag mitgebe. So kann dieser in den onClick Methoden mit getTag() zur Weiterverarbeitung wieder gefunden werden.
Es wird von der MainActivity implementiert(siehe unten);
Mein AsyncTask nimmt als Parameter im Konstruktor jede Klasse die das Interface implementiert an. So kann dann die Methode zur Verarbeitung nach Ablauf des Tasks ausgeführt werden. Als Parameter für die execute() bzw. doInBackground() Methode werden Strings erwartet. Als erster String muss die URL für die HTTP Verbnindung übergeben werden. Danach können beliebig viele POST Variablen übergeben werden, die dann an den Server übermittelt werden. Auch diese sind als String zu übergeben. Dabei ist immer als String erst der variablen Name und dann der Wert zu übergeben. Falls ihr diese Klasse auch weiterverwenden wollt, habe ich das auch nochmal als Java Doc Kommentar in die Klasse geschrieben.
Zum Schluss kommen wir zur MainActivity. Diese benutzt meinen DBRequestTask an verschiedenen Stellen mit verschiedenen URLS und Parametern um die unterschiedlichen PHP Skripte auf meinem Server aufzurufen. Der DBRequestTast ruft dabei jeweils die ergebnisVerarbeiten verarbeiten Methode meiner MainActivity auf und übergibt als String was vom Server als Antwort zurückgekommen ist. Dieser String wird dann in ein JSON Objekt gepackt, damit er leichter verarbeitet werden kann. Zunächst wird dann aus dem JSON Objekt das Status Array geholt um zu entscheiden, wie die Serverantwort verarbeitet werden muss. Beim Status 0 (erfolgreicher Select Befehl) wird dann das Liste Array verarbeitet. Für jeden Listeneintrag wird ein Eintrag Objekt erzeugt und Eintragliste im eintragAdapter gehangen. Zum Schluss wird die notifyDataSetChanged() Methode des Adapters aufgerufen, damit der ListView seine Anzeige aktualisiert.
Ich hoffe dieses Beispiel hilft euch bei der Entwicklung eurer Apps weiter. Bitte Beachtet das Strings die Datenbanken übergeben werden, vorher geprüft werden sollten, damit keine sql injection durchgeführt werden kann. Darauf habe ich bei diesem kleinen Beispiel verzichtet.
Der Quellcode kann nach Belieben weiterverwendet werden, die App ist jedoch nur für das Tutorial entwickelt und aus verschiedenen Gründen nicht für den Echtbetrieb geeignet.
Wie die Überschrift schon vermuten lässt werde ich hier vier Sachen zeigen:
- Zugriff auf eine MySQL Datenbank mittels PHP (Select, Insert, Update und Delete).
- HTTP Verbindung in einem ASync Task
- Verarbeiten einer Antwort im JSON Format
- Darstellung in einer ListView mit eigenem Adapter
Ich unterstelle dabei, dass ihr Grundkenntnisse in SQL und Java habt.
Die App greift auf eine in einer MySQL DB abgelegten To Do Liste zu. Sie kann alle Einträge anzeigen, neue Einträge anlegen, Einträge ändern und Einträge löschen. Eine Vorschau wie die App mit dem ListView aussieht habe ich mal angehängt.
Die Serverseite:
Ihr braucht einen Server (bzw. Platz auf einem Server) der PHP verarbeiten kann und eine MySQL Datenbank. Zum Entwickeln und Testen könnt ihr XAMPP benutzen (einfach mal Google fragen).
Die App erwartet eine Tabelle mit zwei Spalten (ID und Eintrag):
Code:
CREATE TABLE IF NOT EXISTS `ToDoListe` (
`ID` int(4) NOT NULL,
`Eintrag` varchar(32) NOT NULL
);
Zoopa hat mir noch den Tipp gegeben, dass ihr für ID noch AUTO_INCREMENT mitgeben könnt, dann könnt ihr euch im Insert Skript (siehe unten) auch das ermitteln der nächsten freien ID sparen
Als nächsten braucht man ein paar PHP Scripte. Die Ausgaben der Skripte sind im JSON Format und können später von der App gelesen werden. Jede Antwort in meinen PHP Skripten hat ein JSON Array mit Namen Status, dieses besteht aus einer Zahl und einem String.
-1 steht für Fehlermeldungen,
0 für einen erfolgreichen Select Befehl
1 für einen erfolgreichen Insert Befehl
2 für einen erfolgreichen Update Befehl
3 für einen erfolgreichen Delete Befehl
So kann die App dann zur Laufzeit entscheiden, wie sie die Antwort weiterverarbeiten soll. Diese Werte entsprechen keinem mir bekannten Standard, je nachdem wie ihr die Weiterverarbeitung gestaltet braucht ihr mehr oder weniger Status Meldungen oder könnt sogar ganz darauf verzichten.
Dieses erste Skript stellt eine Verbindung zur Datenbank her:
PHP:
<?php
$verbindung = mysql_connect ("servername",
"user", "passwort")
or die ('{"Status":["-1","Verbindung zum Server Fehlgeschlagen"]}');
mysql_select_db("meineTestDB")
or die ('{"Status":["-1","Datenbank nicht gefunden"]}');
mysql_query("SET NAMES 'utf8'");
?>
Servername, User und Passwort müssen natürlich entsprechend angepasst werden.
ui_3k1 hat mich darauf hingewiesen, dass es Fehler mit Sonderzeichen geben könnte, deshalb ist es Sinnvoll mit mysql_query("SET NAMES 'utf8'"); die Zeichensatzkodierung einzustellen.
Mit include kann dieses Skript in die anderen eingebunden werden, sodass man nicht immer alles neu doppelt und dreifach schreiben muss.
Das nächste Skript setzt einen Select Befehl ab und gibt die Antwort im JSON Format zurück. Der Antwort enthält neben dem Status Array ein zweites Array mit dem Namen Liste. Hier drin befinden sich alle Einträge aus der To Do Liste.
PHP:
<?php
include("connect.php");
// SQL Query abschicken
$result = mysql_query("SELECT * FROM ToDoListe");
//Schleife bis alle Eintragungen in Array gespeichert
$listenArray["Liste"] = array();
while($row = mysql_fetch_array($result)) {
$listeneintrag = array();
$listeneintrag["ID"] = $row["ID"];
$listeneintrag["Eintrag"] = $row["Eintrag"];
array_push($listenArray["Liste"], $listeneintrag);
}
//Ausgabe im JSON Format
$listenArray["Status"] = ["0","Select erfolgreich"];
echo json_encode($listenArray);
//Verbindung trennen.
mysql_close($verbindung);
?>
In diesem Skript wird der JSON String mit json_encode() erzeugt, sodass man ihn nicht mühsam von Hand zusammen bauen muss.
Das nächsten drei Skripte sind sehr ähnlich, sie verbinden sich mit der DB setzen eine Query ab und trennen die Verbindung danach wieder. Sie liefern alle eine Antwort mit dem oben erläuterten Status Array.
Die benötigten Variablen werden über HTTP dabei mit der POST Methode übermittelt, man kann natürlich auch GET verwenden denn findet man die Variablen nicht in $_POST[] sondern in $_GET[]. Die Skripten prüfen vor dem Verbindungsaufbau mit der DB ob alle benötigten Variablen auch übermittelt wurden.
Insert für einen neuen Eintrag in der Liste:
PHP:
<?php
//Prüfen ob die über HTTP übermittelten Werte vorhanden sind
if(isset($_POST["Eintrag"])) {
$Eintrag = $_POST["Eintrag"];
//Mit DB Verbinden
include("connect.php");
//Nächste freie ID ermitteln
$ID = mysql_result(
mysql_query("SELECT MAX(ID) FROM ToDoListe") ,0);
$ID++;
// SQL Query abschicken
$result = mysql_query("INSERT INTO ToDoListe (ID, Eintrag) VALUES ('$ID','$Eintrag')");
//Erfolg prüfen
if ($result) {
echo '{"Status":["1","Insert erfolgreich"]}';
} else {
echo '{"Status":["-1","Insert fehlgeschlagen"]}';
}
//Verbindung Trennen
mysql_close($verbindung);
}
else {
//Fehler falls die über HTTP übermittelten Werte nicht vorhanden
echo '{"Status":["-1","Daten wurden nicht verschickt"]}';
}
?>
Update um einen Eintrag zu bearbeiten:
PHP:
<?php
//Prüfen ob die über HTTP übermittelten Werte vorhanden sind
if(isset($_POST["Eintrag"]) && isset($_POST["ID"])) {
$Eintrag = $_POST["Eintrag"];
$ID = $_POST["ID"];
//Mit DB Verbinden
include("connect.php");
// SQL Query abschicken
$result = mysql_query("UPDATE ToDoListe SET Eintrag = '$Eintrag' WHERE ID = '$ID'");
//Erfolg prüfen
if ($result) {
echo '{"Status":["2","Update erfolgreich"]}';
} else {
echo '{"Status":["-1","Update fehlgeschlagen"]}';
}
//Verbindung Trennen
mysql_close($verbindung);
}
else {
//Fehler falls die über HTTP übermittelten Werte nicht vorhanden
echo '{"Status":["-1","Daten wurden nicht verschickt"]}';
}
?>
Und Delete zum Löschen eines Eintrags:
PHP:
<?php
//Prüfen ob die über HTTP übermittelten Werte vorhanden sind
if(isset($_POST["ID"])) {
$ID = $_POST["ID"];
//Mit DB Verbinden
include("connect.php");
// SQL Query abschicken
$result = mysql_query("DELETE FROM ToDoListe WHERE ID = '$ID'");
//Erfolg prüfen
if ($result) {
echo '{"Status":["3","Delete erfolgreich"]}';
} else {
echo '{"Status":["-1","Delete fehlgeschlagen"]}';
}
//Verbindung Trennen
mysql_close($verbindung);
}
else {
//Fehler falls die über HTTP übermittelten Werte nicht vorhanden
echo '{"Status":["-1","Daten wurden nicht verschickt"]}';
}
?>
Damit ist die Serverseite fertig.
Die Android App:
Der XML Teil
Ich fange mal mit den XML Dateien an, diese sind sehr einfach:
Eine XML Datei für das Layout der MainActivity. Diese besteht nur aus einem ListView:
Code:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="kosmus.example.todoliste.MainActivity"
tools:ignore="MergeRootFrame" />
Dann braucht man noch eine Layout-Datei für einzelnen Listeneinträge. Diese besteht bei mir aus einem TextView und zwei ImageButtons.
Beachtet, dass ich den Button bereits in der XML-Datei onClick Methoden zuweise.
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/eintragTextView"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text=""
android:textSize="20dip" />
<ImageButton
android:id="@+id/editButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="bearbeiten"
android:onClick="doEdit"
android:src="@android:drawable/ic_menu_edit" />
<ImageButton
android:id="@+id/deleteButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="löschen"
android:onClick="doDelete"
android:src="@android:drawable/ic_menu_delete" />
</LinearLayout>
Es ist natürlich kein schöner Stil die Größe des Textes und die Beschreibung für ScreenReader direkt in die XML zu schreiben, aber für dieses kleine Tutorial, lass ich es mal so stehen.
In der XML für das Menü habe ich einen Button für die ActionBar zum Erzeugen eines neuen Eintrags in die To Do Liste.
Code:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="kosmus.example.todoliste.MainActivity" >
<item
android:id="@+id/hinzufuegenButton"
android:icon="@android:drawable/ic_menu_add"
android:showAsAction="always"
android:title="Neuer Eintrag">
</item>
</menu>
Im Manifest braucht man noch die Erlaubnis zum Zugriff aus Internet, damit man mit dem Server kommunizieren kann:
Code:
<uses-permission android:name="android.permission.INTERNET" />
Der Java Teil:
Fangen wir mit den leichten Sachen an. Eine Klasse für einen Datenbankeintrag mit Gettern und Settern:
Code:
public class Eintrag {
private int id;
private String eintrag;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEintrag() {
return eintrag;
}
public void setEintrag(String eintrag) {
this.eintrag = eintrag;
}
public Eintrag(int id, String eintrag) {
this.id = id;
this.eintrag = eintrag;
}
}
Als nächstes kommt der Adapter um die Einträge in einer ListView darzustellen. Mein Adapter erbt vom BaseAdapter und hat als zusätzliches Attribut eine ArrayList mit den Datenbankeinträgen. Man kann alternativ auch einen ArrayAdapter verwenden, doch mir persönlich gefällt es so besser.
Code:
public class EintragAdapter extends BaseAdapter {
private ArrayList<Eintrag> eintragListe;
private Context context;
public EintragAdapter(Context context) {
super();
this.eintragListe = new ArrayList<Eintrag>();
this.context = context;
}
public ArrayList<Eintrag> getEintragListe() {
return eintragListe;
}
@Override
public int getCount() {
return eintragListe.size();
}
@Override
public Object getItem(int position) {
return eintragListe.get(position);
}
@Override
public long getItemId(int position) {
return eintragListe.get(position).getId();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.eintrag_layout, parent, false);
}
TextView textView = (TextView) view.findViewById(R.id.eintragTextView);
textView.setText(eintragListe.get(position).getEintrag());
View deleteButton = view.findViewById(R.id.deleteButton);
deleteButton.setTag(eintragListe.get(position));
View editButton = view.findViewById(R.id.editButton);
editButton.setTag(eintragListe.get(position));
return view;
}
}
Code:
public interface DBResultHandler {
public void ergebnisVerarbeiten(String ergebnis);
}
Mein AsyncTask nimmt als Parameter im Konstruktor jede Klasse die das Interface implementiert an. So kann dann die Methode zur Verarbeitung nach Ablauf des Tasks ausgeführt werden. Als Parameter für die execute() bzw. doInBackground() Methode werden Strings erwartet. Als erster String muss die URL für die HTTP Verbnindung übergeben werden. Danach können beliebig viele POST Variablen übergeben werden, die dann an den Server übermittelt werden. Auch diese sind als String zu übergeben. Dabei ist immer als String erst der variablen Name und dann der Wert zu übergeben. Falls ihr diese Klasse auch weiterverwenden wollt, habe ich das auch nochmal als Java Doc Kommentar in die Klasse geschrieben.
Code:
/**
*
* beim Aufruf von Execute muss als erster String die URL mitgegeben werden. In
* den Strings danach können bei Bedarf Name und Wert von Variablen mitgegeben
* werden, die über die POST Methode an den Server übergeben werden sollen.
* Beispiel für einen Aufruf:
* new DBRequestTask(this)).execute(URLString,VarNameString, VarWertString)
*/
public class DBRequestTask extends AsyncTask<String, Void, String> {
private DBResultHandler handler;
public DBRequestTask(DBResultHandler handler) {
super();
this.handler = handler;
}
@Override
protected String doInBackground(String... params) {
String ergebnis = "";
try {
if (params.length % 2 == 0)
throw new Exception("Gerade Zahl an params ist nicht logisch");
URL url = new URL(params[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
if (params.length > 1) {
StringBuilder postDaten = new StringBuilder();
boolean erster = true;
for (int i = 1; i < params.length; i = i + 2) {
if (erster) {
erster = false;
} else {
postDaten.append("&");
}
postDaten.append(URLEncoder.encode(params[i], "UTF-8"));
postDaten.append("=");
postDaten.append(URLEncoder.encode(params[i + 1], "UTF-8"));
}
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(postDaten.toString());
writer.flush();
writer.close();
os.close();
}
conn.connect();
StringBuilder antwort = new StringBuilder("");
InputStream inputStream = conn.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream,
"UTF-8");
char[] buffer = new char[128];
while (reader.read(buffer) > 0) {
antwort.append(buffer);
}
inputStream.close();
ergebnis = antwort.toString();
} catch (Exception e) {
ergebnis = "{\"Status\":[\"-1\",\"HTTP Connection Problem\"]}";
}
return ergebnis;
}
@Override
protected void onPostExecute(String result) {
handler.ergebnisVerarbeiten(result);
}
}
Zum Schluss kommen wir zur MainActivity. Diese benutzt meinen DBRequestTask an verschiedenen Stellen mit verschiedenen URLS und Parametern um die unterschiedlichen PHP Skripte auf meinem Server aufzurufen. Der DBRequestTast ruft dabei jeweils die ergebnisVerarbeiten verarbeiten Methode meiner MainActivity auf und übergibt als String was vom Server als Antwort zurückgekommen ist. Dieser String wird dann in ein JSON Objekt gepackt, damit er leichter verarbeitet werden kann. Zunächst wird dann aus dem JSON Objekt das Status Array geholt um zu entscheiden, wie die Serverantwort verarbeitet werden muss. Beim Status 0 (erfolgreicher Select Befehl) wird dann das Liste Array verarbeitet. Für jeden Listeneintrag wird ein Eintrag Objekt erzeugt und Eintragliste im eintragAdapter gehangen. Zum Schluss wird die notifyDataSetChanged() Methode des Adapters aufgerufen, damit der ListView seine Anzeige aktualisiert.
Code:
package kosmus.example.todoliste;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity implements DBResultHandler {
private EintragAdapter eintragAdapter;
private EditText eingabefeld;
private Eintrag eintrag;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.container);
eintragAdapter = new EintragAdapter(this);
listView.setAdapter(eintragAdapter);
ladeDaten();
}
private void ladeDaten() {
(new DBRequestTask(this)).execute(getString(R.string.basis_url)
+ "selectall.php");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.hinzufuegenButton) {
neuerEintrag();
return true;
}
return super.onOptionsItemSelected(item);
}
private void neuerEintrag() {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
alertBuilder.setTitle("Neuer Eintrag");
eingabefeld = new EditText(this);
alertBuilder.setView(eingabefeld);
alertBuilder.setCancelable(true);
alertBuilder.setNegativeButton("Abbrechen",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertBuilder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
(new DBRequestTask(MainActivity.this)).execute(
getString(R.string.basis_url) + "insert.php",
"Eintrag", eingabefeld.getText().toString());
}
});
alertBuilder.create().show();
}
public void doEdit(View view) {
if (view.getTag() instanceof Eintrag) {
eintrag = (Eintrag) view.getTag();
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this);
alertBuilder.setTitle("Eintrag bearbeiten");
eingabefeld = new EditText(this);
eingabefeld.setText(eintrag.getEintrag());
alertBuilder.setView(eingabefeld);
alertBuilder.setCancelable(true);
alertBuilder.setNegativeButton("Abbrechen",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertBuilder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
(new DBRequestTask(MainActivity.this)).execute(
getString(R.string.basis_url)
+ "update.php", "Eintrag",
eingabefeld.getText().toString(), "ID",
Integer.toString(eintrag.getId()));
}
});
alertBuilder.create().show();
}
}
public void doDelete(View view) {
if (view.getTag() instanceof Eintrag) {
eintrag = (Eintrag) view.getTag();
(new DBRequestTask(MainActivity.this)).execute(
getString(R.string.basis_url) + "delete.php", "ID",
Integer.toString(eintrag.getId()));
}
}
@Override
public void ergebnisVerarbeiten(String ergebnis) {
try {
JSONObject jsonErgebnis = new JSONObject(ergebnis);
JSONArray statusArray = jsonErgebnis.getJSONArray("Status");
int status = statusArray.getInt(0);
switch (status) {
case 0:
JSONArray datenArray = jsonErgebnis.getJSONArray("Liste");
eintragAdapter.getEintragListe().clear();
for (int i = 0; i < datenArray.length(); i++) {
JSONObject einzelsatz = datenArray.getJSONObject(i);
eintragAdapter.getEintragListe().add(
new Eintrag(einzelsatz.getInt("ID"), einzelsatz
.getString("Eintrag")));
}
eintragAdapter.notifyDataSetChanged();
break;
case 1:
Toast.makeText(this, statusArray.getString(1),
Toast.LENGTH_SHORT).show();
ladeDaten();
break;
case 2:
Toast.makeText(this, statusArray.getString(1),
Toast.LENGTH_SHORT).show();
ladeDaten();
break;
case 3:
Toast.makeText(this, statusArray.getString(1),
Toast.LENGTH_SHORT).show();
ladeDaten();
break;
default:
Toast.makeText(this, statusArray.getString(1),
Toast.LENGTH_SHORT).show();
break;
}
} catch (JSONException e) {
Toast.makeText(this,
"Serverantwort konnte nicht verarbeitet werden",
Toast.LENGTH_SHORT).show();
}
}
}
Ich hoffe dieses Beispiel hilft euch bei der Entwicklung eurer Apps weiter. Bitte Beachtet das Strings die Datenbanken übergeben werden, vorher geprüft werden sollten, damit keine sql injection durchgeführt werden kann. Darauf habe ich bei diesem kleinen Beispiel verzichtet.
Anhänge
Zuletzt bearbeitet: