1. 程式人生 > >[Android藍芽]三步實現藍芽聊天APP

[Android藍芽]三步實現藍芽聊天APP

先看下結構目錄

 

  1. ChatService.java —— 藍芽連線
  2. DeviceList.java   —— 裝置顯示
  3. MainActivity.java—— 主介面

1.許可權

要獲取藍芽功能,先在AndroidManifest.xml中申請許可權

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

 

2.介面

先從比較直觀的地方 彈 起吧。

                            

 

 

主聊天介面:Listview顯示對話,EditText編輯訊息,Button傳送訊息

裝置列表:2*ListView分別顯示已配對和搜尋到的裝置。Button按鈕開始查詢。

下面講講如何實現其功能

 

3.程式碼

挑幾個關鍵的地方,其它細節就不一一贅述了。

3.1 DeviceList —— 藍芽搜尋裝置功能

藍芽搜尋主要是要實現一個BroadcastReceiver 廣播接收者。
首先要註冊廣播,才能使用,新增藍芽裝置ACTION_FOUND等,如下
    private IntentFilter filter = new IntentFilter();
    …………………………………………………

    filter.addAction(BluetoothDevice.ACTION_FOUND);
    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    this.registerReceiver(mReceiver,filter);
其次就是這裡廣播接收
一旦開啟廣播搜尋,並找到裝置 接收到ACTION_FOUND的資訊,則可以從BluetoothDevice.EXTRA_DEVICE中得到搜尋到的裝置資訊,顯示到螢幕上。
如果是DISCOVERY_FINISHED,即結束搜尋。  下方程式碼為看起來方便,省略了一些不必要的。
private final 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); // 得到裝置資訊
            }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED
                    .equals(action)){ //結束搜尋了  }
            }
        }
    };

3.2 ChatService —— 藍芽連線功能

通過3個執行緒來實現。

 3.2.1 AcceptThread —— 被動等待連線的執行緒

使用BluetoothServerSocket accept函式,收到連線,則保持此連線傳給 ConnectedThread 
    // 建立監聽執行緒,準備接受新連線。使用阻塞方式,呼叫BluetoothServerSocket.accept()
    private class AcceptThread extends Thread{
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread(){
            BluetoothServerSocket tmp = null;
            try{
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);
            }catch (IOException e){}
            mmServerSocket = tmp;
        }


        public void run(){
        BluetoothSocket socket= null;

        while(mState != STATE_CONNECTED){
            try{
                socket = mmServerSocket.accept();
            }catch (IOException e) {
                break;
            }
            if(socket != null){
                connected(socket,socket.getRemoteDevice());
                try{
                    mmServerSocket.close();
                }catch (IOException e){}
            }
        }
    }

        public void cancel(){
            try{
                mmServerSocket.close();
            }catch (IOException e){}
        }
}

 3.2.1 ConnectThread —— 主動發起連線的執行緒

createRfcommSocketToServiceRecord 根據UUID 發起連線,連線成功則將連線傳入ConnectedThread
// 連線執行緒,專門用來對外發出連線對方藍芽的請求並進行處理
    // 建構函式裡通過BluetoothDevice.createRfcommSocketToServiceRecord(),
    // 從待連線的device產生BluetoothSocket,然後在run方法中connect
    // 成功後呼叫 BluetoothChatService的connnected()方法,定義cancel()在關閉執行緒時能關閉socket
    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
            mmDevice=device;
            BluetoothSocket tmp = null;
            // 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
            mAdapter.cancelDiscovery();
            try{
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();
            }catch (IOException e){
                connectionFailed();
                // Unable to connect; close the socket and get out
                try{
                    mmSocket.close();
                }catch (IOException e2){}

                //ChatService.this.start();
               return;
           }
            synchronized(ChatService.this){
                mConnectedThread = null;
           }
            connected(mmSocket,mmDevice);
        }

        public void cancel(){
           /* try{
                mmSocket.close();
            }catch (IOException e){}*/
        }
    }

 3.2.1 ConnectedThread —— 管理連線的執行緒

管理連線好的雙方,進行資料通訊。輸入輸出流,接收資料,傳送資料
 // 雙方藍芽連線後一直執行的執行緒。建構函式中設定輸入輸出流。
    // Run方法中使用阻塞模式的InputStream.read()迴圈讀取輸入流
    // 然後psot到UI執行緒中更新聊天資訊。也提供了write()將聊天訊息寫入輸出流傳輸至對方,
    // 傳輸成功後回寫入UI執行緒。最後cancel()關閉連線的socket

    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=mmSocket.getInputStream();
                tmpOut=mmSocket.getOutputStream();
            }catch (IOException e){}

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run(){
            byte[]buffer=new byte[1024];
            int bytes;
            while (true){
                try{
                    bytes = mmInStream.read(buffer);
                    mHandler.obtainMessage(MainActivity.MESSAGE_READ,bytes,-1,buffer).sendToTarget();
                }catch (IOException e){
                    connectionLost();
                    break;
                }
            }
        }

        public void write(byte[]buffer){
            try{
                mmOutStream.write(buffer);
            }catch (IOException e){
                Log.d("MainActivity","Send Fail");
            }
            mHandler.obtainMessage(MainActivity.MESSAGE_WRITE,buffer).sendToTarget();
        }

        public void cancel(){
            try{
                mmSocket.close();
            }catch (IOException e){}
        }
    }

3.3 MainActivity—— 主聊天介面

    主要是將雙方資訊顯示在上方,listview的操作,就不講了。


最後,原始碼地址奉上:https://github.com/Zweo/Bluetooth

 
 
 
 
 
 
 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

 
 
 
 
 
 
 
    1.