Android App mit einer MySQL Datenbank verbinden (16.01.2016)

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 Vorraussetzung dieses zu kennen.).

Entwicklungsumgebung

Als IDE verwende ich das Android Studio.

Verwendete Version des Android Studio's.
Verwendete Version des Android Studio’s.

Diese kann unter folgender Adresse „http://developer.android.com/sdk/“ herunter geladen 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.

Startfenster des Android Studio's.
Startfenster des Android Studio’s.

In diesem Fenster wählen Sie den Menüpunkt „Start a new Android Studio project“.

Konfiguration des neuen Projektes.
Konfiguration des neuen Projektes.

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.

Plattform einstellen.
Plattform einstellen.

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.

Erstes Fenster (Activity) erzeugen.
Erstes Fenster (Activity) erzeugen.

In diesem Dialog kann das aussehen der App definiert werden, zbsp. kann man hier auch wählen das Tabs verwendet werden oder mann kann eine fertige Vorlage (Login Activity) erstellen lassen.

Leeres Hauptfenster einstellen.
Leeres Hauptfenster einstellen.

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.
Abschluss des Wizards für das erstellen eines neuen Android Studio Projektes.
Abschluss des Wizards für das erstellen eines neuen Android Studio Projektes.

Nachdem alle Eingaben  getätigt wurden und der Wizard mit der Schaltfä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.)

Android Manifest Datei.
Android Manifest Datei.

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 & 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 das 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 dem selben 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 sind 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.

Fehlender Authentifiziungsschlüssel oder keine erfolgreiche Authentifiziung.
Fehlender Authentifiziungsschlüssel oder keine erfolgreiche Authentifiziung.

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 ließt nun alle Daten aus meiner MySQL Datenbank und gibt diese aus.
Der generierte Output wir 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 App’s 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 run.
Nach dem klick öffnet sich das Fenster für die Auswahl des Gerätes.

Geräteauswahl zum starten der Anwendung.
Geräteauswahl zum starten der Anwendung.

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 zu läßt die SDK Version geändert werden. Diese Änderung der Version wird in der Datei „build.gradle“ durch geführt. (siehe Grafik)

Gradle build Datei.
Gradle build Datei.
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 verwende 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.

Warung, Gradle build "out of sync"
Warung, Gradle build „out of sync“

 

Ausgabe auf der Activity in der App

Wenn nun die App gestartet wird, wird folgender Bildschirm angezeigt.

Startbildschirm der Android App.
Startbildschirm der Android App.

Bei einem „klick“ auf die Schaltfläche „Lesen“ wird eine Verbidnung aufgebaut und die Daten aus der MySQL Datenbank geholt.

Daten aus der MySQL Datenbank.
Daten aus der MySQL Datenbank.

Diese Daten können nun ganz einfach geparst werden und in einer Liste oder ähnlichem dargestellt werden.

Das gesamte Android Studio Projekt zum Download

36 Gedanken zu „Android App mit einer MySQL Datenbank verbinden (16.01.2016)

  • 27. Juni 2016 um 18:53
    Permalink

    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.

    Antwort
  • 11. Januar 2017 um 21:08
    Permalink

    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….

    Antwort
    • 12. Januar 2017 um 10:52
      Permalink

      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…(??)

      Antwort
      • 27. Dezember 2017 um 15:19
        Permalink

        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

        Antwort
  • 23. Januar 2017 um 14:12
    Permalink

    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.

    Antwort
  • 9. Januar 2018 um 12:54
    Permalink

    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

    Antwort
    • 9. Januar 2018 um 13:06
      Permalink

      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

      Antwort
  • 24. Januar 2018 um 08:26
    Permalink

    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!

    Antwort
    • 24. Januar 2018 um 08:32
      Permalink

      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

      Antwort
  • 25. Januar 2018 um 13:56
    Permalink

    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!!

    Antwort
    • 25. Januar 2018 um 13:58
      Permalink

      Hi,

      wie und vorallem mit welchen Parametern rufst du den „Service“ auf?

      Es scheint so das der erwartete Parameter „authcode“ fehlt.

      Gruß,

      Stefan

      Antwort
  • 25. Januar 2018 um 14:41
    Permalink

    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

    Antwort
    • 25. Januar 2018 um 15:00
      Permalink

      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

      Antwort
  • 25. Januar 2018 um 16:41
    Permalink

    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.

    Antwort
    • 25. Januar 2018 um 18:53
      Permalink

      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

      Antwort
      • 25. Januar 2018 um 21:28
        Permalink

        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

        Antwort
        • 26. Januar 2018 um 12:10
          Permalink

          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

          Antwort
          • 26. Januar 2018 um 18:19
            Permalink

            Hi,

            danke für den Hinweis.
            Möchtest du das in der Android App oder im Browser darstellen?

            Gruß,

            Stefan

  • 26. Januar 2018 um 20:31
    Permalink

    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

    Antwort
    • 26. Januar 2018 um 20:41
      Permalink

      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

      Antwort
  • 22. Februar 2018 um 15:13
    Permalink

    „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?

    Antwort
    • 23. Februar 2018 um 13:21
      Permalink

      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

      Antwort
  • 18. Juli 2018 um 12:59
    Permalink

    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

    Antwort
    • 18. Juli 2018 um 13:22
      Permalink

      Hi Christian,

      was passiert wenn du die Adresse http://XXX/reader.php über deinem Browser eingibst?

      Gruß,

      Stefan

      Antwort
  • 18. Juli 2018 um 15:50
    Permalink

    Hi Stefan,

    sie lässt sich normal aufrufen und gibt „array(0) { }“ aus.

    Gruß
    Christian

    Antwort
  • 18. Juli 2018 um 16:42
    Permalink

    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

    Antwort
    • 19. Juli 2018 um 10:04
      Permalink

      Danke, es freut mich immer wenn ich eine Rückmeldung erhalte.

      Gruß,

      Stefan

      Antwort
  • 27. Oktober 2018 um 09:16
    Permalink

    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

    Antwort
    • 27. Oktober 2018 um 10:25
      Permalink

      Danke. Das freut mich das es funktioniert hat.

      Gruß,

      Stefan Draeger

      Antwort
  • 7. Mai 2019 um 22:49
    Permalink

    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.

    Antwort
    • 8. Mai 2019 um 07:29
      Permalink

      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

      Antwort
      • 10. Mai 2019 um 22:16
        Permalink

        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.“

        Antwort
        • 11. Mai 2019 um 11:23
          Permalink

          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

          Antwort
          • 13. Mai 2019 um 20:14
            Permalink

            Hallo Stefan

            Besten Dank. Habe den reader.php auf meinen Server getan (mit Anpassungen). Läuft tiptop.

            🙂

  • 18. März 2020 um 16:00
    Permalink

    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

    Antwort
  • Pingback:Android App Entwicklung: ESP Controller ansprechen #1 - Technik Blog

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.