Android: Bluetooth-Klasse durch andere Klasse aufrufen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Android: Bluetooth-Klasse durch andere Klasse aufrufen

    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! :rolleyes:
  • 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.
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von jogimuc ()

  • 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: blog.rhesoft.com/2016/03/14/tu…-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.
    solderer.tv/data-transfer-betw…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. programmierenlernenhq.de/tutor…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.
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von jogimuc ()

  • 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-Quellcode

    1. package com.example.bluetooth1;
    2. import android.app.Activity;
    3. import android.app.Service;
    4. import android.bluetooth.BluetoothAdapter;
    5. import android.bluetooth.BluetoothSocket;
    6. import android.content.Intent;
    7. import android.os.*;
    8. import android.os.Process;
    9. import android.widget.Toast;
    10. import java.io.OutputStream;
    11. import java.util.UUID;
    12. import java.io.IOException;
    13. import java.lang.reflect.Method;
    14. import android.bluetooth.BluetoothDevice;
    15. import android.os.Build;
    16. import android.os.Bundle;
    17. import android.util.Log;
    18. public class Hintergrund extends Service {
    19. private static final String TAG = "bluetooth1";
    20. private Looper mServiceLooper;
    21. private ServiceHandler mServiceHandler;
    22. @Override
    23. public void onCreate() {
    24. // To avoid cpu-blocking, we create a background handler to run our service
    25. HandlerThread thread = new HandlerThread("TutorialService",
    26. Process.THREAD_PRIORITY_BACKGROUND);
    27. // start the new handler thread
    28. thread.start();
    29. mServiceLooper = thread.getLooper();
    30. // start the service using the background handler
    31. mServiceHandler = new ServiceHandler(mServiceLooper);
    32. }
    33. @Override
    34. public int onStartCommand(Intent intent, int flags, int startId) {
    35. Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show();
    36. // call a new service handler. The service ID can be used to identify the service
    37. Message message = mServiceHandler.obtainMessage();
    38. message.arg1 = startId;
    39. mServiceHandler.sendMessage(message);
    40. return START_STICKY;
    41. }
    42. protected void showToast(final String msg){
    43. //gets the main thread
    44. Handler handler = new Handler(Looper.getMainLooper());
    45. handler.post(new Runnable() {
    46. @Override
    47. public void run() {
    48. // run this code in the main thread
    49. Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
    50. }
    51. });
    52. }
    53. @Override
    54. public IBinder onBind(Intent intent) {
    55. return null;
    56. }
    57. // Object responsible for
    58. private final class ServiceHandler extends Handler {
    59. public ServiceHandler(Looper looper) {
    60. super(looper);
    61. }
    62. @Override
    63. public void handleMessage(Message msg) {
    64. Blauzahn bl1=new Blauzahn();
    65. bl1.sendData("DIESEN TEXT WILL ICH SENDEN");
    66. }
    67. public class Blauzahn extends Activity
    68. {
    69. private static final String TAG = "bluetooth1";
    70. //Bluetooth Adapter Initialisierung
    71. private BluetoothAdapter btAdapter = null;
    72. private BluetoothSocket btSocket = null;
    73. private OutputStream outStream = null;
    74. // SPP UUID service
    75. private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    76. // MAC-address von unserem Bluetooth modul
    77. private String address = "98:D3:31:FB:6C:B2";
    78. //Wird beim ersten Start aaufgerufen
    79. @Override
    80. public void onCreate(Bundle savedInstanceState)
    81. {
    82. super.onCreate(savedInstanceState);
    83. //checkt, ob Bluetooth am Gerät aktiviert ist
    84. btAdapter = BluetoothAdapter.getDefaultAdapter();
    85. checkBTState();
    86. }
    87. //Bluetooth-hardware check
    88. private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException
    89. {
    90. if(Build.VERSION.SDK_INT >= 10)
    91. {
    92. try
    93. {
    94. final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
    95. return (BluetoothSocket) m.invoke(device, MY_UUID);
    96. }
    97. catch (Exception e)
    98. {
    99. Log.e(TAG, "Could not create Insecure RFComm Connection",e);
    100. }
    101. }
    102. return device.createRfcommSocketToServiceRecord(MY_UUID);
    103. }
    104. //Bluetooth verbindungsaufbau
    105. @Override
    106. public void onResume()
    107. {
    108. super.onResume();
    109. Log.d(TAG, "...onResume - try connect...");
    110. BluetoothDevice device = btAdapter.getRemoteDevice(address);
    111. try
    112. {
    113. btSocket = createBluetoothSocket(device);
    114. }
    115. catch (IOException e1)
    116. {
    117. errorExit("Fatal Error", "In onResume() and socket create failed: " + e1.getMessage() + ".");
    118. }
    119. // Verbindungsaufbau-blockiert, bis verbunden
    120. btAdapter.cancelDiscovery();
    121. //Data-Stream wird erstellt um Verbindungsaufbau zum Server durchzusetzen
    122. Log.d(TAG, "...Connecting...");
    123. try
    124. {
    125. btSocket.connect();
    126. Log.d(TAG, "...Connection ok...");
    127. }
    128. catch (IOException e)
    129. {
    130. try {
    131. btSocket.close();
    132. }
    133. catch (IOException e2)
    134. {
    135. errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
    136. }
    137. }
    138. Log.d(TAG, "...Create Socket...");
    139. try
    140. {
    141. outStream = btSocket.getOutputStream();
    142. } catch (IOException e)
    143. {
    144. errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
    145. }
    146. }
    147. @Override
    148. public void onPause()
    149. {
    150. super.onPause();
    151. Log.d(TAG, "...In onPause()...");
    152. if (outStream != null)
    153. {
    154. try
    155. {
    156. outStream.flush();
    157. }
    158. catch (IOException e)
    159. {
    160. errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
    161. }
    162. }
    163. try
    164. {
    165. btSocket.close();
    166. }
    167. catch (IOException e2)
    168. {
    169. errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
    170. }
    171. }
    172. //Überprüft Bluetooth Zustand
    173. private void checkBTState()
    174. {
    175. if(btAdapter==null)
    176. {
    177. errorExit("Fatal Error", "Bluetooth not support");
    178. }
    179. else
    180. {
    181. if (btAdapter.isEnabled())
    182. {
    183. Log.d(TAG, "...Bluetooth ON...");
    184. }
    185. else
    186. {
    187. //Zeigt an, dass Bluetooth angeschaltet werden muss
    188. Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    189. startActivityForResult(enableBtIntent, 1);
    190. }
    191. }
    192. }
    193. //Fehlermeldung
    194. private void errorExit(String title, String message)
    195. {
    196. Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
    197. finish();
    198. }
    199. //Methode um Daten über Bluetooth zu senden
    200. public void sendData(String message)
    201. {
    202. byte[] msgBuffer = message.getBytes();
    203. Log.d(TAG, "...Send data: " + message + "...");
    204. try
    205. {
    206. outStream.write(msgBuffer);
    207. }
    208. catch (IOException e)
    209. {
    210. String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
    211. if (address.equals("00:00:00:00:00:00"))
    212. 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";
    213. msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
    214. errorExit("Fatal Error", msg);
    215. }
    216. }
    217. }
    218. }
    219. }
    Alles anzeigen
  • 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.
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von jogimuc ()

  • 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.
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von jogimuc ()

  • So habe mal aus deinen Code eine Klasse Blauzahn erstellt

    Java-Quellcode

    1. public class Blauzahn
    2. {
    3. private static final String TAG = "bluetooth1";
    4. Context context;
    5. //Bluetooth Adapter Initialisierung
    6. private BluetoothAdapter btAdapter = null;
    7. private BluetoothSocket btSocket = null;
    8. private OutputStream outStream = null;
    9. // SPP UUID service
    10. private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    11. // MAC-address von unserem Bluetooth modul
    12. private String address = "98:D3:31:FB:6C:B2";
    13. public Blauzahn(Context c){
    14. context = c;
    15. }
    16. private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException
    17. {
    18. if(Build.VERSION.SDK_INT >= 10)
    19. {
    20. try
    21. {
    22. final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
    23. return (BluetoothSocket) m.invoke(device, MY_UUID);
    24. }
    25. catch (Exception e)
    26. {
    27. Log.e(TAG, "Could not create Insecure RFComm Connection",e);
    28. }
    29. }
    30. return device.createRfcommSocketToServiceRecord(MY_UUID);
    31. }
    32. //Bluetooth verbindungsaufbau
    33. public void Verbindungstarten()
    34. {
    35. btAdapter = BluetoothAdapter.getDefaultAdapter();
    36. checkBTState();
    37. Log.d(TAG, "...onResume - try connect...");
    38. BluetoothDevice device = btAdapter.getRemoteDevice(address);
    39. try
    40. {
    41. btSocket = createBluetoothSocket(device);
    42. }
    43. catch (IOException e1)
    44. {
    45. errorExit("Fatal Error", "In onResume() and socket create failed: " + e1.getMessage() + ".");
    46. }
    47. // Verbindungsaufbau-blockiert, bis verbunden
    48. btAdapter.cancelDiscovery();
    49. //Data-Stream wird erstellt um Verbindungsaufbau zum Server durchzusetzen
    50. Log.d(TAG, "...Connecting...");
    51. try
    52. {
    53. btSocket.connect();
    54. Log.d(TAG, "...Connection ok...");
    55. }
    56. catch (IOException e)
    57. {
    58. try {
    59. btSocket.close();
    60. }
    61. catch (IOException e2)
    62. {
    63. errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
    64. }
    65. }
    66. Log.d(TAG, "...Create Socket...");
    67. try
    68. {
    69. outStream = btSocket.getOutputStream();
    70. } catch (IOException e)
    71. {
    72. errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + ".");
    73. }
    74. }
    75. public void VerbindungBeenden()
    76. {
    77. Log.d(TAG, "...In onPause()...");
    78. if (outStream != null)
    79. {
    80. try
    81. {
    82. outStream.flush();
    83. }
    84. catch (IOException e)
    85. {
    86. errorExit("Fatal Error", "In onPause() and failed to flush output stream: " + e.getMessage() + ".");
    87. }
    88. }
    89. try
    90. {
    91. btSocket.close();
    92. }
    93. catch (IOException e2)
    94. {
    95. errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
    96. }
    97. }
    98. private void checkBTState()
    99. {
    100. if(btAdapter==null)
    101. {
    102. errorExit("Fatal Error", "Bluetooth not support");
    103. }
    104. else
    105. {
    106. if (btAdapter.isEnabled())
    107. {
    108. Log.d(TAG, "...Bluetooth ON...");
    109. }
    110. else
    111. {
    112. //Zeigt an, dass Bluetooth angeschaltet werden muss
    113. Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    114. startActivityForResult(enableBtIntent, 1);
    115. }
    116. }
    117. }
    118. private void startActivityForResult(Intent enableBtIntent, int i) {
    119. }
    120. //Fehlermeldung
    121. private void errorExit(String title, String message) {
    122. Toast.makeText(context, title + " - " + message, Toast.LENGTH_LONG).show();
    123. }
    124. //Methode um Daten über Bluetooth zu senden
    125. public void sendData(String message)
    126. {
    127. byte[] msgBuffer = message.getBytes();
    128. Log.d(TAG, "...Send data: " + message + "...");
    129. try
    130. {
    131. outStream.write(msgBuffer);
    132. }
    133. catch (IOException e)
    134. {
    135. String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
    136. if (address.equals("00:00:00:00:00:00"))
    137. 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";
    138. msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
    139. errorExit("Fatal Error", msg);
    140. }
    141. }
    Alles anzeigen
    Die MainActivity aus dem Beispiel.

    Java-Quellcode

    1. public class MainActivity extends Activity {
    2. private static final String TAG = "bluetooth1";
    3. Button btnOn, btnOff;
    4. Blauzahn bl1;
    5. @Override
    6. public void onCreate(Bundle savedInstanceState) {
    7. super.onCreate(savedInstanceState);
    8. setContentView(R.layout.activity_main);
    9. btnOn = (Button) findViewById(R.id.btnOn);
    10. btnOff = (Button) findViewById(R.id.btnOff);
    11. bl1 = new Blauzahn(this);
    12. btnOn.setOnClickListener(new OnClickListener() {
    13. public void onClick(View v) {
    14. bl1.sendData("1");
    15. Toast.makeText(getApplicationContext(), "Turn on LED", Toast.LENGTH_SHORT).show();
    16. }
    17. });
    18. btnOff.setOnClickListener(new OnClickListener() {
    19. public void onClick(View v) {
    20. bl1.sendData("0");
    21. Toast.makeText(getApplicationContext(), "Turn off LED", Toast.LENGTH_SHORT).show();
    22. }
    23. });
    24. }
    25. @Override
    26. public void onResume() {
    27. super.onResume();
    28. bl1.Verbindungstarten();
    29. }
    30. @Override
    31. public void onPause() {
    32. super.onPause();
    33. bl1.VerbindungBeenden();
    34. }
    35. }
    Alles anzeigen
    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.

    de.wikibooks.org/wiki/Googles_Android/_Bluetooth
    frag-duino.de/index.php/maker-…einem-arduino-und-android

    PS. habe noch eine kleinigkeit im Code geändert .
    Ein Feedback auf Tipps ist auch schön. :P

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von jogimuc ()

  • 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üße

    Pixhawk