12/08/2018, 11:42

Tìm hiểu về Bluetooth API trên Android : Tạo một ứng dụng Bluetooth Scanner.

Bluetooth Đã trở thành một công nghệ rất phổ biến, đặc biệt là trên các thiết bị di động. Đó là một công nghệ để khám phá và chuyển dữ liệu giữa các thiết bị gần đó. Hầu hết các thiết bị di động hiện đại đều có tính năng Bluetooth . Nếu bạn muốn thực hiện một giao diện ứng dụng với một thiết bị ...

Bluetooth Đã trở thành một công nghệ rất phổ biến, đặc biệt là trên các thiết bị di động. Đó là một công nghệ để khám phá và chuyển dữ liệu giữa các thiết bị gần đó. Hầu hết các thiết bị di động hiện đại đều có tính năng Bluetooth . Nếu bạn muốn thực hiện một giao diện ứng dụng với một thiết bị Bluetooth được kích hoạt , ví dụ điện thoại với loa, tai nghe , hoặc các thiết bị điện tử có sẵn kết nối bluetooth ... Bạn phải biết làm thế nào để sử dụng Bluetooth API của Android.

Trong bài này, tôi sẽ hướng dẫn các bạn xây dựng một ứng dụng tương tự như ở trong Bluetooth Settings trong Cài đặt Android. Nó sẽ bao gồm các tính năng sau: - Bật kết nối Bluetooth. - Hiển thị danh sách các thiết bị đã kết nối,ghép đôi (paired). - Tìm và liệt kê danh sách các thiết bị có kết nối Bluetooth ở xung quanh.

Đây giao diện ứng dụng mà chúng ta sẽ làm cho ứng dụng Bluetooth này. Ở cuối bài mình sẽ có link download source của mình để mọi người tìm hiểu. Dưới đây là giao diện ứng dụng mà tôi làm và hướng dẫn các bạn. viblo-image-1.png

1. Bật BLUETOOTH

Từ ứng dụng chúng ta khởi tạo muốn bật tính năng Bluetooth chúng ta cần phải yêu cầu hệ thống cấp cho chúng ta các quyền (uses-permission). Tại file AndroidManifest chúng ta yêu cầu các quyền. Quyền BLUETOOTH cho phép ứng dụng kết nối, ngắt kết nối, và truyền dữ liệu với các thiết bị Bluetooth khác. Quyền BLUETOOTH_ADMIN cho phép ứng dụng phát hiện ra các thiết bị Bluetooth mới và thay đổi cài đặt Bluetooth của thiết bị.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="vn.framgia.congnt.bluetoothscanner" >
   <uses-permission android:name="android.permission.BLUETOOTH" />
   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

Sử dụng đối tượng BluetoothAdapter (adapter) để giao tiếp với Bluetooth.Ở đây mình tạo instantiate BluetoothAdapter tại class ListActivity

 BluetoothAdapter BTAdapter = BluetoothAdapter.getDefaultAdapter();

. Nếu BTAdapter bị null thì có nghĩa là Bluetooth không được hỗ trợ tại thiết bị này. Và ứng dụng sẽ không hoạt động trên thiết bị mà chúng ta đang chạy. Để xử lý việc này thì mình có một solution là hiển thị một AlertDialog để cảnh báo cho người dùng và thoát khỏi ứng dụng.

@Override
protected void onCreate(Bundle savedInstanceState) {
...
    BTAdapter = BluetoothAdapter.getDefaultAdapter();
    // Phone does not support Bluetooth so let the user know and exit.
    if (BTAdapter == null) {
        new AlertDialog.Builder(this)
                .setTitle("Not compatible")
                .setMessage("Your phone does not support Bluetooth")
                .setPositiveButton("Exit", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        System.exit(0);
                    }
                })
                .setIcon(android.R.drawable.ic_dialog_alert)
                .show();
    }
}

Nếu Bluetooth có sẵn trong thiết bị. Chúng ta cần kiểm tra xem nó đã được kích hoạt hay chưa. Nếu chưa được kích hoạt thì chúng ta có thể gửi một action có sẵn được cung cấp bởi Android SDK có tên BluetoothAdapter.ACTION_REQUEST_ENABLE. Khi gửi action này đến hệ thống với một requestCode REQUEST_BLUETOOTH là một số int để xác định yêu cầu kích hoạt, sau đó hệ thống sẽ hiển thị một dialog yêu cầu kích hoạt Bluetooth trên thiết bị.

public class ListActivity extends ActionBarActivity implements DeviceListFragment.OnFragmentInteractionListener  {
    public static int REQUEST_BLUETOOTH = 1;
    ...
    protected void onCreate(Bundle savedInstanceState) {
    ...
        if (!BTAdapter.isEnabled()) {
            Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBT, REQUEST_BLUETOOTH);
        }
    }
}

Screenshot_2015-09-24-13-31-02.png

2. Lấy danh sách các thiết bị đã ghép nối (Pair)

Ở bước này, mình lấy các thiết bị Bluetooth đã được ghép nối và hiển thị chúng trong một danh sách. Tại các trạng thái mà thiết bị Bluetooth hiển thị trong ứng dụng của mình sẽ là :

  • unknown
  • paired (đã ghép nối).
  • connected (đang kết nối).

