Apps für Android programmieren leicht gemacht!
raspberry pi mit dem smartphone steuern - Teil 6

6. Raspberry Pi mit dem Smartphone steuern

Heute wollen wir unsere Artikelreihe, zur Erstellung einer Raspberry Pi Fernsteuerung’s App fertigstellen und damit die App komplettieren.

Bisher haben wir alle dringend nötigen Funktionen, Bereiche und Speichermöglichkeiten implementiert.
Was allerdings noch an unserem Vorhanden fehlt ist das Zusammenfügen der einzelnen Bereiche und Funktionen zu einem Ganzen.

Wir benötigen nun also die Navigation, um zwischen den einzelnen Bereichen wechseln zu können.
Dazu verwenden wir ein OptionMenü. Auf gut Deutsch bedeutet dies, dass wir oben rechts drei Punkte angezeigt bekommen, über die wir die einzelnen Bereiche ansteuern können. Existiert eine Menütaste an dem Smartphone, dann wird die Navigation darüber geöffnet.

Menü-Icon auf meinem Galaxy S5, ohne Hardware Menütaste.
Menü-Icon auf meinem Galaxy S5, ohne Hardware Menütaste.

 

OptionMenü auf meinem Galaxy S5, ohne Hardware Menütaste.
OptionMenü auf meinem Galaxy S5, ohne Hardware Menütaste.

 

Hilfreich wäre es vielleicht auch, wenn wir eine Nachricht angezeigt bekommen, wenn noch keine Verbindungsdaten angegeben sind.

 

OptionMenü:

Vorerst sollten wir mit dem  größeren Vorhaben beginnen.
Wir benötigen ein paar Einträge in unserer Strings.xml Datei, welche die Texte unserer App enthält. Sie liegt im Ordner res -> values.

<!-- Texte für unser Menü -->
<string name="menu_start">Startseite</string>
<string name="menu_ueber">Über</string>
<string name="menu_einstellungen">Einstellungen</string>
<string name="menu_neuer_befehl">Neuer Befehl</string>

 

Nun, da wir unsere Texte definiert haben, erstellen wir eine neue Datei im Ordner res -> menu, mit dem Namen „actionbar_menu.xml“.
Existiert dieser Ordner wiedererwartend nicht, dann erstellen wir auch diesen.
In dieser Datei werden wir definieren, wie unser OptionMenü aufgebaut ist und die eben erstellten Texte wiederverwenden.

<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright 2016 www.droid-lernen.de
  ~
  ~ Licensed under the Apache License, Version 2.0 (the „License“);
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~ http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an „AS IS“ BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  -->

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <!-- Menüpunkt, der angezeigt wird, wenn auf die drei Punkte in der Actionbar geklickt wird. -->
    <item android:id="@+id/menu_start"
        android:title="@string/menu_start"
        app:showAsAction="never"/>
    <item android:id="@+id/menu_neuer_befehl"
        android:title="@string/menu_neuer_befehl"
        app:showAsAction="never"/>
    <item android:id="@+id/menu_einstellungen"
        android:title="@string/menu_einstellungen"
        app:showAsAction="never"/>
    <item android:id="@+id/menu_ueber"
        android:title="@string/menu_ueber"
        app:showAsAction="never"/>
</menu>

 

Anschließend wechseln wir wieder in die Hauptklasse „MainActivity“.
Hier werden wir der App nun angeben, dass es ein OptionMenü gibt, wie dieses aussehen soll und welche Aktionen beim Klick auf einen der Menüeinträge geschehen soll.

// Definiert, dass es ein OptionMenü gibt und wie dieses aussehen soll. (Nach Vorlage der Datei "actionbar_manu.xml")
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.actionbar_menu, menu);
    return true;
}

 

Was nun in letztem Schritt noch fehlt ist die Funktion, die auf den Klick eines Menüeintrages reagiert und uns dann schließlich die entsprechenden Bereiche anzeigt.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.menu_start:
            // Dieser Teil (bis zum "return") wird ausgeführt, wenn wir auf den Menüpunkt mit der ID "menu_start" klicken.
            zeigeStart();

            return true;
        case R.id.menu_ueber:
            // Dieser Teil (bis zum "return") wird ausgeführt, wenn wir auf den Menüpunkt mit der ID "menu_ueber" klicken.


            return true;
        case R.id.menu_einstellungen:
            // Dieser Teil (bis zum "return") wird ausgeführt, wenn wir auf den Menüpunkt mit der ID "menu_einstellungen" klicken.
            zeigeEinstellungen();

            return true;
        case R.id.menu_neuer_befehl:
            // Dieser Teil (bis zum "return") wird ausgeführt, wenn wir auf den Menüpunkt mit der ID "menu_neuer_befehl" klicken.
            zeigeNeuerBefehl();

            return true;
        default:
            // Standardfunktion. Sollte bestehen bleiben.
            return super.onOptionsItemSelected(item);
    }
}

 

