2025-05-17

 

基礎:

 

 這篇文檔描述瞭怎麼使用Android Bluetooth APIs完成數據交換的四個主要的任務:創建Bluetooth,找到本地區域可用的藍牙設備或匹配的藍牙設備,連接設備,傳輸數據。

 

所有的Bluetooth APIs都在android.bluetooth包下。下面是創建藍牙連接需要實現的類和接口:

 

BluetoothAdapter:

 

       表示本地的藍牙適配器。BluetoothAdapter是所有藍牙交換的接入點。使用它,你可以發現其他的藍牙設備,查找一些匹配的設備,用MAC地址來實例化一個BluetoothDevice。創建一個BluetoothServerSocket來監聽其他設備,進而和它們進行通信。

 

BluetoothDevice:

 

       表示遠程的藍牙設備。用它通過BluetoothSocket來請求與遠程的設備進行連接。後者查詢設備的基本信息,例如名稱,地址,類或者結合的狀態。

 

BluetoothSocket:

 

      表示一個Bluetooth socket接口(與TCP socket相似)。它是一個連接點,運行設備通過InputStream和OutputStream的形式來交換數據。

 

BluetoothServiceSocket:

 

     表示一個打開服務socket,用來監聽收到的請求(與TCP server socket相似)。為瞭連接設備,一個設備必須打開服務socket。當一個遠程的設備請求連接的時候,當連接被接收的時候,BluetoothServiceSocket返回一個BluetoothSocket。

 

BluetoothClass:

 

    描述藍牙設備的一般特征和性能。這是個隻讀的一系列屬性。定義瞭主要和最小的設備類和服務。然而,它描述的設備屬性和和服務是不完全可靠的,但是,在表示設備類型時,它是有用的。

 

BluetoothProfile:

 

     一個代表藍牙屬性的接口。指基於無線藍牙交流的無線接口規則。

 

BluetoothHeadset:

 

    提供在手機手機上使用藍牙耳機的支持。

 

BluetoothA2dp:

 

     定義什麼樣的數據可以在藍牙之間傳遞。

 

BluetoothProfiles.ServiceListener:

 

    當藍牙設備連接或者斷開時,用它來通知BluetoothProfiles IPC客戶端。它是一個接口。

 

藍牙權限:

 

     為瞭使用藍牙,你必須在你的應用程序中聲明權限。

 

<manifest … >

  <uses-permission android:name="android.permission.BLUETOOTH" />

  …

</manifest>

 

兩種權限:BLUETOOTH和BLUETOOTH ADMIN.

 

當使用BLUETOOTH ADMIN時,一定要聲明BLUETOOTH。

 

創建Bluetooth:

 

  1.得到BluetoothAdaper。

 

   BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

 if (mBluetoothAdapter == null) {

    // Device does not support Bluetooth

}

 

如何不為null,說明本機可用藍牙設備。

 

   2.使用Bluetooth。

 

    if (mBluetoothAdapter.isEnabled()) {

    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

}

 

查看匹配的設備:

 

 Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();

// If there are paired devices

if (pairedDevices.size() > 0) {

    // Loop through paired devices

    for (BluetoothDevice device : pairedDevices) {

        // Add the name and address to an array adapter to show in a ListView

        mArrayAdapter.add(device.getName() + "\n" + device.getAddress());

    }

}

 

發現設備:

 

// Create a BroadcastReceiver for ACTION_FOUND

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {

    public void onReceive(Context context, Intent intent) {

        String action = intent.getAction();

        // When discovery finds a device

        if (BluetoothDevice.ACTION_FOUND.equals(action)) {

            // Get the BluetoothDevice object from the Intent

            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            // Add the name and address to an array adapter to show in a ListView

            mArrayAdapter.add(device.getName() + "\n" + device.getAddress());

        }

    }

};

// Register the BroadcastReceiver

IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);

registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy

 

連接設備:

 

做為一個服務者:

 

    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) { }

        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) {

                break;

            }

            // If a connection was accepted

            if (socket != null) {

                // Do work to manage the connection (in a separate thread)

                manageConnectedSocket(socket);

                mmServerSocket.close();

                break;

            }

        }

    }

 

    /** Will cancel the listening socket, and cause the thread to finish */

    public void cancel() {

        try {

            mmServerSocket.close();

        } catch (IOException e) { }

    }

}

 

做為客戶端:

 

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;

 

        // Get a BluetoothSocket to connect with the given BluetoothDevice

        try {

            // MY_UUID is the app's UUID string, also used by the server code

            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);

        } catch (IOException e) { }

        mmSocket = tmp;

    }

 

    public void run() {

        // Cancel discovery because it will slow down the connection

        mBluetoothAdapter.cancelDiscovery();

 

        try {

            // Connect the device through the socket. This will block

            // until it succeeds or throws an exception

            mmSocket.connect();

        } catch (IOException connectException) {

            // Unable to connect; close the socket and get out

            try {

                mmSocket.close();

            } catch (IOException closeException) { }

            return;

        }

 

        // Do work to manage the connection (in a separate thread)

        manageConnectedSocket(mmSocket);

    }

 

    /** Will cancel an in-progress connection, and close the socket */

    public void cancel() {

        try {

            mmSocket.close();

        } catch (IOException e) { }

    }

}

 

管理連接:

 

private class ConnectedThread extends Thread {

    private final BluetoothSocket mmSocket;

    private final InputStream mmInStream;

    private final OutputStream mmOutStream;

 

    public ConnectedThread(BluetoothSocket socket) {

        mmSocket = socket;

        InputStream tmpIn = null;

        OutputStream tmpOut = null;

 

        // Get the input and output streams, using temp objects because

        // member streams are final

        try {

            tmpIn = socket.getInputStream();

            tmpOut = socket.getOutputStream();

        } catch (IOException e) { }

 

        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) {

            try {

                // Read from the InputStream

                bytes = mmInStream.read(buffer);

                // Send the obtained bytes to the UI Activity

                mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)

                        .sendToTarget();

            } catch (IOException e) {

                break;

            }

        }

    }

 

    /* Call this from the main Activity to send data to the remote device */

    public void write(byte[] bytes) {

        try {

            mmOutStream.write(bytes);

        } catch (IOException e) { }

    }

 

    /* Call this from the main Activity to shutdown the connection */

    public void cancel() {

        try {

            mmSocket.close();

        } catch (IOException e) { }

    }

}

摘自 燕龍安的專欄

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *