2011年11月14日 星期一

[Android] Bluetooth - (1)

Using the Bluetooth APIs, an Android application can perform the following:
  • Scan for other Bluetooth devices
  • Query the local Bluetooth adapter for paired Bluetooth devices
  • Establish RFCOMM channels
  • Connect to other devices through service discovery
  • Transfer data to and from other devices
  • Manage multiple connections

Four steps to communicate using Bluetooth
  1. Setting up Bluetooth
  2. Finding devices that are either paired or available in the local area
  3. Connecting devices
  4. Transferring data between devices.

Permissions
  • BLUETOOTH
    • To perform any Bluetooth communication
    • 讓程式有權限連接裝置、傳輸資料。
      • ex: requesting a connection, accepting a connection, and transferring data.
  • BLUETOOTH_ADMIN
    • Initiate device discovery or manipulate Bluetooth settings.
    • 讓程式有權限搜尋裝置及設定藍芽。
  • Note
    • If you use BLUETOOTH_ADMIN permission, then must also have the BLUETOOTH permission.


Check Bluetooth Function

在使用 Bluetooth 前必須先確認裝置有支援並且已開啟。判斷的方式如下:

1. Get the BluetoothAdapter
  • This returns a BluetoothAdapter that represents the device's own Bluetooth adapter (the Bluetooth radio).
    • There's one Bluetooth adapter for the entire system, and your application can interact with it using this object.
  • If getDefaultAdapter() returns null, then the device does not support Bluetooth.
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
    // Device does not support Bluetooth
}


2. Enable Bluetooth
  • Call isEnabled() to check whether Bluetooth is currently enable.
    • If this method returns false, then Bluetooth is disabled.
  • To request that Bluetooth be enabled, call startActivityForResult() with the ACTION_REQUEST_ENABLE action Intent.
    • This will issue a request to enable Bluetooth through the system settings (without stopping your application).
    • enabling Bluetooth succeeds ? return RESULT_OK : RESULT_CANCELED.

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


3.  Listen for the ACTION_STATE_CHANGED broadcast Intent

此步驟可略,但接收此 intent,有助於在程式執行中了解 Bluetooth 的狀態。
  • The system will broadcast whenever the Bluetooth state has changed
  • Contains the extra fields 
    • EXTRA_STATE: new Bluetooth status
    • EXTRA_PREVIOUS_STATE: old Bluetooth status
    • Possible values for these extra fields are STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, and STATE_OFF.


Querying paired devices

在 scan devices 前,可以使用 getBondedDevices() 先找尋已經配對過的資訊。
Set 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());
    }
}

All that's needed from the BluetoothDevice object in order to initiate a connection is the MAC address.



Finding Devices (concept)

找尋裝置 -> 配對 -> 連線

  • Using the BluetoothAdapter
    • Can find remote Bluetooth devices either through device discovery or by querying the list of paired (bonded) devices.
  • Device discovery
    • A scanning procedure that searches the local area for Bluetooth enabled devices and then requesting some information about each one.
    • This is sometimes referred to as "discovering," "inquiring" or "scanning".
  • A Bluetooth device within the local area will respond to a discovery request only if it is currently enabled to be discoverable. 手機必須是已設定為 discoverable 才有可能被找到
    • If a device is discoverable, it will respond to the discovery request by sharing some information.
      • ex: the device name, class, and its unique MAC address
    • Using this information, the device performing discovery can then choose to initiate a connection to the discovered device.
  • Once a connection is made with a remote device for the first time
    • A pairing request is automatically presented to the user.
  • When a device is paired
    • The basic information about that device is saved and can be read using the Bluetooth APIs. 
    • Using the known MAC address for a remote device, a connection can be initiated with it at any time without performing discovery (assuming the device is within range).
Note: Being paired and being connected is the different.
  • To be paired
    • Two devices are aware of each other's existence
    • Have a shared link-key that can be used for authentication
    • Be capable of establishing an encrypted connection with each other.
  • To be connected
    • The devices currently share an RFCOMM channel.
    • Be able to transmit data with each other.
  • The current Android Bluetooth API's require devices to be paired before an RFCOMM connection can be established. (Pairing is automatically performed when you initiate an encrypted connection with the Bluetooth APIs.)


