Raspberry Pi – Bewegungsmelder

Raspberry Pi – Bewegungsmelder

Zu einer modernen und gelungenen Hausautomation und/oder Alarmanlage gehört heutzutage, dass man an seinem Smartphone über jede Änderung benachrichtigt wird.
Projekte mit Bewegungsmeldern an einem Raspberry Pi gibt es viele, doch wer so technikvernarrt ist wie ich, der hat bestimmt schon einmal über die Konnektivität zwischen Raspberry und Smartphone nachgedacht.

Wir (StaticFloat und www.tutorials-raspberrypi.de) haben nun ein kleines Projekt auf die Beine gestellt, welches diese Verbindung herstellt.
Lasse dich ab jetzt von deinem Android Smartphone benachrichtigen, sobald der Bewegungsmelder an deinem Raspberry Pi eine Bewegung registriert.

Als kleine Erläuterung zu diesem Projekt.
Uns ist bewusst, dass die Wenigsten eine eigene Webseite/einen eigenen Server besitzen. Aus diesem Grund benutzen wir den Google Cloud Messaging Dienst (kurz GCM).
Dieser sendet, bei Benachrichtigung vom Raspberry Pi an alle verbundenen Android Geräte eine Nachricht, mit Ort und Zeit der Bewegung. So sparen wir uns die Programmierung eines eigenen Webservices und vor allem Akku, denn Google Benachrichtigt uns und wir fragen nicht nach.
Auf www.tutorials-raspberrypi.de findet ihr alle nötigen Anleitungen, um euren Raspberry Pi einzurichten und zu programmieren. Dieser Benachrichtigt, bei Bewegung, Google.
Auf StaticFloat findet ihr die nötigen Anleitungen, um eine Benachrichtigung unter Android anzuzeigen, die wir von Google bekommen.

Der SourceCode steht unter der Apache 2.0 Lizenz,  ihr könnt die App also benutzen/verändern/veröffentlichen, wie es euch beliebt.
Bitte achtet darauf, dass ihr die google-services.json Datei, welche ihr in diesem Artikel erstellt, mit einfügt. Wie das geht ist unter dem Punkt “Vorarbeit” erklärt.

Raspberry Pi einrichten:

Wie bereits angesprochen findet ihr den Artikel zur Einrichtung und Programmierung eures Raspberry Pi nicht bei StaticFloat.
Bitte folgt also dieser Anleitung -> Raspberry Pi + Android: Benachrichtigung vom Bewegungmelder

Android App erstellen:

Solltet ihr zum ersten mal eine Android App programmieren, dann folgt bitte diesen 3 Artikeln:

Habt ihr Android Studio installiert, dann erstellt eine neue App. Dieser gebt ihr einen Namen und einen Package Namen.
Der Package Name besteht aus einem Ländercode (z. B. de), einem Entwicklernamen und dem Appnamen. Jeweils mit einem “.” getrennt.

Als minimale Version benutzt ihr 9 und ihr wählt “Blank Activity” (ab Android Studio 2.1 heißt es “Empty Activity”) aus.
Android Studio wird nun ein erstes Grundgerüst erstellen.

Vorarbeit:

Bitte folgt den Anleitungen in diesem Artikel Raspberry Pi – Google Cloud API-Key, um eure App für GCM vorzubereiten. Am Ende dieses Vorgangs wird euch der Download einer google-services.json Datei angeboten.

Diese müssen wir nun in unsere App einfügen. Klickt dazu in der linken Leiste mittels Rechtsklick auf “App” und dann auf “Im Explorer anzeigen” oder wie bei mir “Reveal in Finder”. Es öffnet sich der Ordner, in den wir die Datei einfach verschieben. Der Ordner kann danach wieder geschlossen werden.

Nun müssen wir die Dateien “gradle.build (Module: app)” und “gradle.build (Project: ????)” anpassen. Diese sind unter der Kategorie “Gradle” ebenfalls in der linken Dateiliste zu finden.

