2017-07-17 7 views
0

Ich versuche, eine App zu erstellen, die es ermöglicht, eine Zeichenfolge von einem Android-Telefon zu einem anderen zu senden. Der Code dafür ist unten angegeben. Es funktioniert jedoch nicht, da ich weiterhin Ausnahmen vom try-catch-Code im Abschnitt pairDevice() erhalte. Weiß jemand, warum ich das bekomme?So senden/empfangen Nachrichten über Bluetooth android Studio

import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothSocket; 
import android.content.Intent; 
import android.os.ParcelUuid; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.Toast; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.Scanner; 
import java.util.Set; 

public class MainActivity extends AppCompatActivity { 

    InputStream inStream; 
    OutputStream outputStream; 
    private static final int REQUEST_ENABLE_BT = 1; 

    public void pairDevice() { 
     BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) { 
      Intent enableBtIntent = new 
      Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
      startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);} 

     Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); 
     if (pairedDevices.size() > 0) { 
      Object[] devices = pairedDevices.toArray(); 
      BluetoothDevice device = (BluetoothDevice) devices[0]; 
      ParcelUuid[] uuid = device.getUuids(); 
      try { 
       BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid[0].getUuid()); 
       socket.connect(); 
       Toast.makeText(this, "Socket connected", Toast.LENGTH_LONG).show(); 
       outputStream = socket.getOutputStream(); 
       inStream = socket.getInputStream(); 
      } catch (IOException e) { 
       Toast.makeText(this, "Exception found", Toast.LENGTH_LONG).show(); 
      } 

     } 
    } 


public void SendMessage(View v) { 
    EditText outMessage = (EditText) findViewById(R.id.editText); 
    try { 
     if (outputStream != null) 
      outputStream.write(outMessage.toString().getBytes()); 
      TextView displayMessage = (TextView) findViewById(R.id.textView); 
      Scanner s = new Scanner(inStream).useDelimiter("\\A"); 
      displayMessage.setText(s.hasNext() ? s.next() : ""); 
    } catch (IOException e) {/*Do nothing*/} 
    Toast.makeText(this,"No output stream", Toast.LENGTH_LONG).show(); 
} 





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

}

Antwort

1

ich zu Ihrer App gemacht haben einige Änderungen: -

Zunächst verschob ich den Code verantwortlich für die Erstellung der Bluetooth-Verbindung zu ConnectThread.

2) hinzugefügt AcceptThread verantwortlich für das Hören und eingehende Verbindungen ConnectedThread die BTConnection Aufrechterhaltung, die Daten senden und Empfangen ankommende Daten, die durch Eingangs-/Ausgangsströme sind. 3) 2 Schaltflächen erstellt, um ConnectThread und AcceptThread zu starten.

HINWEIS: Stellen Sie sicher, dass beide Geräte gepaart sind und das Gerät, das Sie versuchen, an der Spitze der Liste zu verbinden ist (oder nur entfernen Sie alle die gekoppelten Geräte von beiden Geräte und koppeln nur die Geräte , die Sie verbinden möchten).Außerdem müssen Sie die AcceptThread vor ConnectThread

MAINACTIVITY.JAVA

public class MainActivity extends AppCompatActivity { 

    private static final UUID MY_UUID_INSECURE = 
      UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66"); 

    private static final int REQUEST_ENABLE_BT = 1; 
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
    private BluetoothDevice mmDevice; 
    private UUID deviceUUID; 
    ConnectedThread mConnectedThread; 
    private Handler handler; 

    String TAG = "MainActivity"; 
    EditText send_data; 
    TextView view_data; 
    StringBuilder messages; 






