Guten Tag,
Ich versuche eine App zu programmieren, mit welcher ich Strings an einen Arduino (hc05) schicken kann. Als Beispielcode habe ich mich an diesem hier orientiert: solderer.tv/data-transfer-between-android-and-arduino-via-bluetooth/
Funktioniert auch soweit bestens. Nun habe ich ein Menü, und dementsprechend auch zwei Klassen geschrieben, durch die ich mittels einem Klick, auf die Menüoberfläche, gelange. Gedacht war, durch ein weiteren Klick auf einem Button in der jeweiligen Klasse die oben verlinkte Bluetoothklasse (heißt bei mir Blauzahn) aufzurufen:
Blauzahn bl1=new Blauzahn();
bl1.sendData("10110");
Jedoch bin ich dann ja garnicht dauerhaft mit meinem Bluetoothmodul verbunden, sondern erst wenn ich Blauzahn aufruf... Da der Verbindungsaufbau immer etwas braucht bekomme ich hier dann den Fehler das ich nicht verbunden bin.
Nun zur eigentlichen Frage:
Gibt es eine Möglichkeit die Bluetooth-klasse dauerhaft aktiv zu haben, egal in welcher Oberfläche/Klasse ich mich befinde?
Hoffe es ist einigermaßen Verständlich,
Guten Rutsch!
Android: Bluetooth-Klasse durch andere Klasse aufrufen
-
-
Hallo, du könntest die Kommunikation mit einem Service der von deiner activity gestartet ,beendet, bedient werden kann realisieren. Im Service lässt du die Verbindung offen bis du ihn beendest.
Habe mir mal das Beispiel angesehen. Da ist es so das in der onResume die Verbindung aufgebaut und in der onPause geschlossen wird. Wo und wie machst du das?
"Nun habe ich ein Menü, und dementsprechend auch zwei Klassen geschrieben, durch die ich mittels einem Klick, auf die Menüoberfläche, gelange." Damit meist du bestimmt Activitys oder ?
könntest auch versuchen die Blauzahn Klasse und Methoden static zu machen, dann ist sie ohne Instanz nutzbar und in der App immer verfügbar.
Den Verbindungs aufbau und ende solltest du nicht mit Callback Methoden machen sondern manuell. Damit nicht die Verbindung neu aufgebaut wird wenn du von einer Activity zur anderen gehst. -
Danke für deine schnelle Antwort!
""[i]Nun habe ich ein Menü, und dementsprechend auch zwei Klassen geschrieben, durch die ich mittels einem Klick, auf die Menüoberfläche, gelange." Damit meist du bestimmt Activitys oder ?"[/i]
Ja, habe zwei activitys mit dazugehörigen Java-klassen geschrieben, sorry:)
Das mit den Service klingt nach genau dem, wonach ich gesucht habe. Da ich sehr unerfahren mit Android bin habe ich mir auch hier ein Beispielcode mal rausgesucht: http://blog.rhesoft.com/2016/0…-services-android-studio/
Jedoch weiß ich nicht, wie ich im Service Handler unter HandleMessage meinen Code implementieren soll? Das Problem liegt (denke ich) bei der Vererbung, da ich nun ja service und nicht mehr Activity extende...
Das mit dem Verbindungsaufbau und -ende muss ich auch erst noch lösen, bis jetzt habe ich es einfach noch da stehen. Meinst du so etwas in der Art wie bei betätigung eines Buttons on wird onResume() aufgerufen, bei off dann onPause()? Ich finde in der jetzigen methode garnicht wodurch onResume() und onPause() das aufgerufen wird...
Danke nochmals für dein großartige Hilfe! -
Hi, zum Thema Verbindungs Auf u. Abbau ich gehe von diesen hier aus.
http://solderer.tv/data-transf…nd-arduino-via-bluetooth/
Da wird in der onResume Methode die verbindung aufgebaut. onResume ist eine von Android selbst beim start einer Activity aufgerufenne Methote. onPause genau das selbe nur wird sie beim verlassen der Activity von Android aufgerufen. Zumindestens ist das in dem Beispiel so was du zu grundlage genommen hast. Das hat nichts mit den Button zu tuhen. Schaue dir dazu den Lifecycle einer Activity an. http://www.programmierenlernen…y-und-fragment-lifecycle/Ich wolte wissen wo und wie du den Aufbau der verbindung machst. Auch ist es besser das senden und Empfangen in einen eigenen Thread zu machen so wie das listing 2 im Beispiel.
Das mit dem Srvice schau ich mir noch an.
-
Zum verständnis was ein service ist hier ein video
External Content www.youtube.comContent embedded from external sources will not be displayed without your consent.Through the activation of external content, you agree that personal data may be transferred to third party platforms. We have provided more information on this in our privacy policy. -
Zum Verbindungsaufbau: Ich habe die Mac-adresse in der App eingegeben und mich mit dem hc05-Modul gepaart. Beim öffnen der App auf dem smartphone verbindet sich diese von allein mit dem HC-05-das funktioniert. Hab mal meinen Code für den Hintergrund-Service angehängt(Ab Zeile 85 fängt die Bluetooth klasse an (Ich weiß, besser ist ne neue Klasse anlegen..)). Starte den Service in der Main mit: Intent service = new Intent(this, Hintergrund.class); startService(service);. Wie kann ich nun Zeile 78 am besten in meinen anderen Klassen aufrufen/Daten übermitteln? Geht das ganz normal wie bei Methoden anderer Klassen?
Danke für deine Geduld!
Java
Display Morepackage com.example.bluetooth1; import android.app.Activity; import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.os.*; import android.os.Process; import android.widget.Toast; import java.io.OutputStream; import java.util.UUID; import java.io.IOException; import java.lang.reflect.Method; import android.bluetooth.BluetoothDevice; import android.os.Build; import android.os.Bundle; import android.util.Log; public class Hintergrund extends Service { private static final String TAG = "bluetooth1"; private Looper mServiceLooper; private ServiceHandler mServiceHandler; @Override public void onCreate() { // To avoid cpu-blocking, we create a background handler to run our service HandlerThread thread = new HandlerThread("TutorialService", Process.THREAD_PRIORITY_BACKGROUND); // start the new handler thread thread.start(); mServiceLooper = thread.getLooper(); // start the service using the background handler mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show(); // call a new service handler. The service ID can be used to identify the service Message message = mServiceHandler.obtainMessage(); message.arg1 = startId; mServiceHandler.sendMessage(message); return START_STICKY; } protected void showToast(final String msg){ //gets the main thread Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { // run this code in the main thread Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } }); } @Override public IBinder onBind(Intent intent) { return null; } // Object responsible for private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { Blauzahn bl1=new Blauzahn(); bl1.sendData("DIESEN TEXT WILL ICH SENDEN"); } public class Blauzahn extends Activity { private static final String TAG = "bluetooth1"; //Bluetooth Adapter Initialisierung private BluetoothAdapter btAdapter = null; private BluetoothSocket btSocket = null; private OutputStream outStream = null; // SPP UUID service private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // MAC-address von unserem Bluetooth modul private String address = "98:D3:31:FB:6C:B2"; //Wird beim ersten Start aaufgerufen @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //checkt, ob Bluetooth am Gerät aktiviert ist btAdapter = BluetoothAdapter.getDefaultAdapter(); checkBTState(); } //Bluetooth-hardware check private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException { if(Build.VERSION.SDK_INT >= 10) { try { final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class }); return (BluetoothSocket) m.invoke(device, MY_UUID); } catch (Exception e) { Log.e(TAG, "Could not create Insecure RFComm Connection",e); } } return device.createRfcommSocketToServiceRecord(MY_UUID); } //Bluetooth verbindungsaufbau @Override public void onResume() { super.onResume(); Log.d(TAG, "...onResume - try connect..."); BluetoothDevice device = btAdapter.getRemoteDevice(address); try { btSocket = createBluetoothSocket(device); } catch (IOException e1) { errorExit("Fatal Error", "In onResume() and socket create failed: " + e1.getMessage() + "."); } // Verbindungsaufbau-blockiert, bis verbunden btAdapter.cancelDiscovery(); //Data-Stream wird erstellt um Verbindungsaufbau zum Server durchzusetzen Log.d(TAG, "...Connecting..."); try { btSocket.connect(); Log.d(TAG, "...Connection ok..."); } catch (IOException e) { try { btSocket.close(); } catch (IOException e2) { errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + "."); } } Log.d(TAG, "...Create Socket..."); try { outStream = btSocket.getOutputStream(); } catch (IOException e) { errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + "."); } } @Override public void onPause() { super.onPause(); Log.d(TAG, "...In onPause()..."); if (outStream != null) { try { outStream.flush(); } catch (IOException e) { errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + "."); } } try { btSocket.close(); } catch (IOException e2) { errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + "."); } } //Überprüft Bluetooth Zustand private void checkBTState() { if(btAdapter==null) { errorExit("Fatal Error", "Bluetooth not support"); } else { if (btAdapter.isEnabled()) { Log.d(TAG, "...Bluetooth ON..."); } else { //Zeigt an, dass Bluetooth angeschaltet werden muss Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, 1); } } } //Fehlermeldung private void errorExit(String title, String message) { Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show(); finish(); } //Methode um Daten über Bluetooth zu senden public void sendData(String message) { byte[] msgBuffer = message.getBytes(); Log.d(TAG, "...Send data: " + message + "..."); try { outStream.write(msgBuffer); } catch (IOException e) { String msg = "In onResume() and an exception occurred during write: " + e.getMessage(); if (address.equals("00:00:00:00:00:00")) msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 35 in the java code"; msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n"; errorExit("Fatal Error", msg); } } } } }
-
Was überhaupt nicht geht ist in der Klasse Hintergrund (service) eine neue innerere Klasse von Activity zu erstellen. Die muss in eine eigene Datei. Denke du hast das Prinziep vom einen Service noch nicht verstanden, eben so noch nicht was die die Activity Callback Methoden sind schaue dir meinen link dazu noch mal an.
Denn du hast den gesamten verbindungs aufbau, datensenden ... noch in der Activity. Wenn du das mit einen Service machen willst muss das im service erledigt werden .
In einem Service kannst du keine innere Klasse erstellen die von activity erbt das ist totaler Nonsens.
Ebenfals kannst du auch in einer activity nicht eine neue Klasse von activity machen.
Außerdem ist es so das ein Service sowas wie ein eigenständiger Programm Teil ist. Von diesen kannst du keine Methoden der acktivty und umgekehrt benutzen. Die beiden unterhalten sich über Nachrichten. Da muss der Service schon alle Funktionen zum verbinden selber an Board haben. Da kann ich in deinen Code nichs erkennen.Ich denke du läst das erstmal mit dem Sevice und versuchst es ohne. Dein Vorhaben solle
ohne Service auch gehen.Was genau willst du eigentlich machen?
Erläutere Mal dein Vorhaben denke dein Ansatz ist falsch. -
Wenn du Zwei Activitys hast in denen verschiedene menus und button sind die daten Senden sollen.
Deine Komunikation sich in der Blauzahn klasse abspielen soll, must und darf die Blauzahn klasse nicht von Activity erben.
Erstelle dir in der Bauzahn Kasse eine Methode zum Verbindungs aufbau, benden , zum daten senden.
Rufe die methoden selber in deine Activity auf . Wie gesagt schaue dir den Lifecycle noch mal an.Wenn du programmteile auslagern willst weil du sie in mehreren activitys Bildschirmseiten benutzen willst. Braucht die neue Klasse nicht zu erben und schon gar nicht von Activity.
Wenn du Variablen in der Klasse beim Instanzsieren setzen willst benutze den Konstuktor.
Wie schon gesagt eine activity in einer activity geht nicht. Genau das machst du wenn du von deiner Blauzahn klasse eine Instanz erstellst, da deine blauzahn klasse von activity erbt. -
So habe mal aus deinen Code eine Klasse Blauzahn erstellt
Java
Display Morepublic class Blauzahn { private static final String TAG = "bluetooth1"; Context context; //Bluetooth Adapter Initialisierung private BluetoothAdapter btAdapter = null; private BluetoothSocket btSocket = null; private OutputStream outStream = null; // SPP UUID service private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // MAC-address von unserem Bluetooth modul private String address = "98:D3:31:FB:6C:B2"; public Blauzahn(Context c){ context = c; } private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException { if(Build.VERSION.SDK_INT >= 10) { try { final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class }); return (BluetoothSocket) m.invoke(device, MY_UUID); } catch (Exception e) { Log.e(TAG, "Could not create Insecure RFComm Connection",e); } } return device.createRfcommSocketToServiceRecord(MY_UUID); } //Bluetooth verbindungsaufbau public void Verbindungstarten() { btAdapter = BluetoothAdapter.getDefaultAdapter(); checkBTState(); Log.d(TAG, "...onResume - try connect..."); BluetoothDevice device = btAdapter.getRemoteDevice(address); try { btSocket = createBluetoothSocket(device); } catch (IOException e1) { errorExit("Fatal Error", "In onResume() and socket create failed: " + e1.getMessage() + "."); } // Verbindungsaufbau-blockiert, bis verbunden btAdapter.cancelDiscovery(); //Data-Stream wird erstellt um Verbindungsaufbau zum Server durchzusetzen Log.d(TAG, "...Connecting..."); try { btSocket.connect(); Log.d(TAG, "...Connection ok..."); } catch (IOException e) { try { btSocket.close(); } catch (IOException e2) { errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + "."); } } Log.d(TAG, "...Create Socket..."); try { outStream = btSocket.getOutputStream(); } catch (IOException e) { errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + "."); } } public void VerbindungBeenden() { Log.d(TAG, "...In onPause()..."); if (outStream != null) { try { outStream.flush(); } catch (IOException e) { errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + "."); } } try { btSocket.close(); } catch (IOException e2) { errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + "."); } } private void checkBTState() { if(btAdapter==null) { errorExit("Fatal Error", "Bluetooth not support"); } else { if (btAdapter.isEnabled()) { Log.d(TAG, "...Bluetooth ON..."); } else { //Zeigt an, dass Bluetooth angeschaltet werden muss Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, 1); } } } private void startActivityForResult(Intent enableBtIntent, int i) { } //Fehlermeldung private void errorExit(String title, String message) { Toast.makeText(context, title + " - " + message, Toast.LENGTH_LONG).show(); } //Methode um Daten über Bluetooth zu senden public void sendData(String message) { byte[] msgBuffer = message.getBytes(); Log.d(TAG, "...Send data: " + message + "..."); try { outStream.write(msgBuffer); } catch (IOException e) { String msg = "In onResume() and an exception occurred during write: " + e.getMessage(); if (address.equals("00:00:00:00:00:00")) msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 35 in the java code"; msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n"; errorExit("Fatal Error", msg); } }
Die MainActivity aus dem Beispiel.
Java
Display Morepublic class MainActivity extends Activity { private static final String TAG = "bluetooth1"; Button btnOn, btnOff; Blauzahn bl1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnOn = (Button) findViewById(R.id.btnOn); btnOff = (Button) findViewById(R.id.btnOff); bl1 = new Blauzahn(this); btnOn.setOnClickListener(new OnClickListener() { public void onClick(View v) { bl1.sendData("1"); Toast.makeText(getApplicationContext(), "Turn on LED", Toast.LENGTH_SHORT).show(); } }); btnOff.setOnClickListener(new OnClickListener() { public void onClick(View v) { bl1.sendData("0"); Toast.makeText(getApplicationContext(), "Turn off LED", Toast.LENGTH_SHORT).show(); } }); } @Override public void onResume() { super.onResume(); bl1.Verbindungstarten(); } @Override public void onPause() { super.onPause(); bl1.VerbindungBeenden(); } }
Die Verbindung wird automatisch beim sichtbar werden der Activity hergestellt. Dies wird durch den aufruf der onResume vom Bs automatisch gemacht. Kannst es aber auch auf einen Button legen.
Der Verbindungs abbau wird auch automatisch in der onPause gemacht. Diese Methode wird auch vom BS selber aufgerufen wenn die Activity beendet oder in den Hintergrund tritt. Wenn du einen Intent zu einer anderen Activity machst wird die alte Activity beendet und somit auch die Verbindung unterbrochen. Die müsstest du dann in der neuen Activity wieder neu aufbauen entweder in den Callback Methoden oder Mannuel z.B. Button.https://de.wikibooks.org/wiki/Googles_Android/_Bluetooth
https://www.frag-duino.de/inde…einem-arduino-und-androidPS. habe noch eine kleinigkeit im Code geändert .
-
Wow, Danke für deine Hilfe!
Habe es jetzt hinbekommen, auch ohne Service
Da muss ich wohl mich noch ein bisschen einarbeiten...
Ich möchte damit über eine App an ein Arduino Befehle senden, welcher dann Servomotoren ansteuert (Wird eine Roboterhand).Vielen Dank für deine Ausführlichen Erklärungen, du hast mir sehr geholfen! Konnte es jetzt so lösen, das die Verbindung bei jeder neuen Activity aufgebaut wird. Geht aber so schnell das es kaum auffällt... Funktioniert soweit
Liebe GrüßePixhawk
-
Freut mich das ich helfen konnte
Participate now!
Don’t have an account yet? Register yourself now and be a part of our community!