In die Datei “gradle.build (Project: ????)” fügen wir innerhalb der {}-Klammern von dependecies ein:

classpath 'com.google.gms:google-services:3.0.0'


// Das sieht in etwa so aus:
dependencies {
 classpath 'com.android.tools.build:gradle:3.0.1'
 classpath 'com.google.gms:google-services:3.0.0'
}

In die Datei “gradle.build (Module: app)” müssen wir 2 Stellen bearbeiten.
Als Erstes fügen wir ganz am Ende der Datei ein:

apply plugin: 'com.google.gms.google-services'

Und wieder fügen wir innerhalb der {}-Klammern von dependencies ein:

compile "com.google.android.gms:play-services-gcm:9.4.0"

// Das sieht dann in etwas so aus:
dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 testCompile 'junit:junit:4.12'
 compile 'com.android.support:appcompat-v7:24.2.0'
 compile "com.google.android.gms:play-services-gcm:9.4.0"
}

Damit ist unsere Vorarbeit auch schon geleistet.
Wir haben Android Studio mit diesen kleinen Anpassungen nun beauftragt zur Erstellung der App die Google Play Services mit einzubinden. Dadurch bekommen wir die Möglichkeit diese zu benutzen. Das Google Cloud Messaging ist ein Teil der Google Play Services.

AndroidManifest.xml:

Wir müssen nun vor der Programmierung noch ein paar wichtige Informationen an Android weitergeben.

Im Raspberry Pi Teil dieses Projektes habt ihr auf dem Raspberry Pi mit einem Python Skript programmiert. Dieses Skript läuft, wie jedes Programm, von oben nach unten ab.
Java auf Android auch, mit dem Unterschied, dass Java eine Objektorientierte Programmiersprache ist. Dies bedeutet, dass wir Objekte erstellen können. Objekte sind hierbei im Groben und Ganzen nichts anderes als unterschiedliche Java Dateien, die in Variablen geschrieben werden können und parallel zu dem Hauptprogramm ablaufen. Wir können somit mehrere Java Dateien in eine Java Datei importieren oder mehrere Java Dateien in unserer App parallel und unabhängig von einander ausführen.

Genau bei diesem Punkt kommt die AndroidManifest.xml-Datei mit ins Spiel.
In dieser Datei steht nämlich drin, wann Android welche Klasse aufrufen und benutzen soll.
Zum Beispiel könnten wir sagen, dass Android beim Start der App die Klasse/Datei “MainActivity” öffnen soll, aber wenn Android gerade neu gestartet hat, dann soll die Klasse/Datei “Restarted” geöffnet werden.

Wir nutzen diese AndroidManifest.xml-Datei, um zu sagen, welche Berechtigungen unsere App bekommen soll und welche Klasse/Datei geöffnet werden soll, wenn unsere App eine Nachricht vom GCM Dienst bekommt.

Die AndroidManifest.xml-Datei ist in der linken Liste unter app->manifest zu finden.

Wir fügen vorerst die benötigten Berechtigungen ein.
Dazu schreiben wir folgende Zeilen innerhalb des -Tags, aber überhalb von :

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name=".permission.C2D_MESSAGE" tools:replace="android:name" android:protectionLevel="signature" />
<uses-permission android:name=".permission.C2D_MESSAGE" tools:replace="android:name" />

[EDIT]: Zu zwei der Tags muss ab Android Studio 3 nun die Info “tools:replace=”android:name”” hinzugefügt werden. Dank an Lenny.

Anschließend fügen wir folgende Zeilen innerhalb des -Tags ein:

<!-- Regelt den Empfang von Nachrichten durch Google -->
<receiver android:name="com.google.android.gms.gcm.GcmReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
 <intent-filter android:priority="1000">
 <action android:name="com.google.android.c2dm.intent.RECEIVE"></action>
 <category android:name="[Euer Packagename]"></category>
 </intent-filter>
</receiver>

<!-- Regelt den Empfang von Nachrichten durch Google -->
<service android:name=".GcmListener" android:exported="false">
 <intent-filter android:priority="1000">
 <action android:name="com.google.android.c2dm.intent.RECEIVE"></action>
 </intent-filter>
</service>

<!-- Regelt den Empfang von einer ID für unsere App durch Google -->
<service android:name=".InstanceListener" android:exported="false">
 <intent-filter>
 <action android:name="com.google.android.gms.iid.InstanceID"></action>
 </intent-filter>
</service>

<!-- Regelt die Registrierung unserer App von Nachrichten durch Google -->
<service android:name=".RegistrationIntentService" android:exported="false">
</service>


Programmierung:

Schlussendlich haben wir nun alles vorbereitet, was wir benötigen, um den Empfang von GCM Nachrichten zu regeln.
Nun gilt es noch die nötigen Klassen/Dateien zu programmieren, die wir soeben in der AndroidManifest.xml-Datei definiert haben.

RegistrationIntentService.class:

Fangen wir mit der Registrierung unserer App beim Google Server an. Diese Klasse müssen wir bereitstellen, damit Google weiß, dass unsere App die Nachrichten von unserem Raspberry erhalten kann und welche Nachrichten an uns versendet werden sollen.
Ihr erstellt diese Datei, indem ihr in der linken Liste auf app->java->(Euer Package Name ohne Test oder ähnliches) geht und mit einem Rechtsklick “new” und dann “Java class” auswählt.
Gebt hier “RegistrationIntentService” ein.

Ersetzt den Inhalt der Datei mit dem gleich folgenden Code, aber achtet drauf, dass ihr die Zeile oberste mit “package ?????;” erhaltet!

import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.google.android.gms.gcm.GcmPubSub;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;

import java.io.IOException;

public class RegistrationIntentService extends IntentService {

 private static final String TAG = "RegistrationIntentService";
 private static final String[] TOPICS = {"bewegung"};

 public RegistrationIntentService() {
 super(TAG);
 }

 // Diese Funktion wird von Android aufgerufen, wenn Google unsere App über GCM registriert hat.
 @Override
 protected void onHandleIntent(Intent intent) {
 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

 try {
 InstanceID instanceID = InstanceID.getInstance(this);
 String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
 GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

 subscribeTopics(token);

 sharedPreferences.edit().putBoolean(Einstellungen.SENT_TOKEN_TO_SERVER, true).apply();
 } catch (Exception e) {
 sharedPreferences.edit().putBoolean(Einstellungen.SENT_TOKEN_TO_SERVER, false).apply();
 }

 Intent registrationComplete = new Intent(Einstellungen.REGISTRATION_COMPLETE);
 LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
 }
 // Mit dieser Funktion registrieren wir unsere App für das Thema "bewegung".
 // Alle Push Nachrichten, die unser Pi über GCM mit dem Thema/topic "bewegung" sendet werden ab jetzt von Google an diese App weitergeleitet.
 private void subscribeTopics(String token) throws IOException {
 GcmPubSub pubSub = GcmPubSub.getInstance(this);
 for (String topic : TOPICS) {
 pubSub.subscribe(token, "/topics/" + topic, null);
 }
 }

}

InstanceListener.class:

Diese Klasse müssen wir bereitstellen, damit unsere App die Registrierung auf dem Google Server als bestätigt ansehen kann.
Ihr erstellt diese Datei, indem ihr in der linken Liste auf app->java->(Euer Package Name ohne Test oder ähnliches) geht und mit einem Rechtsklick “new” und dann “Java class” auswählt.
Gebt hier “InstanceListener” ein.

Ersetzt den Inhalt der Datei mit dem gleich folgenden Code, aber achtet drauf, dass ihr die oberste Zeile mit “package ?????;” erhaltet!

import android.content.Intent;
import com.google.android.gms.iid.InstanceIDListenerService;

public class InstanceListener extends InstanceIDListenerService {

 // Diese Funktion wird aufgerufen, falls sich der Token unserer Registrierung bei GCM ändert und speichert den neuen Token wieder über die Klasse "RegisterIntentService".
 @Override
 public void onTokenRefresh() {
 Intent intent = new Intent(this, RegistrationIntentService.class);
 startService(intent);
 }
}

GcmListener.class:

Diese Klasse müssen wir bereitstellen, damit unsere App alle Nachrichten auch empfangen kann.
Ihr erstellt diese Datei, indem ihr in der linken Liste auf app->java->(Euer Package Name ohne Test oder ähnliches) geht und mit einem Rechtsklick “new” und dann “Java class” auswählt.
Gebt hier “GcmListener” ein.

Ersetzt den Inhalt der Datei mit dem gleich folgenden Code, aber achtet drauf, dass ihr die oberste Zeile mit “package ?????;” erhaltet!

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

import com.google.android.gms.gcm.GcmListenerService;

import org.json.JSONException;
import org.json.JSONObject;

public class GcmListener extends GcmListenerService {

 @Override
 public void onMessageReceived(String from, Bundle data) {
 String jsonString = data.getString("message");

 String ort = "Unbekannt";
 Long zeitUnix = 0L;
 DateFormat formatter ;
 Date date = null;
 formatter = new SimpleDateFormat("HH:mm dd.MM.yyy");

 try {

 // JSON einlesen
 JSONObject message = new JSONObject(jsonString);

 // Lese die Zeit und den Ort aus und erstelle aus der Unix Zeit ein lesbares Datum.
 ort = message.getString("O");
 zeitUnix = message.getInt("T") * 1000L;
 date = new java.util.Date(zeitUnix);

 // Prüfe, ob es sich bei der Benachrichtigung um das richtige Thema handelt.
 if (from.startsWith("/topics/bewegung")) {
 sendNotification(ort + " - " + formatter.format(date), getIdentifier(ort));
 }

 } catch (JSONException e) {
 e.printStackTrace();
 }

 }

 // Erstelle aus jedem Ort eine eindeutige ID, damit es für jeden Ort eine eigene Banchrichtigung gibt.
 public int getIdentifier(String str) {
 try {
 int id = 0;
 for (Byte t : str.getBytes("UTF-8")) {
 id += t.intValue();
 }
 return id;
 } catch (UnsupportedEncodingException e) {
 return 0;
 }
 }

 // Gib eine Benachrichtigung aus.
 private void sendNotification(String message, int id) {
 Intent intent = new Intent(this, MainActivity.class);
 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
 PendingIntent.FLAG_ONE_SHOT);

 Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
 NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
 .setSmallIcon(R.mipmap.ic_launcher)
 .setContentTitle("Bewegungsmelder")
 .setContentText(message)
 .setAutoCancel(true)
 .setSound(defaultSoundUri)
 .setContentIntent(pendingIntent);

 NotificationManager notificationManager =
 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

 notificationManager.notify(id, notificationBuilder.build());
 }
}

[EDIT]: Der Import lautet ab Android Studio 3 android.support.v4.app.NotificationCompat und nicht mehr android.support.v7.app.NotificationCompat. Dank an Lenny.

Einstellungen.class:

Diese Klasse ist nicht unbedingt notwendig. Sie enthält einige Einstellungsnamen, die wir in verschiedenen Klassen aufrufen. Wir benutzen die Klasse Einstellungen, damit wir bei Änderungen der Einstellungsnamen nur diese Klasse ändern müssen und nicht in jeder verwendenden Klasse. Wir sparen uns also Arbeit.
Ihr erstellt diese Datei, indem ihr in der linken Liste auf app->java->(Euer Package Name ohne Test oder ähnliches) geht und mit einem Rechtsklick “new” und dann “Java class” auswählt.
Gebt hier “Einstellungen” ein.

