In diesem Tutorial möchte ich gerne mein bestehendes Tutorial “Android App mit MySQL Datenbank verbinden” erweitern und mit einem konkreten Beispiel verfeinern.
Das bestehende Tutorial dient dabei als Grundlage (es ist jedoch keine Voraussetzung dieses zu kennen.).
Entwicklungsumgebung
Als IDE verwende ich das Android Studio.
Diese kann unter folgender Adresse “http://developer.android.com/sdk/” heruntergeladen werden (ca. 1.1 GB ohne Updates).
Nachdem die IDE installiert wurde und ggf. die Updates für die neuen Android-Versionen eingespielt wurden, kann ein neues Projekt erstellt werden.
Erstellen des Android Projektes “SimpleMySQLConnectionApp”
Als Erstes muss man das Projekt in der IDE erstellen, dieses geht am einfachsten mit dem Wizard welcher einen durch die Fenster führt.
In diesem Fenster wählen Sie den Menüpunkt “Start a new Android Studio project”.
Geben Sie hier nun
- Application name – der Name der Android Anwendung
- Company Domain – dieses wird unser default Pakage
- Project location – Ablageort der Sourcen
- dieser Pfad darf nicht zu lang und
- es dürfen keine Leerzeichen im Pfad benutzt werden
ein.
Als Zielplattform verwende ich mindestens die Android-Version 4.4.
In diesem Dialog könnte man noch andere Plattformen definieren, welches für dieses Tutorial jedoch zu viel Overhead erzeugen würde.
In diesem Dialog kann das Aussehen der App definiert werden, zbsp. kann man hier auch wählen das Tabs verwendet werden oder man kann eine fertige Vorlage (Login Activity) erstellen lassen.
Ich wähle hier eine leere Activity da es für dieses Beispiel nur eine Ausgabe auf der Activity geben soll.
In diesem Dialog geben Sie
- Activity Name – der Name der zu erstellenden Activity ein
- späterer Dateiname der *.java Datei
- Layout Name – der Name der Layout Datei
- späterer Dateiname der *.xml Datei
- Titel – der Titel der Anwendung
- Menu Resource Name – Name des Menüs welches für diese Activity angelegt werden soll.
Nachdem alle Eingaben getätigt wurden und der Wizard mit der Schaltfläche “Finish” beendet wurde, wird das Projekt angelegt. Je nach Rechner kann dieses etwas dauern.
Es kann ggf. vorkommen das die IDE eine Fehlermeldung nach dem Starten erzeugt, dieses liegt in den meisten fällen daran dass, das Kompilieren des Projektes noch nicht abgeschlossen ist und somit noch nicht alle Sourcen zur Verfügung stehen.
Erstellen der Datenquelle für die Activity
Die Datenquelle für die Activity wird wie folgt erstellt.
Erstellen der Datei “ActivityDataSource.java”
Es wird eine Java Klasse erstellt (vorzugsweise in einem separaten Pakage) welche die abstrakte Klasse AsyncTask erweitert. Die abstrakte Klasse AsyncTask zwingt einem nun die Methode “doInBackground” zu implementieren, welche wir später für das Lesen der Daten benötigen.
public class ActivityDataSource extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { return null; } }
App Berechtigungen einstellen
Für die nächsten Schritte müssen die App Berechtigungen eingestellt bzw. verändert werden. Dieses wird für die Benutzung des Internets bzw. des Netzwerkes benötigt.
Die Berechtigungen (auf Englisch “permission”) werden in der Datei “AndroidManifest.xml” gesetzt (siehe Grafik.)
Berechtigung zum Zugriff auf das Internet
<uses-permission android:name="android.permission.INTERNET" />
Berechtigung zum lesen des Netzwerk Statuses
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Erstellen der Methoden zum verbinden zur Schnittstelle
Folgende Methode erstellt die URL mit den benötigten Parametern und öffnet eine Verbindung zu dieser mit einer URLConnection.
/** * Öffnet eine Verbindung {@link URLConnection}. * @throws IOException */ private void openConnection() throws IOException{ //StringBuffer für das zusammensetzen der URL StringBuffer dataBuffer = new StringBuffer(); dataBuffer.append(URLEncoder.encode("authkey", "UTF-8")); dataBuffer.append(POST_PARAM_KEYVALUE_SEPARATOR); dataBuffer.append(URLEncoder.encode(AUTHKEY, "UTF-8")); dataBuffer.append(POST_PARAM_SEPARATOR); dataBuffer.append(URLEncoder.encode("method", "UTF-8")); dataBuffer.append(POST_PARAM_SEPARATOR); dataBuffer.append(URLEncoder.encode(DESTINATION_METHOD, "UTF-8")); //Adresse der PHP Schnittstelle für die Verbindung zur MySQL Datenbank URL url = new URL("https://draeger-it.blog/smssca/reader.php"); conn = url.openConnection(); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write(dataBuffer.toString()); wr.flush(); }
Lesen des Ergebnisses aus der geöffneten URLConnection
Im vorherigen Schritt haben wir eine Verbindung geöffnet und einen Befehl abgesetzt, unsere PHP Schnittstelle hat aus diesem Befehl einen Output generiert welchen wir nun lesen und ggf. parsen können / müssen.
/** * Ließt das Ergebnis aus der geöffneten Verbindung. * @return liefert ein String mit dem gelesenen Werten. * @throws IOException */ private String readResult()throws IOException{ String result = null; //Lesen der Rückgabewerte vom Server BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line = null; //Solange Daten bereitstehen werden diese gelesen. while ((line = reader.readLine()) != null) { sb.append(line); } return sb.toString(); }
Die gesamte Klasse “ActivityDataSource.java”
Hier nun die gesamte Klasse.
Im Konstruktor wird hier ein TextView Objekt erwartet welches im letzten Schritt “onPostExceute” befüllt wird.
package smssca.stefandraegersoftware.de.simplemysqlconnectionapp.datasource; import android.os.AsyncTask; import android.widget.TextView; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; public class ActivityDataSource extends AsyncTask<String, Void, String> { public static final String AUTHKEY = "test321"; public static final String POST_PARAM_KEYVALUE_SEPARATOR = "="; public static final String POST_PARAM_SEPARATOR = "&"; private static final String DESTINATION_METHOD = "allEntrys"; private TextView textView; private URLConnection conn; public ActivityDataSource(TextView textView) { this.textView = textView; } @Override protected String doInBackground(String... params) { try { openConnection(); return readResult(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * Öffnet eine Verbindung {@link URLConnection}. * @throws IOException */ private void openConnection() throws IOException{ //StringBuffer für das zusammensetzen der URL StringBuffer dataBuffer = new StringBuffer(); dataBuffer.append(URLEncoder.encode("authkey", "UTF-8")); dataBuffer.append(POST_PARAM_KEYVALUE_SEPARATOR); dataBuffer.append(URLEncoder.encode(AUTHKEY, "UTF-8")); dataBuffer.append(POST_PARAM_SEPARATOR); dataBuffer.append(URLEncoder.encode("method", "UTF-8")); dataBuffer.append(POST_PARAM_KEYVALUE_SEPARATOR); dataBuffer.append(URLEncoder.encode(DESTINATION_METHOD, "UTF-8")); //Adresse der PHP Schnittstelle für die Verbindung zur MySQL Datenbank URL url = new URL("https://draeger-it.blog/smssca/reader.php"); conn = url.openConnection(); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write(dataBuffer.toString()); wr.flush(); } /** * Ließt das Ergebnis aus der geöffneten Verbindung. * @return liefert ein String mit dem gelesenen Werten. * @throws IOException */ private String readResult()throws IOException{ String result = null; //Lesen der Rückgabewerte vom Server BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line = null; //Solange Daten bereitstehen werden diese gelesen. while ((line = reader.readLine()) != null) { sb.append(line); } return sb.toString(); } @Override protected void onPostExecute(String result) { if(!isBlank(result)) { //String[] arr = result.split("\\|"); this.textView.setText(result); } } private boolean isBlank(String value){ return value == null || value.trim().isEmpty(); } }
Erstellen des Layouts für die App
Da das Ziel dieser App das Darstellen eines Wertes aus einer Datenbank ist, wird das Layout sehr minimal ausfallen. Jedoch hat die IDE ein komplexes Layout vorbereitet, welches wir wiefolgt überschreiben. (Copy-and-paste)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:screenOrientation="portrait" tools:context=".Hauptfenster" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="Large Text" android:id="@+id/textView" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/lesenBtnText" android:id="@+id/lesenBtn" android:layout_below="@+id/textView" android:layout_alignParentStart="true" android:layout_marginTop="40dp" /> </RelativeLayout>
Dieses Layout beinhaltet
- ein TextFeld
- eine Schaltfläche
und mehr benötige ich für dieses Tutorial nicht.
Erstellen / Erweitern der Klasse Hauptfenser.java
Auch die Klasse Hauptfenster.java kann wie folgt eingekürzt werden, da der “Rest” für dieses Tutorial unnötig ist.
public class Hauptfenster extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_hauptfenster); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_hauptfenster, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true;} return super.onOptionsItemSelected(item); } }
Erstellen der Aktion für die Schaltfläche “lesenBtn”
Die Schaltfläche soll dazu dienen, dass die lesen Aktion angestoßen wird. Da dieses über einen asyncronen Task geschieht ist mit einer gewissen Verzögerung zu rechnen.
Die Zeit, welche der asyncrone Task benötigt werden, beeinflusst von:
- Geräteleistung,
- Internet geschwindigkeit, Netzwerkverbindung,
- Auslastung des Servers, sowie
- verwendeter Quellcode
Folgender Code wird nun implementiert.
//Textfeld auf dem Layout final TextView textView = (TextView) findViewById(R.id.textView); Button lesenBtn = (Button) findViewById(R.id.lesenBtn); lesenBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new ActivityDataSource(textView).execute("someParams"); } });
Hier ist gut zusehen das wir “nur” der Klasse ActivityDataSource im Konstruktor das TextView Objekt übergeben müssen und den Prozess mit “dataSource.execute();” starten.
Der Methode “execute” können eine beliebige Anzahl (VarArg) von Parametern übergeben werden, welche in der Methode “doInBackground” in der Klasse ActivityDataSource ausgewertet und verwendet werden können.
Die gesamte Klasse “Hauptfenster.java”
package smssca.stefandraegersoftware.de.simplemysqlconnectionapp; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.Button; import android.widget.TextView; import smssca.stefandraegersoftware.de.simplemysqlconnectionapp.datasource.ActivityDataSource; public class Hauptfenster extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_hauptfenster); final TextView textView = (TextView) findViewById(R.id.textView); Button lesenBtn = (Button) findViewById(R.id.lesenBtn); lesenBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new ActivityDataSource(textView).execute("someParams"); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_hauptfenster, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true;} return super.onOptionsItemSelected(item); } }
Erstellen der PHP Schnittstelle
Als Schnittstelle dient uns eine PHP Datei welche auf einem Server im Internet läuft
(Im idealfall auf demselben Server wie auch die Datenbank.)
Erstellen des Verzeichnisses und ablegen der Datei “reader.php”
Mit der Hilfe eines FTP Programmes wird nun das Verzeichnis auf dem gewünschten Server erstellt und die Datei “reader.php” abgelegt.
PSPAD Editor
Für die weitere Entwicklung in PHP verwende ich den PSPAD Editor welcher kostenlos auf der Herstellerseite http://www.pspad.com/de/ heruntergeladen werden kann.
Der Vorteil dieses Editors ist dass, man Online entwickeln kann, d.h. man baut durch das eingebaute Tool eine FTP Verbindung zum Server auf und kann dort eine Datei bearbeiten und speichern. Die Änderung ist sofort aktiv und müssen nicht erst umständlich hochgeladen werden.
Authentifizierung
Als Sicherheitsmaßnahme habe ich einen authentifizierungsschlüssel implementiert, welcher von der App mit in der URL übergeben wird. Dieser wird in der PHP Datei auf gleichheit geprüft und wenn dieser gleich ist (Case Sensitive) dann geht die Prozedure weiter und wenn nicht, dann wird die gesamte Prozedure abgebrochen und eine Fehlermeldung ausgegeben.
In dieser Methode wird zuerst geprüft, ob die Parameter “authkey” und “method” als POST Parameter vorhanden sind. Wenn diese Vorhanden sind, wird geprüft, ob der Wert für den Parameter “authkey” gleich “meinAuth……” ist. Wenn die Parameter NICHT gesetzt wurden und auch nicht der Key stimmt dann wird jeweils die Fehlermeldung ausgegeben.
function checkAuthCode(){ $fehler0 = "Fehler 0: Keine erfolgreiche Authentifizierung!"; if (isset($_POST['authkey']) AND isset($_POST['method'])){ $authkey = $_POST['authkey']; if ($authkey != 'test321'){ die($authkey); } } else { die(var_dump($_POST)); } }
Aufbau der Datenbankverbindung
Nachdem die Authentifizierung erfolgreich war, kann nun mit dem Aufbau der Datenbankverbindung begonnen werden.
//Datenbankverbindung aufbauen $connection = getDBConnection(); function getDBConnection(){ //Einstellungen der Datenbank $dbusername = 'Draeg_gartenroot'; //Benutzername $dbpassword = 'g8Uki51!127'; //Passwort $dburl='localhost'; //URL $dbname='DraegerStefan_gartenmanager'; //Datenbankname $fehler1 = "Fehler 1: Fehler beim aufbauen der Datenbankverbindung!"; $link = mysqli_connect($dburl, $dbusername, $dbpassword,$dbname); if (!$link) { die('Verbindung schlug fehl: ' . mysqli_error()); } /* check connection */ if (mysqli_connect_errno()) { die($fehler1); } return $link; }
Für die spätere Verwendung der Datenbankverbindung wird diese in eine Variable gespeichert.
Die Funktion “getDBConnection()” erstellt aus den Werten der Variablen eine Verbindung. Wenn diese nicht erfolgreich ist, wird die Fehlermeldung ausgegeben.
Variablen für die Funktion “getDBConnection()”
Tragen Sie hier die Benutzer und Datenbankeinstellungen ein.
(Es wurden hier die originalen Werte entfernt.)
//Einstellungen der Datenbank $dbusername = ''; //Benutzername $dbpassword = ''; //Passwort $dburl=''; //URL $dbname=''; //Datenbankname
Lesen der Daten aus der MySQL Datenbank mit PHP
Folgende Funktion liest nun alle Daten aus meiner MySQL Datenbank und gibt diese aus.
Der generierte Output wird mit einem senkrechten Strich getrennt und kann in der Android-App an dieser Stelle geparst werden.
function getAllEntrys($connection){ $sqlStmt = "SELECT * FROM Plants;"; $result = mysqli_query($connection,$sqlStmt); $data = array(); if ($result = $connection->query($sqlStmt)) { while ($row = $result->fetch_assoc()) { $id = $row["id"]; $de_name = $row["de_name"]; array_push($data,array("ID"=> $id,"de_name"=>$de_name)); } $result->free(); } closeConnection($connection); foreach ($data as $d){ echo $d["de_name"]; echo "|"; } }
Die gesamte Datei “reader.php”
<?php $reportingLevel = -1; //0 für alle PHP Fehler und Warungen ausblenden, -1 für alle anzeigen error_reporting($reportingLevel); //Sicherheitsabfrage ob der Authentifizierungscode mit übergeben wurde. //Wenn der Code nicht übergeben wurde wird die gesamte Prozedure abgebrochen. checkAuthCode(); //Datenbankverbindung aufbauen $connection = getDBConnection(); function getDBConnection(){ //Einstellungen der Datenbank $dbusername = ''; //Benutzername $dbpassword = ''; //Passwort $dburl=''; //URL $dbname=''; //Datenbankname $fehler1 = "Fehler 1: Fehler beim aufbauen der Datenbankverbindung!"; $link = mysqli_connect($dburl, $dbusername, $dbpassword,$dbname); if (!$link) { die('Verbindung schlug fehl: ' . mysqli_error()); } /* check connection */ if (mysqli_connect_errno()) { die($fehler1); } return $link; } $method = $_POST['method']; if ($method == 'allEntrys'){ getAllEntrys($connection); } function getAllEntrys($connection){ $sqlStmt = "SELECT * FROM Plants;"; $result = mysqli_query($connection,$sqlStmt); $data = array(); if ($result = $connection->query($sqlStmt)) { while ($row = $result->fetch_assoc()) { $id = $row["id"]; $de_name = $row["de_name"]; array_push($data,array("ID"=> $id,"de_name"=>$de_name)); } $result->free(); } closeConnection($connection); foreach ($data as $d){ echo $d["de_name"]; echo "|"; } } function checkAuthCode(){ $fehler0 = "Fehler 0: Keine erfolgreiche Authentifizierung!"; if (isset($_POST['authkey']) AND isset($_POST['method'])){ $authkey = $_POST['authkey']; if ($authkey != 'test321'){ die($authkey); } } else { die(var_dump($_POST)); } } function closeConnection($connection){ mysqli_close($connection); } ?>
Starten der Android Anwendung
Es gibt zwei Möglichkeiten die erstellte Android-App zu starten
- in einem Emulator, oder
- auf einem “echten” Gerät.
Ich starte die Apps immer auf einem “echten” Gerät, da man hier genauso gut debuggen sowie gleich die Oberfläche von der Bedienbarkeit mit der Hand prüfen kann.
Möchte man nun die App Starten so klickt man auf die Schaltfläche .
Nach dem Klick öffnet sich das Fenster für die Auswahl des Gerätes.
Nachdem dieses Fenster mit der Schaltfläche “OK” bestätigt wurde, wird die Anwendung auf das Gerät kopiert, deployt und gestartet. Den gesamten Vorgang kann man in der Konsole verfolgen.
Ändern der SDK Ziel Version
Sollte es hier vorkommen, dass, das Gerät in der List nicht unterstützt wird muss, soweit dieses natürlich der verwendete Quellcode es zulässt die SDK Version geändert werden. Diese Änderung der Version wird in der Datei “build.gradle” durch geführt. (siehe Grafik)
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "21.1.2" defaultConfig { applicationId "smssca.stefandraegersoftware.de.simplemysqlconnectionapp" minSdkVersion 17 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:design:23.1.1' }
Da ich als Zielgerät ein Samsung Galaxy S2 Plus verwenden muss ich den Wert für “minSdkVersion” von 19 auf 17 ändern. Da die Änderung erst kompiliert und das Projekt erneut gebaut werden muss, “erkennt” dieses die IDE und erzeugt folgende Warnung am oberen Rand der Datei.
Ausgabe auf der Activity in der App
Wenn nun die App gestartet wird, wird folgender Bildschirm angezeigt.
Bei einem “klick” auf die Schaltfläche “Lesen” wird eine Verbindung aufgebaut und die Daten aus der MySQL Datenbank geholt.
Diese Daten können nun ganz einfach geparst werden und in einer Liste oder ähnlichem dargestellt werden.
Hallo!
Erstmal vielen Dank für dein aktuelles Tutorial (Es wahr das einzige welches ich gefunden habe, das dazu noch up-to-date ist!)
Es ist alles sehr gut erklärt finde ich, sodass ich alles verstehen konnte 😀
Trotzdem habe ich eine kleine Frage: Ich will die Datenbank quasi in einen String “auslesen” und ich wüsste jetzt nach ausprobieren nicht mehr wie ich das anstellen soll, deswegen habe ich mich entschlossen einfach mal zu fragen. :’D
MfG
Erik S.
Ich suche genau nach DIESER Lösung -allerdings bin ich in der Abfolge deines Tutorials oftmals verwirrt, weil ich an vielen Punkten nicht weiss, in welche Datei ich nun WAS eintragen soll… Es geht schon los unter dem Punkt: Erstellen der Datei „ActivityDataSource.java“ Muss ich diese Datei neu erstellen? Wie mache ich das? Eine step-by-step Anleitung wäre mir hier viel hilfreicher….
Edit: Ich habe es nun hinbekommen, nachdem ich mein Projekt genau so benannt habe, wie du deines. Nun habe ich allerdings noch eine Frage: wie kann ich jetzt die Ausgabe vernünftig formatieren? HTML-Formatierung ist in der foreach ja nicht möglich. Ich möchte zb. nach jedem Datensatz einen Zeilenumbruch generieren…(??)
ich bin mir nicht sicher ob es dir noch hilft aber wenn du in der PHP Datei an der Stelle echo “|” das | durch \n ersetzt dann macht dann sollte die Datei an dieser Stelle ein Zeilenumbruch machen.
mit freundlichen güßen Thomas
Super Tutorial danke!
Nur leider wenn ich auf Lesen tippe passiert nichts…irgendein Tipp woran das liegen könnte? Wenn ich die Url so aufrufe habe ich eine Verbindung.
Ich habe mal eine Frage, wenn ich auf den Knopf in der App drücke bekomme ich ganz viel css code ausgegeben und unter anderem die Fehlermeldung undefinded index: de_name in users/***/www/reader.php
Ich bitte um Hilfe.
Zur Info: ich verwende meine eigene Datenbank
Hi,
das sieht nach einem PHP Fehler aus, dazu müsste man aber zusätzlich noch die Datei ansehen.
Wenn du möchtest kannst du mir ja mal die Daten per E-Mail zusenden.
Gruß,
Stefan
Hi Stefan,
ich habe das Projekt gerade nachgebaut und komme nicht so recht weiter. Wen ich den Button lesen betätige, erhalte ich nicht den Output der Datenbank sondern folgendes: Array(1){[“authkey”]=> string(7) “test321”}
Hast Du einen Tipp für mich, was da falsch läuft? Vielen dank im Voraus!
Hi,
der Parameter “authkey” ist falsch.
Über welche URL rufst du den Service auf?
Hier musst du prüfen
if (isset($_POST[‘authkey’]) AND isset($_POST[‘method’])){
$authkey = $_POST[‘authkey’];
if ($authkey != ‘test321’){
die($authkey);
}
} else {
die(var_dump($_POST));
}
Gruß,
Stefan
Gruß,
Stefan
Hi Stefan,
ich habe in die reader.php genau Deinen Code hineinkopiert:
function checkAuthCode(){
$fehler0 = “Fehler 0: Keine erfolgreiche Authentifizierung!”;
if (isset($_POST[‘authkey’]) AND isset($_POST[‘method’])){
$authkey = $_POST[‘authkey’];
if ($authkey != ‘test321’){
die($authkey);
}
} else {
die(var_dump($_POST));
}
Dennoch erhalte ich die selbe Fehlermeldung. Die php liegt auf einem Webserver im Heimnetz, auf dem auch der MySQL Server läuft. Wenn ich die php über einen browser aufrufe, erhalte ich folgenden Output:
array(0) { }
Danke für Deine Hilfe!!
Hi,
wie und vorallem mit welchen Parametern rufst du den “Service” auf?
Es scheint so das der erwartete Parameter “authcode” fehlt.
Gruß,
Stefan
Hi wenn ich in der reader.php
die (var_dump($_POST));
durch
echo “TEST”;
ersetze, erhalte ich im Browser und auch auf einem Android tablet als Ausgabe
TEST.
ich weiß nicht genau, “Aufruf des Service” bedeutet, erfolgt der über Hauptfenster.java?
Gruß Marius
Hi,
es wird in der Methode ” private void openConnection()” eine Adresse genannt diese muss existieren, des weiteren werden POST Parameter übergeben. Hast du lokal ein XAMPP laufen?
Gruß,
Stefan
Hi Stefan,
hier die Methode:
private void openConnection() throws IOException{
//StringBuffer für das zusammensetzen der URL
StringBuffer dataBuffer = new StringBuffer();
dataBuffer.append( URLEncoder.encode(“authkey”, “UTF-8”));
dataBuffer.append(POST_PARAM_KEYVALUE_SEPARATOR);
dataBuffer.append(URLEncoder.encode(AUTHKEY, “UTF-8”));
dataBuffer.append(POST_PARAM_SEPARATOR);
dataBuffer.append(URLEncoder.encode(“method”, “UTF-8”));
dataBuffer.append(POST_PARAM_SEPARATOR);
dataBuffer.append(URLEncoder.encode(DESTINATION_METHOD, “UTF-8”));
//Adresse der PHP Schnittstelle für die Verbindung zur MySQL Datenbank
URL url = new URL(“http://192.168.178.110/android/reader.php”);
conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(dataBuffer.toString());
wr.flush();
}
Unter 192.168.178.110 läuft eine Linuxmaschine mit Webserver und MySQL.
Hi,
das sieht gut aus.
Was passiert wenn du die Adresse “http://192.168.178.110/android/reader.php” im Browser öffnest?
Man könnte auch die Adresse und die Parameter in Postman mal aufrufen. Das gibt es als Browserplugin sowie als eigenständige Anwendung.
Das leere Array array(0) { } zeigt eigentlich an das keine POST Parameter ankommen.
Gruß,
Stefan
Hi Stefan,
Danke für den Tip. Wenn ich mit postman einen POST request sende und im Bereich url encoded die Parameter für authkey und Methode mitgebe, dann erhalte ich im Browser das korrekte Ergebnis der DB Abfrage. Wenn ich den Parameter Methode weglasse, erhalte ich wie zuvor beschrieben „ array(1) { [“authkey”]=> string(7) “test321” }„. Also scheint bei der Übergabe der Methode etwas falsch zu sein?
Danke und Gruß
Marius
Hi Stefan, ich habe den Fehler gefunden: in der Methode wird
method&allEntrys übergeben,es muss aber method=allEntrys ankommen.Falscher Seperator. Also in Deinem Beispiel muss in Zeile 13
folgender Code stehen:
dataBuffer.append(POST_PARAM_KEYVALUE_SEPARATOR);
Kannst Du mir noch eien Tipp geben, wie ich das auf einem Android Tablett schön als Tabelle ausgeben kann?
Danke & Gruß
marius
Hi,
danke für den Hinweis.
Möchtest du das in der Android App oder im Browser darstellen?
Gruß,
Stefan
Hi,
Ich möchte am liebsten das Ergebnis des select statements in der Android App als Tabelle darstellen, also mit mehreren Spalten und Zeilen.
Vg
Marius
Hi,
es gibt das TableLayout in Android damit kann man das lösen.
Als Anfang würde ich das Ergebnis des SQL Statements als JSON zurück geben,
dieses kann man zbsp. mit Google GSON parsen und bequem in Objekten darstellen.
Wenn das Ergebnis als Liste mit Objekten vorliegt kann man nun mit einer For Each Schleife
(oder stream je nach Ziel SDK) darüber iterieren und eine neue Zeile erzeugen (TableRow),
jeder Wert aus dem Objekt wird eine neue TextView und wird der Zeile hinzugefügt. Am Ende wird die Zeile dem
TableLayout hinzugefügt.
Damit sollte dann eine Tabelle dargestellt werden.
Gruß,
Stefan
“Als Schnittstelle dient uns eine PHP Datei welche auf einem Server im Internet läuft
(Im idealfall auf dem selben Server wie auch die Datenbank.)”
Super! Sehr hilfreich.
Und weiter?
Kommt etwa PHP-Datei alleine zum Server sobald sie die Notwendigkeit riecht?
Hallo,
bitte beschreiben Sie das Problem etwas genauer?
Im nächsten Abschnitt wird erläutert wie die Schnittstelle erstellt und wo diese abgelegt wird.
Gruß,
Stefan
Leider funktioniert der Code bei mir nicht, ich konnte es mittlerweile soweit eingrenzen, dass der Fehler wohl im OutputStreamWriter liegt. Hier kommt immer die Fehlermeldung: “W/System.err: java.io.FileNotFoundException: http://XXX/reader.php”
Sobald ich wr.flush() auskommentiere, kommt die zu erwartende Rückmeldung: “array(0){}”
Hat hier einer eine Idee woran das liegen kann?
Gruß
Christian
Hi Christian,
was passiert wenn du die Adresse http://XXX/reader.php über deinem Browser eingibst?
Gruß,
Stefan
Hi Stefan,
sie lässt sich normal aufrufen und gibt “array(0) { }” aus.
Gruß
Christian
Hallo Stefan,
nach langem hin und her, hat sich soeben herausgestellt das es sich um einen serverseitigen Fehler handelt. Auf dem betroffendem Server war POST abgeschaltet.
Vielen Dank für das gute Tutorial, jetzt funktioniert alles 🙂
Gruß
Christian
Danke, es freut mich immer wenn ich eine Rückmeldung erhalte.
Gruß,
Stefan
Genau das, was ich suchte!
Bin derzeit an der (Neu-) Umsetzung einer App mit MySQL-Zugriff. Auf der Suche nach Möglichkeiten bin ich über deinen Beitrag gestolpert. Gerade die Sache mit “authkey” gefällt mir gut. Umgesetzt und funktioniert – so muss das!
Jetzt gehts ans Feintuning…
Vielen Dank
Danke. Das freut mich das es funktioniert hat.
Gruß,
Stefan Draeger
Hallo
Und erst mal besten Dank. Das ist genau das, was ich gesucht habe. Leider kriege ich beim Verbinden eine Exeption:
“java.io.FileNotFoundException: http://stefan-draeger-software.de/smssca/reader.php”
Wenn ich mit dem Browser auf die URL gehe, erscheint ein Hinweis, das die Domain zu verkaufen ist. Ist der reader.php auf eine neue Seite gezügelt, oder ist das Projekt gestorben. Ich muss definitiv den reader auf meine Datenbank tun, aber erst mal hätten mir “Apfel|Rettich etc” genügt.
Hallo,
vielen Dank für dein Kommentar.
Die Webseite “stefan-draeger-software.de” ist alt und wurde zu “draeger-it.blog” bei der migration sind mir jedoch einige Adressen durchgerutscht daher sind in einpaar wenigen Beiträgen noch falsche Adressen bzw. Broken Links enthalten, dafür möchte ich mich jedoch entschuldigen (habe ich nun in dem Beitrag bereinigt).
Die Datei “reader.php” habe ich unter https://draeger-it.blog/android-app-mit-einer-mysql-datenbank-verbinden-16-01-2016/#Die_gesamte_Datei_8222readerphp8220 ausführlich beschrieben. Hier muss jedoch das Codefenster aufgeklappt werden.
Sollten weiterhin fragen bestehen so kannst du dich gerne per E-Mail oder hier in den Kommentaren an mich wenden.
Gruß,
Stefan Draeger
Besten Dank
Allerdings klappt es mit dem neuen “ActivityDataSource.java” immer noch nicht. Die neue Exception lautet nun:
“java.io.FileNotFoundException: https://draeger-it.blog/smssca/reader.php”
Wenn ich die Seite: “https://draeger-it.blog/smssca/reader.php” mit einem Browser aufrufe, erschheint:
“Diese Seite konnte leider nicht gefunden werden.”
Hi Andi,
die Datei reader.php liegt nicht mehr auf dem Server.
Das ist auch nicht das größte Problem denn diese muss ja auch zusätzlich die Daten für die Verbindung zur Datenbank beinhalten und diese lautet bei dir ja anders.
Du kannst dir ein XAMPP auf dem Rechner lokal einrichten und dann hast du ja eine MySQL Datenbank inkl. php zur Verfügung.
Dann kannst du dieses erstmal lokal bei dir hosten.
Wenn du nicht weißt wie das geht kann ich dir gerne dazu einen Beitrag veröffentlichen. (Dieser steht sowieso auf meiner ToDo Liste.)
Gruß,
Stefan
Hallo Stefan
Besten Dank. Habe den reader.php auf meinen Server getan (mit Anpassungen). Läuft tiptop.
🙂
Hi Stefan,
ich habe versucht, Dein Programm unter Android Studio 3.6.1 zu testen.
Leider hat es nicht funktioniert. die Reader.php habe ich erweitert, dass auf Post oder get reagieren kann.
Ich habe sie selbst getestet und zeigt mir mit das Ergebnis. Wenn ich jetzt auf Lesen klicke, passiert nichts?
ich habe ein paar Kontrollpunkten eingebaut, um zu sehen, wo es hängt. ich habe gemerkt, dass er kurz nach diesem Befehl “OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());” hängen bleibt .
Hast Du eine Idee?
Danke im Voraus