Für den Menüpunkt „Über“ habe ich mir etwas ganz ausgefallenes einfallen lassen.
Das Ganze nennt sich DialogFragment und zeigt uns eine Art Pop-Up mit dem vorher eingestellten Text und den eingestellten Knöpfen an.

DialogFragment unter Android
DialogFragment unter Android.
//Kleine Klasse zum Erstellen eines Dialogs
public static class UeberDialog extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        //Dialog erstellen
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        //Befülle Dialog mit dem Text "ueber_text" aus der Datei res -> strings.xml
        builder.setMessage(R.string.ueber_text)
                //Erstelle einen Button mit dem Text "ok"  aus der Datei res -> strings.xml
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        //Schließe das Dialogfeld, beim Klick auf den erstellten Button
                        dismiss();
                    }
                });
        //Gib das erstellte Dialogfeld an die aufrufende Klasse zurück, um es anzeigen zu können.
        return builder.create();
    }
}

 

In die Funktion onOptionMenuSelected schreiben wir unter den Fall „case R.id.menu_ueber“:

DialogFragment newFragment = new UeberDialog();
newFragment.show(this.getFragmentManager(), "Über");

Damit wird das Pop-Up geöffnet. Der Titel ist das „Über“.

 

Benachrichtigung:

Wie bereits oben angesprochen haben wir ja den Plan eine Benachrichtigung anzeigen zu lassen, falls noch keine Verbindungsdaten angegeben sind.
Um dies zu realisieren gehen wir ans Ende der „onCreate“ Funktion und fügen den Funktionsaufruf von „benachrichtige();“ ein.

Damit wir nicht in einen Fehler laufen, müssen wir diese Funktion selbstverständlich auch definieren.

// Zeigt eine Benachrichtigung an, falls zu dem Zeitpunkt des Starts noch keine Verbindungsdaten angegeben wurde.
public void benachrichtige(){

    // Prüft, ob eines der Felder für die Verbindungsdaten unvollständig ist.
    if(pref.getInt("port", 0) == 0 || pref.getString("ip", "").equals("") || pref.getString("passwort", "").equals("") || pref.getString("nutzername", "").equals("")) {
        Toast.makeText(MainActivity.this, "Verbindungsdaten unvollständig. Menü -> Einstellungen", Toast.LENGTH_LONG).show();
    }
    
}

 

Nachwort:

Puhh, da haben wir ja bereits eine gehörige Portion Arbeit hinter uns.
Unsere App sieht vielleicht nicht super schön aus und 1 bis 2 zusätzliche Funktionen sind für die Marktreifen Gebrauch auch noch nötig, doch für den Hausgebrauch ist diese App vollkommen ausreichend.
Ich hoffe ich konntet so Einiges in dieser Artikelreihe lernen und euch ist mit der Funktionsweise geholfen.
Ich wünsche selbstverständlich frohes Programmieren und viel Glück bei dem Raspberry Pi Projekt.

Bitte beachtet die Lizenzen von JSch.

QuickSSH - Source Code


Abschließend zu dieser Artikelreihe kannst du dir hier den Source Code der kompletten App herunterladen. Bitte beachte die Lizenzen von JSch.

DownloadLizenzbedingungen

Marvin

Ich bin 23 Jahre jung und studiere zurzeit Wirtschaftsinformatik an der Georg-August-Universität in Göttingen. Ich bin ein Mensch, der sich neben der Programmierung noch für tausend andere Dinge interessiert, die mal mehr und mal weniger verrückt sind. Vor allem aber bin ich Feuer und Flamme mit der Programmierung von eigenen kleinen Apps und Programmen, die mein Leben bereichern.

2 Kommentare

*Pflichtfeld

  • Hallo Marvin,
    vielen Dank für das Tutorial.

    Kannst du mir bitte zeigen wie ein Befehl aussehen soll?

    Bsp: Titel: test
    Befehl: ifconfig.

    Gehen die normalen Kommandozeilenbefehle für den Pi?
    Wie sehe ich dass ich eine Verbindung zu einem PI habe?

    Grüße Pascal

    • Hallo Pascal,

      der Titel ist nur für die App zur einfacherern Identifizierung von Befehlen in der App. Der Befehl an sich muss immer so aussehen, wie du ihn auch in der Linux Konsole verwenden würdest. Die App tut eigentlich nichts weiter, als die gesetzten Befehle per SSH an den Pi zu senden und diese dann auszuführen.

      Wenn die App und damit auch die SSH Verbindung funktionieren, dann findest du nach jedem Befehl in der Android Studio Konsole einen Log-Output.

      Testen könntest du die App weiterhin über folgenden Befehl: echo „Some text here.“ > test.txt

      Existiert in deinem Home Directory dann eine Datei test.txt ist die Verbindung geglückt.

      Gruß