Ersetzt den Inhalt der Datei mit dem gleich folgenden Code, aber achtet drauf, dass ihr die oberste Zeile mit “package ?????;” erhaltet!

public class Einstellungen {

 public static final String SENT_TOKEN_TO_SERVER = "Token";
 public static final String REGISTRATION_COMPLETE = "registrationComplete";

}

Erster Start:

Beim ersten Start der App muss die App sich nun bei Google registrieren. Ersetzt den Inhalt der Datei “MainActivity” mit dem gleich folgenden Code, aber achtet drauf, dass ihr die oberste Zeile mit “package ?????;” erhaltet!

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {
 
 private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
 private boolean isReceiverRegistered = false;
 private BroadcastReceiver mRegistrationBroadcastReceiver;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 // Prüfe, ob auf dem Gerät der Google PlayService installiert ist.
 // Dieser wird für den Empfang der GCM Nachrichten benötigt.
 if(checkPlayServices()) {

 // Erstelle einen Listener, der immer dann ausgeführt wird, wenn die App bei GCM registriert wurde oder ein Fehler bei der Registrierung auftrat.
 mRegistrationBroadcastReceiver = new BroadcastReceiver() {
 @Override
 public void onReceive(Context context, Intent intent) {
 SharedPreferences sharedPreferences =
 PreferenceManager.getDefaultSharedPreferences(context);
 boolean sentToken = sharedPreferences
 .getBoolean(Einstellungen.SENT_TOKEN_TO_SERVER, false);
 }
 };

 // Starte den oben beschriebenen Listener.
 registerReceiver();

 // Starte einen IntentService, um die App bei GCM zu registrieren.
 Intent intent = new Intent(this, RegistrationIntentService.class);
 startService(intent);

 }


 }

 private boolean checkPlayServices() {
 GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
 int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
 if (resultCode != ConnectionResult.SUCCESS) {
 if (apiAvailability.isUserResolvableError(resultCode)) {
 apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
 .show();
 } else {
 finish();
 }
 return false;
 }
 return true;
 }

 // Ab hier folgen Fehlerkorrekturen, damit die App auch beim Neustart funktioniert.
 @Override
 protected void onResume() {
 super.onResume();
 registerReceiver();
 }

 @Override
 protected void onPause() {
 LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
 isReceiverRegistered = false;
 super.onPause();
 }

 private void registerReceiver(){
 if(!isReceiverRegistered) {
 LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver, new IntentFilter(Einstellungen.REGISTRATION_COMPLETE));
 isReceiverRegistered = true;
 }
 }
}

Schlusswort:

Nun könnt ihr die App von Android Studio erstellen lassen und beim ersten Start der App registriert sich diese bei Google.
Probiert nun einfach aus, was passiert, wenn der Bewegungsmelder etwas registriert.
Die Benachrichtigungen erfolgen auch bei einem Neustart von Android.

Wir werden versuchen in näherer Zukunft auch eine einfache Android App im Google PlayStore zu veröffentlichen, mit der die Einrichtung einfacher wird.

Weitere Raspberry Pi + Android Smartphone Projekte findet ihr auf StaticFloat und www.tutorials-raspberrypi.de.

[DM id=”644″]

Marvin

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.

Hat dir dieser Artikel gefallen?

Kommentar hinzufügen

