Android 平台包含蓝牙网络堆栈支持,此支持能让设备以无线方式与其他蓝牙设备交换数据。应用框架提供通过 Android Bluetooth API 访问蓝牙功能的权限。这些 API 允许应用以无线方式连接到其他蓝牙设备,从而实现点到点和多点无线功能。
Android 应用可通过 Bluetooth API 执行以下操作:
扫描其他蓝牙设备 查询本地蓝牙适配器的配对蓝牙设备 建立 RFCOMM 通道 通过服务发现连接到其他设备 与其他设备进行双向数据传输 管理多个连接
如要在应用中使用蓝牙功能,您必须声明两个权限。第一个是 BLUETOOTH。您需要此权限才能执行任何蓝牙通信,例如请求连接、接受连接和传输数据等。
第二个必须声明的权限是 ACCESS_FINE_LOCATION。您的应用需要此权限,因为蓝牙扫描可用于收集用户的位置信息。此类信息可能来自用户自己的设备,以及在商店和交通设施等位置使用的蓝牙信标。
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
1.获取
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { // Device doesn't support Bluetooth }
2.启用
if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
1.查询已配对的设备
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { // There are paired devices. Get the name and address of each paired device. for (BluetoothDevice device : pairedDevices) { String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } }
2.发现设备
@Override protected void onCreate(Bundle savedInstanceState) { ... // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); } // Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } } }; @Override protected void onDestroy() { super.onDestroy(); ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver); }
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 = bluetoothAdapter.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); } } }
class AcceptThread extends Thread { private BluetoothServerSocket mServerSocket; private BluetoothSocket mSocket; private InputStream btIs; private OutputStream btOs; private PrintWriter writer; private boolean canAccept; private boolean canRecv; public AcceptThread() { canAccept = true; canRecv = true; } @Override public void run() { try { //获取套接字 BluetoothServerSocket temp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("TEST", UUID.fromString(BT_UUID)); mServerSocket = temp; //监听连接请求 -- 作为测试,只允许连接一个设备 if (mServerSocket != null) { // while (canAccept) { mSocket = mServerSocket.accept();//阻塞等待客户端连接 sendHandlerMsg("有客户端连接"); // } } //获取输入输出流 btIs = mSocket.getInputStream(); btOs = mSocket.getOutputStream(); //通讯-接收消息 BufferedReader reader = new BufferedReader(new InputStreamReader(btIs, "UTF-8")); String content = null; while (canRecv) { content = reader.readLine(); sendHandlerMsg("收到消息:" + content); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (mSocket != null) { mSocket.close(); } // btIs.close();//两个输出流都依赖socket,关闭socket即可 // btOs.close(); } catch (IOException e) { e.printStackTrace(); sendHandlerMsg("错误:" + e.getMessage()); } } } private void sendHandlerMsg(String content) { Message msg = mHandler.obtainMessage(); msg.what = 1001; msg.obj = content; mHandler.sendMessage(msg); } public void write(String msg) { if (btOs != null) { try { if (writer == null) { writer = new PrintWriter(new OutputStreamWriter(btOs, "UTF-8"), true); } writer.println(msg); } catch (UnsupportedEncodingException e) { e.printStackTrace(); writer.close(); sendHandlerMsg("错误:" + e.getMessage()); } } } }
private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { // Use a temporary object that is later assigned to mmSocket // because mmSocket is final. BluetoothSocket tmp = null; mmDevice = device; try { // Get a BluetoothSocket to connect with the given BluetoothDevice. // MY_UUID is the app's UUID string, also used in the server code. tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's create() method failed", e); } mmSocket = tmp; } public void run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter.cancelDiscovery(); try { // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. mmSocket.connect(); } catch (IOException connectException) { // Unable to connect; close the socket and return. try { mmSocket.close(); } catch (IOException closeException) { Log.e(TAG, "Could not close the client socket", closeException); } return; } // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(mmSocket); } // Closes the client socket and causes the thread to finish. public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the client socket", e); } } }