    public void pairDevice(View v) { 

     Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); 
     Log.e("MAinActivity", "" + pairedDevices.size()); 
     if (pairedDevices.size() > 0) { 
      Object[] devices = pairedDevices.toArray(); 
      BluetoothDevice device = (BluetoothDevice) devices[0]; 
      //ParcelUuid[] uuid = device.getUuids(); 
      Log.e("MAinActivity", "" + device); 
      //Log.e("MAinActivity", "" + uuid) 

      ConnectThread connect = new ConnectThread(device,MY_UUID_INSECURE); 
      connect.start(); 

     } 
    } 

    private class ConnectThread extends Thread { 
     private BluetoothSocket mmSocket; 

     public ConnectThread(BluetoothDevice device, UUID uuid) { 
      Log.d(TAG, "ConnectThread: started."); 
      mmDevice = device; 
      deviceUUID = uuid; 
     } 

     public void run(){ 
      BluetoothSocket tmp = null; 
      Log.i(TAG, "RUN mConnectThread "); 

      // Get a BluetoothSocket for a connection with the 
      // given BluetoothDevice 
      try { 
       Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: " 
         +MY_UUID_INSECURE); 
       tmp = mmDevice.createRfcommSocketToServiceRecord(MY_UUID_INSECURE); 
      } catch (IOException e) { 
       Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage()); 
      } 

      mmSocket = tmp; 

      // Make a connection to the BluetoothSocket 

      try { 
       // This is a blocking call and will only return on a 
       // successful connection or an exception 
       mmSocket.connect(); 

      } catch (IOException e) { 
       // Close the socket 
       try { 
        mmSocket.close(); 
        Log.d(TAG, "run: Closed Socket."); 
       } catch (IOException e1) { 
        Log.e(TAG, "mConnectThread: run: Unable to close connection in socket " + e1.getMessage()); 
       } 
       Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE); 
      } 

      //will talk about this in the 3rd video 
      connected(mmSocket); 
     } 
     public void cancel() { 
      try { 
       Log.d(TAG, "cancel: Closing Client Socket."); 
       mmSocket.close(); 
      } catch (IOException e) { 
       Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage()); 
      } 
     } 
    } 

    private void connected(BluetoothSocket mmSocket) { 
     Log.d(TAG, "connected: Starting."); 

     // Start the thread to manage the connection and perform transmissions 
     mConnectedThread = new ConnectedThread(mmSocket); 
     mConnectedThread.start(); 
    } 

    private class ConnectedThread extends Thread { 
     private final BluetoothSocket mmSocket; 
     private final InputStream mmInStream; 
     private final OutputStream mmOutStream; 

     public ConnectedThread(BluetoothSocket socket) { 
      Log.d(TAG, "ConnectedThread: Starting."); 

      mmSocket = socket; 
      InputStream tmpIn = null; 
      OutputStream tmpOut = null; 



      try { 
       tmpIn = mmSocket.getInputStream(); 
       tmpOut = mmSocket.getOutputStream(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      mmInStream = tmpIn; 
      mmOutStream = tmpOut; 
     } 

     public void run(){ 
      byte[] buffer = new byte[1024]; // buffer store for the stream 

      int bytes; // bytes returned from read() 

      // Keep listening to the InputStream until an exception occurs 
      while (true) { 
       // Read from the InputStream 
       try { 
        bytes = mmInStream.read(buffer); 
        final String incomingMessage = new String(buffer, 0, bytes); 
        Log.d(TAG, "InputStream: " + incomingMessage); 

        runOnUiThread(new Runnable() { 

         @Override 
         public void run() { 
          view_data.setText(incomingMessage); 
         } 
        }); 


       } catch (IOException e) { 
        Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage()); 
        break; 
       } 
      } 
     } 


     public void write(byte[] bytes) { 
      String text = new String(bytes, Charset.defaultCharset()); 
      Log.d(TAG, "write: Writing to outputstream: " + text); 
      try { 
       mmOutStream.write(bytes); 
      } catch (IOException e) { 
       Log.e(TAG, "write: Error writing to output stream. " + e.getMessage()); 
      } 
     } 

     /* Call this from the main activity to shutdown the connection */ 
     public void cancel() { 
      try { 
       mmSocket.close(); 
      } catch (IOException e) { } 
     } 
    } 


    public void SendMessage(View v) { 
     byte[] bytes = send_data.getText().toString().getBytes(Charset.defaultCharset()); 
     mConnectedThread.write(bytes); 
    } 


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


     send_data =(EditText) findViewById(R.id.editText); 
     view_data = (TextView) findViewById(R.id.textView); 

     if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) { 
      Intent enableBtIntent = new 
        Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
      startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); 
     } 


    } 

    public void Start_Server(View view) { 

     AcceptThread accept = new AcceptThread(); 
     accept.start(); 

    } 

    private class AcceptThread extends Thread { 

     // The local server socket 
     private final BluetoothServerSocket mmServerSocket; 

     public AcceptThread(){ 
      BluetoothServerSocket tmp = null ; 

      // Create a new listening server socket 
      try{ 
       tmp = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("appname", MY_UUID_INSECURE); 

       Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE); 
      }catch (IOException e){ 
       Log.e(TAG, "AcceptThread: IOException: " + e.getMessage()); 
      } 

      mmServerSocket = tmp; 
     } 

     public void run(){ 
      Log.d(TAG, "run: AcceptThread Running."); 

      BluetoothSocket socket = null; 

      try{ 
       // This is a blocking call and will only return on a 
       // successful connection or an exception 
       Log.d(TAG, "run: RFCOM server socket start....."); 

       socket = mmServerSocket.accept(); 

       Log.d(TAG, "run: RFCOM server socket accepted connection."); 

      }catch (IOException e){ 
       Log.e(TAG, "AcceptThread: IOException: " + e.getMessage()); 
      } 

      //talk about this is in the 3rd 
      if(socket != null){ 
       connected(socket); 
      } 

      Log.i(TAG, "END mAcceptThread "); 
     } 

     public void cancel() { 
      Log.d(TAG, "cancel: Canceling AcceptThread."); 
      try { 
       mmServerSocket.close(); 
      } catch (IOException e) { 
       Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage()); 
      } 
     } 

    } 