Discovering devices
  • Using startDiscovery() to start discovering devices.
    • The process is asynchronous and the method will immediately return with a boolean indicating whether discovery has successfully started.
  • The discovery process usually involves an inquiry scan of about 12 seconds, followed by a page scan of each found device to retrieve its Bluetooth name.
  • Your application must register a BroadcastReceiver for the ACTION_FOUND Intent in order to receive information about each device discovered.
    • This Intent carries the extra fields
      • EXTRA_DEVICE: BluetoothDevice
      • EXTRA_CLASS: BluetoothClass
// 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

NotePerforming device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources.
  • Once you have found a device to connect, be certain that you always stop discovery with cancelDiscovery() before attempting a connection.
  • Also, if you already hold a connection with a device, then performing discovery can significantly reduce the bandwidth available for the connection, so you should not perform discovery while connected.


Enabling discoverability

必須要將裝置設為 discoverable 才能被搜尋到。
  • To make the local device discoverable to other devices
    • startActivityForResult(Intent, int) with the ACTION_REQUEST_DISCOVERABLE action Intent.
    • This will issue a request to enable discoverable mode through the system settings (without stopping your application).
  • By default, the device will become discoverable for 120 seconds
    • You can define a different duration by adding the EXTRA_DISCOVERABLE_DURATION Intent extra.
      • The maximum duration an app can set is 3600 seconds
      • A value of 0 means the device is always discoverable.
      • Any value below 0 or above 3600 is automatically set to 120 secs
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);

ACTION_SCAN_MODE_CHANGED Intent
  • Notified when the discoverable mode has changed.
  • This will contain the extra fields
    • EXTRA_SCAN_MODE: new scan mode
    • EXTRA_PREVIOUS_SCAN_MODE: old scan mode
    • Possible values for each are
      • SCAN_MODE_CONNECTABLE_DISCOVERABLE: discoverable mode
      • SCAN_MODE_CONNECTABLE: not in discoverable mode but still able to receive connections
      • SCAN_MODE_NONE: not in discoverable mode and unable to receive connections
Note
  • You do not need to enable device discoverability if you will be initiating the connection to a remote device.
  • Enabling discoverability is only necessary when you want your application to host a server socket that will accept incoming connections, because the remote devices must be able to discover the device before it can initiate the connection.


By the way
  • Bluetooth Profile (藍牙規範)
    • 目的是要確保 Bluetooth 設備間的互通性(interoperability)。
      • The way a device uses Bluetooth technology depends on its profile capabilities. 
      • The profiles provide standards which manufacturers follow to allow devices to use Bluetooth in the intended manner.
    • 由藍牙技術聯盟所定義。
    • 但 Bluetooth 產品無須實現所有的 Bluetooth 規範 Profile。
    • Bluetooth 規格 1.1 定義 13 個 Profiles。
    • At a maximum, each profile specification contains information on the following topics:
      • Dependencies on other formats
      • Suggested user interface formats
      • Specific parts of the Bluetooth protocol stack used by the profile.
        • To perform its task, each profile uses particular options and parameters at each layer of the stack. This may include an outline of the required service record, if appropriate.
  • Advance Audio Distribution Profile (A2DP, 藍牙立體聲音訊傳輸規範)
    • 規定了使用藍牙非同步傳輸信道方式,傳輸高質量音樂檔案數據的協議堆棧軟體和使用方法,基於該協議就能通過以藍牙方式傳輸高品質的立體聲音樂。
    • 分為 1.1 版和 1.2 版,只要連線雙方支援 A2DP 協議都能以 16 bits,44.1 kHz的質量傳輸聲音訊號。
    • 假如有一方沒有支援 A2DP 的話,只能以 8 bits,8 kHz的質量的 Handsfree Profile 傳輸模式,聲音質量會大打折扣



* Reference
- Bluetooth | Android Developers **
- package android.bluetooth
- Android應用程式學習筆記 - Bluetooth
- 藍牙規範 - 维基百科,自由的百科全书
- Bluetooth profile - Wikipedia, the free encyclopedia
- Android 上的 Bluetooth | 憑虛御風

沒有留言:

張貼留言