Android藍牙操作筆記,android藍牙筆記
藍牙是一種支持設備短距離傳輸數據的無線技術。android在2.0以後提供了這方面的支持。
從查找藍牙設備到能夠相互通信要經過幾個基本步驟(本機做為服務器):
1.設置權限
在manifest中配置
- <uses-permission android:name="android.permission.BLUETOOTH"/>
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
2.啟動藍牙
首先要查看本機是否支持藍牙,獲取BluetoothAdapter藍牙適配器對象
- BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if(mBluetoothAdapter == null){
- //表明此手機不支持藍牙
- return;
- }
- if(!mBluetoothAdapter.isEnabled()){ //藍牙未開啟,則開啟藍牙
- Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
- }
- //......
- public void onActivityResult(int requestCode, int resultCode, Intent data){
- if(requestCode == REQUEST_ENABLE_BT){
- if(requestCode == RESULT_OK){
- //藍牙已經開啟
- }
- }
- }
3。發現藍牙設備
這裡可以細分為幾個方面
(1)使本機藍牙處於可見(即處於易被搜索到狀態),便於其他設備發現本機藍牙
- //使本機藍牙在300秒內可被搜索
- private void ensureDiscoverable() {
- if (mBluetoothAdapter.getScanMode() !=
- BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
- Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
- discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
- startActivity(discoverableIntent);
- }
- }
(2)查找已經配對的藍牙設備,即以前已經配對過的設備
- Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
- if (pairedDevices.size() > 0) {
- findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
- for (BluetoothDevice device : pairedDevices) {
- //device.getName() +" "+ device.getAddress());
- }
- } else {
- mPairedDevicesArrayAdapter.add("沒有找到已匹對的設備");
- }
(3)通過mBluetoothAdapter.startDiscovery();搜索設備,要獲得此搜索的結果需要注冊
一個BroadcastReceiver來獲取。先注冊再獲取信息,然後處理
- //注冊,當一個設備被發現時調用onReceive
- IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
- this.registerReceiver(mReceiver, filter);
-
- //當搜索結束後調用onReceive
- filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- this.registerReceiver(mReceiver, filter);
- //.......
- private BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if(BluetoothDevice.ACTION_FOUND.equals(action)){
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- // 已經配對的則跳過
- if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
- mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); //保存設備地址與名字
- }
- }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //搜索結束
- if (mNewDevicesArrayAdapter.getCount() == 0) {
- mNewDevicesArrayAdapter.add("沒有搜索到設備");
- }
- }
-
- }
- };
4.建立連接
查找到設備 後,則需要建立本機與其他設備之間的連接。
一般用本機搜索其他藍牙設備時,本機可以作為一個服務端,接收其他設備的連接。
啟動一個服務器端的線程,死循環等待客戶端的連接,這與ServerSocket極為相似。
這個線程在准備連接之前啟動
- //UUID可以看做一個端口號
- private static final UUID MY_UUID =
- UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
- //像一個服務器一樣時刻監聽是否有連接建立
- private class AcceptThread extends Thread{
- private BluetoothServerSocket serverSocket;
-
- public AcceptThread(boolean secure){
- BluetoothServerSocket temp = null;
- try {
- temp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(
- NAME_INSECURE, MY_UUID);
- } catch (IOException e) {
- Log.e("app", "listen() failed", e);
- }
- serverSocket = temp;
- }
-
- public void run(){
- BluetoothSocket socket=null;
- while(true){
- try {
- socket = serverSocket.accept();
- } catch (IOException e) {
- Log.e("app", "accept() failed", e);
- break;
- }
- }
- if(socket!=null){
- //此時可以新建一個數據交換線程,把此socket傳進去
- }
- }
-
- //取消監聽
- public void cancel(){
- try {
- serverSocket.close();
- } catch (IOException e) {
- Log.e("app", "Socket Type" + socketType + "close() of server failed", e);
- }
- }
-
- }
搜索到設備後可以獲取設備的地址,通過此地址獲取一個BluetoothDeviced對象,可以看做客戶端,通過此對象device.createRfcommSocketToServiceRecord(MY_UUID);同一個UUID可與服務器建立連接獲取另一個socket對象,由此服務端與客戶端各有一個socket對象,此時
他們可以互相交換數據了。
創立客戶端socket可建立線程
- //另一個設備去連接本機,相當於客戶端
- private class ConnectThread extends Thread{
- private BluetoothSocket socket;
- private BluetoothDevice device;
- public ConnectThread(BluetoothDevice device,boolean secure){
- this.device = device;
- BluetoothSocket tmp = null;
- try {
- tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
- } catch (IOException e) {
- Log.e("app", "create() failed", e);
- }
- }
-
- public void run(){
- mBluetoothAdapter.cancelDiscovery(); //取消設備查找
- try {
- socket.connect();
- } catch (IOException e) {
- try {
- socket.close();
- } catch (IOException e1) {
- Log.e("app", "unable to close() "+
- " socket during connection failure", e1);
- }
- connetionFailed(); //連接失敗
- return;
- }
- //此時可以新建一個數據交換線程,把此socket傳進去
- }
-
- public void cancel() {
- try {
- socket.close();
- } catch (IOException e) {
- Log.e("app", "close() of connect socket failed", e);
- }
- }
- }
5.建立數據通信線程,進行讀取數據
- //建立連接後,進行數據通信的線程
- private class ConnectedThread extends Thread{
- private BluetoothSocket socket;
- private InputStream inStream;
- private OutputStream outStream;
-
- public ConnectedThread(BluetoothSocket socket){
-
- this.socket = socket;
- try {
- //獲得輸入輸出流
- inStream = socket.getInputStream();
- outStream = socket.getOutputStream();
- } catch (IOException e) {
- Log.e("app", "temp sockets not created", e);
- }
- }
-
- public void run(){
- byte[] buff = new byte[1024];
- int len=0;
- //讀數據需不斷監聽,寫不需要
- while(true){
- try {
- len = inStream.read(buff);
- //把讀取到的數據發送給UI進行顯示
- Message msg = handler.obtainMessage(BluetoothChat.MESSAGE_READ,
- len, -1, buff);
- msg.sendToTarget();
- } catch (IOException e) {
- Log.e("app", "disconnected", e);
- connectionLost(); //失去連接
- start(); //重新啟動服務器
- break;
- }
- }
- }
-
-
- public void write(byte[] buffer) {
- try {
- outStream.write(buffer);
-
- // Share the sent message back to the UI Activity
- handler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
- .sendToTarget();
- } catch (IOException e) {
- Log.e("app", "Exception during write", e);
- }
- }
-
- public void cancel() {
- try {
- socket.close();
- } catch (IOException e) {
- Log.e("app", "close() of connect socket failed", e);
- }
- }
- }