android -------- 藍牙通訊

前面介紹了藍牙的一些知識,今天來聊一聊藍牙之間的通訊,實現兩個設備通訊。java

我用兩部手機實現相互發消息的功能android

 

不管是BluetoothSocket,仍是BluetoothServerSocket,都須要一個UUID(全局惟一標識符,UniversallyUnique Identifier)git

 

藍牙的UUIDgithub

兩個藍牙設備進行鏈接時須要使用同一個UUID。但不少讀者可能發現,有不少型號的手機(多是非Android系統的手機)之間使用了不一樣的程序也能夠使用藍牙進行通信。從表面上看,它們之間幾乎不可能使用同一個UUID。數組

UUID的格式以下:網絡

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxsocket

UUID的格式被分紅5段,其中中間3段的字符數相同,都是4,第1段是8個字符,最後一段是12個字符。因此UUID其實是一個8-4-4-4-12的字符串。ide

實際上,UUID和TCP的端口同樣,也有一些默認的值。例如,將藍牙模擬成串口的服務就使用了一個標準的UUID:this

00001101-0000-1000-8000-00805F9B34FBspa

除此以外,還有不少標準的UUID,以下面就是兩個標準的UUID:

信息同步服務:00001104-0000-1000-8000-00805F9B34FB

文件傳輸服務:00001106-0000-1000-8000-00805F9B34FB

 

藍牙終端間數據傳輸

經過藍牙傳輸數據與Socket相似。在網絡中使用Socket和ServerSocket控制客戶端和服務端的數據讀寫。而藍牙通信也由客戶端和服務端Socket來完成。藍牙客戶端Socket是BluetoothSocket,藍牙服務端Socket是BluetoothServerSocket。這兩個類都在android.bluetooth包中。

不管是BluetoothSocket,仍是BluetoothServerSocket,都須要一個UUID(全局惟一標識符,Universally Unique Identifier),UUID至關於Socket的端口,而藍牙地址至關於Socket的IP。

模擬一個藍牙數據的傳輸:

private ListView lvDevices;  
      // 獲取到藍牙適配器  
      private BluetoothAdapter mBluetoothAdapter;  
      // ListView的字符串數組適配器  
      private List<String> bluetoothDevices = new ArrayList<String>();  
      private ArrayAdapter<String> arrayAdapter;  
      // UUID,藍牙創建連接須要的  
      private final UUID MY_UUID = UUID  
              .fromString("abcd1234-ab12-ab12-ab12-abcdef123456");//隨便定義一個  
      
      // 獲取到選中設備的客戶端串口,全局變量,不然鏈接在方法執行完就結束了  
      private BluetoothSocket clientSocket;  
      // 選中發送數據的藍牙設備,全局變量,不然鏈接在方法執行完就結束了  
      private BluetoothDevice device;  
      // 獲取到向設備寫的輸出流,全局變量,不然鏈接在方法執行完就結束了  
      private OutputStream os;//輸出流  
      
      
      // 爲其連接建立一個名稱  
      private final String NAME = "Bluetooth_Socket";  
      
      // 服務端利用線程不斷接受客戶端信息  
      private AcceptThread thread;

主要代碼:

@Override  
        protected void onCreate(@Nullable Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.demo2);  
            initView();  
        }  
      
        private void initView() {  
                 findViewById(R.id.btn1).setOnClickListener(this);  
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();  
      
            lvDevices = (ListView) findViewById(R.id.listview);  
            //獲取已經配對的藍牙設備  
            Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();  
            if (pairedDevices.size() > 0) {  
                for (BluetoothDevice device : pairedDevices) {  
                    bluetoothDevices.add(device.getName() + ":"+ device.getAddress());  
                }  
            }  
            arrayAdapter = new ArrayAdapter<String>(this,  
                    android.R.layout.simple_list_item_1, android.R.id.text1,bluetoothDevices);  
            lvDevices.setAdapter(arrayAdapter);  
            lvDevices.setOnItemClickListener(this);//Activity實現OnItemClickListener接口  
      
            //每搜索到一個設備就會發送一個該廣播  
            IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);  
            this.registerReceiver(receiver, filter);  
            //當所有搜索完後發送該廣播  
            filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);  
            this.registerReceiver(receiver, filter);  
      
      
            // 實例接收客戶端傳過來的數據線程  
            thread = new AcceptThread();  
            // 線程開始  
            thread.start();  
      
        }  
      
      
        @Override  
        public void onClick(View v) {  
            //若是當前在搜索,就先取消搜索  
            if (mBluetoothAdapter.isDiscovering()) {  
                mBluetoothAdapter.cancelDiscovery();  
            }  
            //開啓搜索  
            mBluetoothAdapter.startDiscovery();  
        }  
      
        @Override  
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {  
            String s = arrayAdapter.getItem(position);  
            String address = s.substring(s.indexOf(":") + 1).trim();//把地址解析出來  
            //主動鏈接藍牙服務端  
            try {  
                //判斷當前是否正在搜索  
                if (mBluetoothAdapter.isDiscovering()) {  
                    mBluetoothAdapter.cancelDiscovery();  
                }  
                try {  
                    if (device == null) {  
                        //得到遠程設備  
                        device = mBluetoothAdapter.getRemoteDevice(address);  
                    }  
                    if (clientSocket == null) {  
                        //建立客戶端藍牙Socket  
                        clientSocket = device.createRfcommSocketToServiceRecord(MY_UUID);  
                        //開始鏈接藍牙,若是沒有配對則彈出對話框提示咱們進行配對  
                        clientSocket.connect();  
                        //得到輸出流(客戶端指向服務端輸出文本)  
                        os = clientSocket.getOutputStream();  
                    }  
                } catch (Exception e) {  
                    e.printStackTrace();  
                    Toast.makeText(this, "失敗", Toast.LENGTH_LONG).show();  
                }  
                if (os != null) {  
                    //往服務端寫信息  
                    os.write("藍牙信息來了".getBytes("utf-8"));  
                    // 吐司一下,告訴用戶發送成功  
                    Toast.makeText(this, "發送信息成功,請查收", Toast.LENGTH_LONG).show();  
                }  
            } catch (Exception e) {  
                e.printStackTrace();  
                // 若是發生異常則告訴用戶發送失敗  
                Toast.makeText(this, "發送信息失敗", Toast.LENGTH_LONG).show();  
            }  
        }  
      
      
      
        /** 
         * 定義廣播接收器 
         */  
        private final BroadcastReceiver receiver = 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) {  
                        bluetoothDevices.add(device.getName() + ":" + device.getAddress());  
                        arrayAdapter.notifyDataSetChanged();//更新適配器  
                    }  
      
                } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {  
                    //已搜素完成  
                    Toast.makeText(Demo2Activity.this,"已搜索完成",Toast.LENGTH_LONG).show();  
                }  
            }  
        };  
      
        // 建立handler,由於咱們接收是採用線程來接收的,在線程中沒法操做UI,因此須要handler  
        Handler handler = new Handler() {  
            @Override  
            public void handleMessage(Message msg) {  
                // TODO Auto-generated method stub  
                super.handleMessage(msg);  
                // 經過msg傳遞過來的信息,吐司一下收到的信息  
                Log.i(NAME,msg.obj.toString());// 接收其餘設備傳過來的消息  
                Toast.makeText(Demo2Activity.this, (String) msg.obj, Toast.LENGTH_LONG).show();  
            }  
        };  
      
      
        // 服務端接收信息線程  
        private class AcceptThread extends Thread {  
            private BluetoothServerSocket serverSocket;// 服務端接口  
            private BluetoothSocket socket;// 獲取到客戶端的接口  
            private InputStream is;// 獲取到輸入流  
            private OutputStream os;// 獲取到輸出流  
      
            public AcceptThread() {  
                try {  
                    // 經過UUID監聽請求,而後獲取到對應的服務端接口  
                    serverSocket = mBluetoothAdapter  
                            .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);  
                } catch (Exception e) {  
                    // TODO: handle exception  
                }  
            }  
      
            public void run() {  
                try {  
                    // 接收其客戶端的接口  
                    socket = serverSocket.accept();  
                    // 獲取到輸入流  
                    is = socket.getInputStream();  
                    // 獲取到輸出流  
                    os = socket.getOutputStream();  
      
                    // 無線循環來接收數據  
                    while (true) {  
                        // 建立一個128字節的緩衝  
                        byte[] buffer = new byte[128];  
                        // 每次讀取128字節,並保存其讀取的角標  
                        int count = is.read(buffer);  
                        // 建立Message類,向handler發送數據  
                        Message msg = new Message();  
                        // 發送一個String的數據,讓他向上轉型爲obj類型  
                        msg.obj = new String(buffer, 0, count, "utf-8");  
                        // 發送數據  
                        handler.sendMessage(msg);  
                    }  
                } catch (Exception e) {  
                    // TODO: handle exception  
                    e.printStackTrace();  
                }  
      
            }  
        }

分別在兩個手機上安裝APP,點擊掃描設備,而後點擊鏈接的藍牙名稱發送消息

下圖是我發送給另外一個設備,而後另外一個收到消息在發送消息過來。

效果圖:

    

源碼下載:https://github.com/DickyQie/android-bluetooth

相關文章
相關標籤/搜索