*Pflichtfeld

  1. Personx

    Hallo, danke für das Tutorial :) Ich bin noch komplett unerfahren und habe alles Schritt für Schritt befolgt, allerdings habe ich in 4 Skripten Errors. Alle haben fangen mit R. ... . ... an also das R wird iwie nicht akzeptiert. Und zu dem MainActivity Script, dass hat wshl scheinlich dann meinen Projektnamen oder ? Weil eins welches MainActivity habe ich nicht, soll ich meins (welches RPI) heißt lieber dazu umbenennen oder den Code einfach da einfügen. Weiter so ! LG

  2. Melvin

    Hallo, bei den Pfaden, die "R. ... . ..." heißen handelt es sich um den Packagepfad der Ressource. Meistens kannst du diesen Fehler beheben, indem du einen "Gradle Sync" durchführst. Das heißt, dass alle Ressourcen, die mit einem beginnenden "R." aufgeführt sind auch so bleiben müssen. Alle weiteren Java Klassen, die du selber erstellt hast (wie die MainActivity) müssen natürlich mit deinem Packagenamen beginnen. Gruß, Melvin

  3. Personx

    Thx für deine Antwort. Der Gradle Sync hat leider nichts bewirkt. Mein package wird in der ersten Zeile immer geladen, wie es in diesem Tutorial beschrieben ist. Aber bei : GcmListener ist der error hier: .setSmallIcon(R.mipmap.ic_launcher) --> bei R MainActivity: setContentView(R.layout.activity_main); --> bei R RegistrationIntentService: String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId), --> auch bei R Und ich gehe mal davon aus, dass diese Pfade nicht geändert werden sollten?! Lieben Gruß

  4. Melvin

    Dein Fehler kann mehrere Gründe haben, aber in jedem Fall fehlt die Datei R.java oder sie ist fehlerhaft. Diese Datei wirst du nicht sehen können und du solltest sie auch nicht selber erstellen. Sie wird von Android Studio generiert. Fehlt sie, dann gibt es den von dir beschriebenen Fehler. Manchmal kann diese R.java Datei aber auch "einfach so" mal fehlen und ein Gradle Sync und/oder Build helfen weiter, ohne dass explizit Fehler vorliegen müssen. Versuche als Erstes mal über den Menüpunkt "Build" einen "Clean Project" und dann einen "Build Project" mit anschließendem "Gradle Sync". Hilft das nicht, dann gibt es höchstwahrscheinlich einen Fehler in einer der XML-Dateien. Bitte prüfe einmal alle .xml-Dateien. Der/Die Fehler werden in der Regel in der rechten Scrollbar von Android Studio als rote Balken oder Quadrate dargestellt. Hier mal ein Beispiel mit Warnungen (gelb) und weiteren Hinweisen (grün): Ich versuche es gleich mal nachzustellen. Gruß, Melvin

  5. Personx

    Ich habe es jetzt noch mal mit einem neuen Projekt ausprobiert, dort entsteht der gleiche Fehler. Eine Sache muss ich anders machen als im Tutorial: Bei dem build.gradle(modul:app) muss ich folgende Zeile schreiben: compile "com.google.android.gms:play-services-gcm:10.2.1" -> die 9.4.0 ist zu alt. Es ist ja von eurer Seite aus in Planung eine fertige App in den Playstore zu stellen ? Gibt es da schon weitere Pläne ?

  6. Melvin

    Den Tipp werde ich mir merken. Die App ist weiterhin in Arbeit. Leider habe ich momentan nicht die nötige Zeit parat mich intensiv mit der App zu beschäftigen und weiter daran zu programmieren. Aber nächste Woche ist wieder Land in sich, dann geht es weiter. :) Wird sich also nicht mehr um Monate handeln. Gruß, Marvin

  7. Lenny

    Hallo, ich habe ein Problem mit deiner Anleitung, ich erhalte beim Gradle Sync immer diese beiden Fehler, leider kann ich damit nichts anfangen. Die Versionsfehler konnte ich eleminieren, jedoch weiß ich nicht ob dies Auswirkungen auf den restlichen Code hatte. Error: Attribute permission#de.Andre.PiBewegungsmelder.permission.C2D_MESSAGE@name value=(.permission.C2D_MESSAGE) from AndroidManifest.xml:7:17-55 is also present at AndroidManifest.xml:29:9-63 value=(de.Andre.PiBewegungsmelder.permission.C2D_MESSAGE). Suggestion: add 'tools:replace="android:name"' to element at AndroidManifest.xml:7:5-94 to override. app main manifest (this file), line 6 Error: Attribute uses-permission#de.Andre.PiBewegungsmelder.permission.C2D_MESSAGE@name value=(.permission.C2D_MESSAGE) from AndroidManifest.xml:8:22-60 is also present at AndroidManifest.xml:32:22-76 value=(de.Andre.PiBewegungsmelder.permission.C2D_MESSAGE). Suggestion: add 'tools:replace="android:name"' to element at AndroidManifest.xml:8:5-63 to override. app main manifest (this file), line 7 Desweiteren habe ich hier auf "v4" anstatt "v7" umgeswiched, da ich sonst hätte eine neue Class erstellen müssen, wird zumindest vorgeschlagen... Vielleicht kannst du Helfen. Danke import android.support.v4.content.LocalBroadcastManager;

  8. Melvin

    Hallo Lenny, selbiges Problem hatte ich die Tage auch. Werde den Artikel gleich noch einmal korrigieren. Danke dir. Bitte gehe einmal in die AndroidManbifest.xml Datei und Ersetze die beiden Zeilen: <permission android:name=".permission.C2D_MESSAGE" /> <uses-permission android:name=".permission.C2D_MESSAGE" /> durch folgendes: <permission android:name=".permission.C2D_MESSAGE" tools:replace="android:name" android:protectionLevel="signature" /> <uses-permission android:name=".permission.C2D_MESSAGE" tools:replace="android:name" /> Der Wechsel von v7 auf v4 war genau richtig. Ich nehme des Weiteren an, dass du Android Studio 3+ benutzt. Achte bitte darauf, dass in den build.gradle Dateien, in denen "jcenter()" steht auch noch zusätzlich (am Besten darunter) "google()" aufgeführt wird. In meiner build.gradle Datei stand jcenter zwei mal. Bei weiteren Fragen kannst du gerne wieder schreiben. Ich hoffe geholfen zu haben. Gruß, Melvin

  9. Hermann Nienaber

    Hallo Melvin, gibt es schon eine Grund-APP von dir oder wird diese noch kommen? Ich habe versucht, mich mit der Anleitung durchzuhangeln. Aber leider sind viele Programmversionen oder Dienste inzwischen überholt und in der Bedienung nun ganz anders (Google Firebase, AndroidStudio 3.2). Die eigene APP nach Kochbuchmanier bekomme ich so nicht hin bzw. wächst mir dieses "Neben"-Projekt über den Kopf... Gruß Hermann

  10. Melvin

    Hallo Hermann, Was genau meinst du mit einer "Grund-App"? Gruß, Melvin

  11. Dominik

    Hallo Melvin, wenn mal zeit hast und dich mit mir in Verbindung setzen würdest wäre ich dir sehr dankbar! Ich habe hier von dem App schrei gar keine Ahnung. Mit freundlichen Grüßen Dominik

  12. David

    Beim Punkt AndroidManifest.xml findet sich kein Code im Codefenster. Was sollte da stehen? Danke im Voraus, David

  13. JonesO

    Ich versteh das nicht wirklich.
    Warum gibt es nicht einfach ne fertige apk zum Download?

  14. Marvin

    Hallo JonesO,

    es gibt hier keine fertige APK, da dieses Projekt von der Marke "Eigenbau" ist und damit nicht einfach im PlayStore zur Verfügung steht. Es geht darum etwas eigenes geschaffen zu haben und den Spaß an der Freude zu basteln und nicht nur zu konfigurieren. Solltest du nicht selber programmieren können oder wollen, so würde ich dir folgende Alternativen empfehlen: Homebridge (Apple), IFTT oder OpenHab

    Die haben so alle ihre Vor- und Nachteile. Lies dich am Besten mal ein, was geht und was für dich passt.

    Gruß
    Marvin