ACTIVITY_MAIN.XML

<?xml version="1.0" encoding="utf-8"?> 
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.hpi5.bluethoothshot.MainActivity" 
    tools:layout_editor_absoluteY="81dp" 
    tools:layout_editor_absoluteX="0dp"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Hello World!" 
     android:id="@+id/textView" 
     tools:layout_constraintTop_creator="1" 
     tools:layout_constraintRight_creator="1" 
     app:layout_constraintRight_toRightOf="parent" 
     android:layout_marginTop="58dp" 
     tools:layout_constraintLeft_creator="1" 
     app:layout_constraintLeft_toLeftOf="parent" 
     app:layout_constraintTop_toTopOf="parent" /> 

    <EditText 
     android:id="@+id/editText" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:ems="10" 
     android:inputType="textPersonName" 
     android:text="Name" 
     tools:layout_constraintTop_creator="1" 
     tools:layout_constraintRight_creator="1" 
     app:layout_constraintRight_toRightOf="parent" 
     android:layout_marginTop="153dp" 
     tools:layout_constraintLeft_creator="1" 
     app:layout_constraintLeft_toLeftOf="parent" 
     app:layout_constraintTop_toTopOf="parent" /> 

    <Button 
     android:id="@+id/button" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Button" 
     android:onClick="SendMessage" 
     tools:layout_constraintTop_creator="1" 
     tools:layout_constraintRight_creator="1" 
     app:layout_constraintRight_toRightOf="parent" 
     android:layout_marginTop="22dp" 
     app:layout_constraintTop_toBottomOf="@+id/editText" 
     tools:layout_constraintLeft_creator="1" 
     app:layout_constraintLeft_toLeftOf="parent" /> 

    <Button 
     android:id="@+id/button2" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Server" 
     android:onClick="Start_Server" 
     android:layout_marginEnd="53dp" 
     tools:layout_constraintRight_creator="1" 
     tools:layout_constraintBottom_creator="1" 
     app:layout_constraintBottom_toBottomOf="parent" 
     app:layout_constraintRight_toRightOf="parent" 
     android:layout_marginBottom="84dp" /> 

    <Button 
     android:id="@+id/button3" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="ConnectionREq" 
     android:onClick="pairDevice" 
     android:layout_marginStart="34dp" 
     tools:layout_constraintTop_creator="1" 
     tools:layout_constraintBottom_creator="1" 
     app:layout_constraintBottom_toBottomOf="@+id/button2" 
     tools:layout_constraintLeft_creator="1" 
     app:layout_constraintLeft_toLeftOf="parent" 
     app:layout_constraintTop_toTopOf="@+id/button2" 
     android:layout_marginLeft="30dp" 
     app:layout_constraintVertical_bias="0.0" /> 

</android.support.constraint.ConstraintLayout> 
+0

DANKE SO VIEL !!! Die App funktioniert perfekt, ich habe das Internet nach Tutorials durchforstet und deine Antwort war die einzige Sache, die für mich bisher funktioniert hat. Noch eine Frage, sollte dies auf einem Bluetooth-Gerät funktionieren (z. B. Apple zu Apple oder Android zu Apple) oder wird es nur von Android zu Android funktionieren. –

+0

Es ist * nicht * nativ möglich, eine Android-Anwendung unter iOS (die iPhone, iPad, iPod usw.) zu betreiben. – rayan

2

Ausnahmebeschreibung helfen defenitely, aber ich bin zu 99% sicher, dass das System verhindert, dass Sie von Socket-Verbindung Code innerhalb UI-Thread ausgeführt wird - so müssen Sie einen neuen Thread erstellen, bewegen Sie die Buchse Erstellungs- und Socket-Verbindungscode für diesen Thread und schließlich einen Rückruf, der Listener darauf hinweist, dass die Verbindung hergestellt wurde oder fehlgeschlagen ist.

Beachten Sie, dass Android die meisten Ihrer Versuche blockiert netzwerkbezogene zeitaufwändige Operationen innerhalb UI-Threads zu tun, weil es UI so sloooow ;-) macht

1

zwei große Probleme-

1) connect() ist ein blockierender Aufruf, Sie sollten diese Verbindungsprozedur immer in einem Thread ausführen, der vom Thread der Hauptaktivität (UI) getrennt ist. Sie tun dies auf dem Hauptthread.

Hinweis: Sie sollten immer cancelDiscovery() aufrufen, um sicherzustellen, dass die Gerät Geräteerkennung nicht durchführen, bevor Sie eine Verbindung herstellen() aufrufen. Wenn eine Erkennung durchgeführt wird, ist der Verbindungsversuch erheblich verlangsamt und es ist wahrscheinlicher, dass ein Fehler auftritt.

2) Wenn Sie den gleichen Code auf dem zweiten Gerät zu verwenden (so dass Sie Daten senden oder empfangen kann), dann sehe ich keinen Anruf zu accept(). accept() hört Verbindungsanforderungen ab. Auch hier handelt es sich bei accept() um einen blockierenden Aufruf. Er sollte nicht im Hauptaktivitäts-UI-Thread ausgeführt werden, damit Ihre Anwendung weiterhin auf andere Benutzerinteraktionen reagieren kann.

Vereinfachte Thread für die Serverkomponente, die eingehende Verbindungen akzeptiert:

private class AcceptThread extends Thread { 
    private final BluetoothServerSocket mmServerSocket; 

    public AcceptThread() { 
     // Use a temporary object that is later assigned to mmServerSocket 
     // because mmServerSocket is final. 
     BluetoothServerSocket tmp = null; 
     try { 
      // MY_UUID is the app's UUID string, also used by the client code. 
      tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); 
     } catch (IOException e) { 
      Log.e(TAG, "Socket's listen() method failed", e); 
     } 
     mmServerSocket = tmp; 
    } 

    public void run() { 
     BluetoothSocket socket = null; 
     // Keep listening until exception occurs or a socket is returned. 
     while (true) { 
      try { 
       socket = mmServerSocket.accept(); 
      } catch (IOException e) { 
       Log.e(TAG, "Socket's accept() method failed", e); 
       break; 
      } 

      if (socket != null) { 
       // A connection was accepted. Perform work associated with 
       // the connection in a separate thread. 
       manageMyConnectedSocket(socket); 
       mmServerSocket.close(); 
       break; 
      } 
     } 
    } 

    // Closes the connect socket and causes the thread to finish. 
    public void cancel() { 
     try { 
      mmServerSocket.close(); 
     } catch (IOException e) { 
      Log.e(TAG, "Could not close the connect socket", e); 
     } 
    } 
} 

Android Dokumentation - BLUETOOTH

+0

Danke für die ausführliche Antwort beginnen. Ich habe Ihre Vorschläge in mein Programm implementiert. Die Anwendung stürzt jedoch ab, wenn ich auf die Schaltfläche "Senden" klicke. Durch das Ausführen der Anwendung viele Male weiß ich, dass dies aufgrund der zwei Codezeilen ist Scanner s = neuer Scanner (inStream) .useDelimiter ("\\ A"); displayMessage.setText (s.hasNext()? S.next(): ""); Können Sie vorschlagen, warum oder vielleicht geben Sie einen Code, der den Text aus dem Ausgabestream nehmen würde, und setzen Sie es auf den Text in der TextView. –

Verwandte Themen