Một điều quan trọng là chúng ta cần phải phân biệt giữa paired và connected của một thiết bị Bluetooth. Thiết bị đã paired là chỉ biết về sự tồn tại của nhau và sẵn sàng kết nối thông qua một mã code. Mã code được sử dụng để xác thực và dẫn đến một kết nối. 2 thiết bị sẽ tự động kết nối khi mã hóa được thành lập. Khi thiết bị đã connected sẽ chia sẻ một kênh RFCOMM cho phép việc gửi và nhận dữ liệu. Một thiết bị có thể có paired với nhiều thiết bị khác, nhưng trong một thời điểm chỉ connected với một thiết bị khác. Một thiết bị Bluetooth được đại diện bởi đối tương BluetoothDevice. Lấy một danh sách các thiết bị đã paired có thể lấy được bằng cách gọi hàm getBondedDevices(). Ở đây mình sẽ gọi hàm getBondedDevices() tại hàm onCreate() của class DeviceListFragment.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Log.d("DEVICELIST", "Super called for DeviceListFragment onCreate
");
    deviceItemList = new ArrayList<DeviceItem>();

    Set<BluetoothDevice> pairedDevices = bTAdapter.getBondedDevices();
}

Trong object BlueDevice có rất nhiều getter và setter thể hiện thuộc tính của BluetoothDevice.Ở đây tôi sử dụng hàm getName() để hiển thị tên của thiết bị và getAddress() hiển thị địa chỉ Mac. Địa chỉ Mac là địa chỉ độc nhất để xác định thiết bị. Khi chúng ta có một danh sách các thiết bị. Tôi sẽ tạo ra object DeviceItem tương ứng với BluetoothDevice. Sử dụng một List<DeviceItem> để hiển thị danh sách các thiết bị Bluetooth đã paired với thiết bị trong ứng dụng của tôi.

if (pairedDevices.size() > 0) {
    for (BluetoothDevice device : pairedDevices) {
        DeviceItem newDevice= new DeviceItem(device.getName(),device.getAddress(),"false");
        deviceItemList.add(newDevice);
    }
}

3 Tìm kiếm các thiết bị ở gần có kích hoạt Bluetooth

Ở bước này, Khi bấm nút Scan ứng dụng sẽ tìm kiếm các thiết bị xung quanh chưa kết nối với thiết bị. Các thiết bị có trạng thái unknow. Sau đó thêm chúng vào danh sách thiết bị paired. Code xử lý nằm tại class DeviceListFragment. Đầu tiên thì tôi sẽ tạo một BroadcastReceiver để nhận mỗi khi tìm thấy một thiết bị Bluetooth. Tại method onReceive() có trả về một đối số Intent. Chúng ta có thể kiểm tra action được broadcasting bằng hàm getAction() của Intent. Nếu action là BluetoothDevice.ACTION_FOUND. sau đó ứng dụng sẽ biết là tìm thấy một thiết bị Bluetooth. Khi nhận được action này, chúng ta tạo đối tượng DeviceItem dùng tên thiết bị và địa chỉ Mac. Chúng ta sẽ thêm object DeviceItem vào ArrayAdapter để hiển thị nó trên giao diện ứng dụng.

public class DeviceListFragment extends Fragment implements AbsListView.OnItemClickListener{
    ...
    private final BroadcastReceiver bReciever = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // Create a new device item
                DeviceItem newDevice = new DeviceItem(device.getName(), device.getAddress(), "false");
                // Add it to our adapter
                mAdapter.add(newDevice);
            }
        }
    };
}

Khi nút SCAN bật lên, chỉ cần register BroadcastReceiver và gọi hàm startDiscovery(). Khi nút SCAN tắt đi, chỉ cần unregister BroadcastReceiver và gọi hàm cancelDiscovery(). Việc này rất chiếm tài nguyên của máy. Nếu ứng dụng của bạn kết nối với các thiết bị Bluetooth khác, Bạn nên nhớ phải luôn tắt việc SCAN và sau đó kết nối. Mỗi khi SCAN bắt đầu thì mình sẽ clear ArrayAdapter. Vì khi bắt đầu SCAN chúng ta cũng chẳng muốn hiển thị các thiết bị có thể không còn có trong phạm vi quét của thiết bị.

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_deviceitem_list, container, false);
    ToggleButton scan = (ToggleButton) view.findViewById(R.id.scan);
    ...
    scan.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            if (isChecked) {
                mAdapter.clear();
                getActivity().registerReceiver(bReciever, filter);
                bTAdapter.startDiscovery();
            } else {
                getActivity().unregisterReceiver(bReciever);
                bTAdapter.cancelDiscovery();
            }
        }
    });
}

4. Kết nối đến thiết bị bluetooth

Kết nối Bluetooth hoạt động cũng giống với các kết nối khác (Socket,Http...). Phải có một máy chủ(server) và một máy khách(client) và giao tiếp thông qua RFCOMM sockets. Trên Android, RFCOMM sockets được đại diện bởi object BluetoothSocket. May mắn thay!!! Tất cả các kỹ thuật để phát triển một máy chủ(servers) đã được quản lý bởi AndroidSDK và có sẵn thông qua các Bluetooth API. Nên chúng ta không phải quan tâm rằng sẽ phải phát triển một Bluetooth Servers như thế nào             </div>
            
            <div class=

0