如何通过蓝牙android工作室发送/接收消息

我正在尝试创建一个应用程序,允许从一个Android手机发送到另一个Android手机。 下面提供了此代码。 但是,它不起作用,因为我继续从pairDevice()部分下的try catch代码中获取exception。 有谁知道为什么我会得到这个?

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 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(); } 

}

我对您的应用进行了一些更改: –

首先,我将负责创建蓝牙连接的代码转移到ConnectThread

2)添加了AcceptThread负责监听传入连接, ConnectedThread维护BTConnection,发送数据和通过输入/输出流接收输入数据。 3)创建2个按钮以启动ConnectThread和AcceptThread。

注意:确保两个设备都已配对,并且您尝试连接的设备位于列表顶部(或者只是从两个设备中删除所有配对设备,并仅配对要连接的设备)。 此外,您必须在ConnectThread之前启动AcceptThread

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 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中

         

exception描述肯定有帮助,但我99%确定系统阻止你在UI线程内执行套接字连接代码 – 所以你需要创建一个新线程,将你的套接字创建和套接字连接代码移动到该线程,最后,创建一个回调,它将指示侦听器已执行连接或失败。

请注意,android会阻止你在UI线程内进行与网络相关的耗时操作的大部分尝试,因为它使得UI如此懒散;-)

两个主要问题 –

1) connect()是一个阻塞调用,你应该总是在一个独立于主活动(UI)线程的线程中执行这个连接过程。 你是在主线程上这样做的。

注意:在调用connect()之前,应始终调用cancelDiscovery()以确保设备未执行设备发现。 如果发现正在进行中,则连接尝试速度会显着降低,并且更有可能失败。

2)如果您在第二台设备上使用相同的代码(以便您可以发送或接收数据),那么我看不到任何对accept()调用。 accept()侦听连接请求。 同样, accept()调用是一个阻塞调用,它不应该在主活动UI线程中执行,这样您的应用程序仍然可以响应其他用户交互。

接受传入连接的服务器组件的简化线程:

 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文档 – BLUETOOTH