1. 程式人生 > >android 藍芽模組Bluetooth 使用 十六進位制資料傳送

android 藍芽模組Bluetooth 使用 十六進位制資料傳送

一個藍芽模組看起來很小,弄起來還是有點複雜的,從網上找了一個示例程式碼,http://blog.csdn.net/vnanyesheshou/article/details/51554852但是不能直接用,需要自己進行閱讀理解和修改後才能使用。

先貼一張自制的uml圖:


從圖中不難看出涉及的類還是挺多的,大致上分為裝置初始化、建立連線、傳送訊息三個大致的步驟吧。網上的程式碼封裝成了一個BluetoothChatUtil實用的類,負責建立通訊和傳送訊息,然後通過訊息的方式讓介面顯示獲取到的資料。BroadcastReceiver負責接收藍芽掃描時獲取到的裝置,由於專案中的目標藍芽是已經繫結的,所以直接使用BluetoothAdapter類的getBondedDevices()函式來獲取已經繫結的藍芽裝置,然後通過設定名稱或者地址來進行連線。

為現有專案新增藍芽模組的步驟大致如下(簡單地從程式碼出發):

(1)增加成員變數:

//獲取訊息的Handler

Handler mHandler;

//藍芽模組

//待連線的藍芽名稱

         publicstatic final String BLUETOOTH_NAME = "XXXX";

         //連線 msg

         publicstatic final String OPEN_BLUE_HEX_STRING = "00 00 00 00 ";

         //關閉 msg

         publicstatic final String CLOSE_BLUE_HEX_STRING = "FF FF FF FF";

         //待連線的藍芽地址

         privateString mBluetoothAddress = "XX:XX:XX:XX:XX:XX";

    boolean hasregister = false;

    private ProgressDialog mProgressDialog;

    //藍芽通訊模組

         privateBluetoothChatUtil mBlthChatUtil;

         //當前activity的控制代碼

         privateContext mContext;

         privateint REQUEST_ENABLE_BT = 1;

(2)onCreate中初始化:

mContext = this;

         mProgressDialog= new ProgressDialog(this);

         在handleMessage(Message msg)中捕獲幾個訊息:

        //連線成功

 caseBluetoothChatUtil.STATE_CONNECTED:

                 if(mProgressDialog.isShowing()){

                        mProgressDialog.dismiss();

                 }

                 StringdeviceName = msg.getData().getString(BluetoothChatUtil.DEVICE_NAME);

                 //mBtnBluetoothConnect.setText("已成功連線到裝置"+ deviceName);

                 Toast.makeText(getApplicationContext(),"連線成功:"+deviceName, Toast.LENGTH_SHORT).show();

 //連線後就傳送你需要傳送的訊息

                 sendBluetoothMessage(OPEN_BLUE_HEX_STRING);

                  break;      

//連線失敗                            

         caseBluetoothChatUtil.STATAE_CONNECT_FAILURE:

                 if(mProgressDialog.isShowing()){

                  mProgressDialog.dismiss();

                  }

        Toast.makeText(getApplicationContext(),"連線失敗", Toast.LENGTH_SHORT).show();

          break;

//斷開連線

      caseBluetoothChatUtil.MESSAGE_DISCONNECTED:

                 if(mProgressDialog.isShowing()){

                        mProgressDialog.dismiss();

                 }

          //mBtnBluetoothConnect.setText("與裝置斷開連線");

                break;

//收到訊息

        caseBluetoothChatUtil.MESSAGE_READ:

                byte[]buf = msg.getData().getByteArray(BluetoothChatUtil.READ_MSG);

                Stringstr = new String(buf,0,buf.length);

               Toast.makeText(getApplicationContext(),"讀成功" + str, Toast.LENGTH_SHORT).show();

                break;

         例項化通訊模組,並連線藍芽:

//藍芽模組

                   mBlthChatUtil= BluetoothChatUtil.getInstance(mContext);

                   mBlthChatUtil.registerHandler(mHandler);

                   initBluetooth();

//根據自己的需求來選擇需不需要掃描裝置

        //mBluetoothAdapter.startDiscovery();

//連線裝置

        connect();

        if (mBlthChatUtil.getState() == BluetoothChatUtil.STATE_NONE) {

                            //啟動藍芽聊天服務

                            mBlthChatUtil.start();

                  }

               藍芽初始化函式initBluetooth()和connect函式:

private void initBluetooth() {

                      mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();

                     if(mBluetoothAdapter == null) {//裝置不支援藍芽

                            Toast.makeText(getApplicationContext(),"裝置不支援藍芽", Toast.LENGTH_LONG).show();

                            finish();

                            return;

                   }

                   //判斷藍芽是否開啟

                   if(!mBluetoothAdapter.isEnabled()) {//藍芽未開啟

                            IntentenableIntent = new Intent(

                                               BluetoothAdapter.ACTION_REQUEST_ENABLE);

                            startActivityForResult(enableIntent,REQUEST_ENABLE_BT);

                            //開啟藍芽

                            mBluetoothAdapter.enable();

                   }                          

                   //

                   IntentFilterfilter = new IntentFilter();

                   filter.addAction(BluetoothDevice.ACTION_FOUND);

                   filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

                   //registerReceiver(mBluetoothReceiver,filter);

                   //hasregister= true;

                   if(mBluetoothAdapter.isEnabled()) {

                            intnMode = mBluetoothAdapter.getScanMode();

                            if(nMode== BluetoothAdapter.SCAN_MODE_CONNECTABLE){

                                     Log.e(TAG_BLUE,"getScanMode= SCAN_MODE_CONNECTABLE");

                            }

                            if(nMode== BluetoothAdapter.SCAN_MODE_NONE){

                                     Log.e(TAG_BLUE,"getScanMode= SCAN_MODE_NONE");

                            }

                            if(nMode== BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){

                                     Log.e(TAG_BLUE,"getScanMode= SCAN_MODE_CONNECTABLE_DISCOVERABLE");

                            }

                         //if(nMode == BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {

                         //     IntentdiscoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);

                         /       discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);

                         //       startActivity(discoverableIntent);

                         //}

                   }

                   //本身藍芽的名稱和地址

                   Stringname = mBluetoothAdapter.getName();

                   Stringaddress = mBluetoothAdapter.getAddress();

                   Log.d(TAG_BLUE,"bluetoothname ="+name+" address ="+address);

         }

 

         publicvoid connect() {

                   Set<BluetoothDevice>device = mBluetoothAdapter.getBondedDevices(); 

       

       if(device.size()>0){ //存在已經配對過的藍芽裝置 

           for(Iterator<BluetoothDevice>it=device.iterator();it.hasNext();){ 

                BluetoothDevicebtd=it.next(); 

                String name = btd.getName();

                String address =btd.getAddress();

                String nameString =btd.getName()+'\n'+btd.getAddress(); 

               Log.e(TAG_BLUE,"getBondedDevices :" + nameString);

                //if(name != null &&name.equals(BLUETOOTH_NAME)){

                if(address != null &&address.equals(mBluetoothAddress)){

                         mBlthChatUtil.connect(btd);

                         break;

                                               //Toast.makeText(mContext,"連線成功", Toast.LENGTH_SHORT).show();

                }

           } 

       }else{  //不存在已經配對過的藍芽裝置 

                Log.e(TAG,"No can bematched to use bluetooth"); 

       } 

}

十六進位制資料轉換HexCommandtoByte和訊息傳送函式sendBluetoothMessage

//  十六進位制的字串轉換成byte陣列     

    public static byte[]HexCommandtoByte(byte[] data) { 

            if (data == null) { 

                return null; 

            } 

            int nLength = data.length;  

              

            String strTemString = new String(data, 0, nLength); 

            String[] strings = strTemString.split(" "); 

            nLength = strings.length; 

            data = new byte[nLength];            

            for (int i = 0; i < nLength; i++) { 

                if (strings[i].length() != 2) { 

                     data[i] = 00; 

                     continue; 

                } 

                try { 

                     data[i] =(byte)Integer.parseInt(strings[i], 16); 

                } catch (Exception e) { 

                     data[i] = 00; 

                     continue; 

                } 

            } 

            return data; 

         }

         public void sendBluetoothMessage(Stringmessagesend){

                   Log.e(TAG_BLUE,"sendmessage : " + messagesend);

                   byte[] sendByte =HexCommandtoByte(messagesend.getBytes());

                   //mBlthChatUtil.write(messagesend.getBytes());

                   mBlthChatUtil.write(sendByte);

         }

 

(3)在返回onBackPressed()或者onDestroy()傳送關閉藍芽訊息,並登出藍芽:

//關閉

       sendBluetoothMessage(CLOSE_BLUE_HEX_STRING);

        if(mBluetoothAdapter!=null &&mBluetoothAdapter.isDiscovering()){ 

                 mBluetoothAdapter.cancelDiscovery(); 

        } 

       

        if (mBlthChatUtil.getState() !=BluetoothChatUtil.STATE_CONNECTED) {

                            Toast.makeText(mContext,"藍芽未連線", Toast.LENGTH_SHORT).show();

                   }else {

                            mBlthChatUtil.stop();

                   }

BluetoothChatUtil.java內容如下:

package XXX;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 這類做所有的工作,建立和管理藍芽
*連線其他裝置。它有一個執行緒,監聽
*傳入連線,螺紋連線裝置,和一個
*執行資料傳輸線連線時。
 */
public class BluetoothChatUtil {
    // 除錯
    private static final String TAG = "BluetoothChatService";
    private static final boolean D = true;

    // 名社民黨記錄當建立伺服器套接字
    private static final String NAME = "BluetoothChat";
    									 				
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	public static StringBuffer hexString = new StringBuffer();
    // 介面卡成員
    private final BluetoothAdapter mAdapter;
    private Handler mHandler;
    private AcceptThread mAcceptThread;
    private ConnectThread mConnectThread;
    private ConnectedThread mConnectedThread;
    private int mState;
	private static BluetoothChatUtil mBluetoothChatUtil;
	private BluetoothDevice mConnectedBluetoothDevice;
    //常數,指示當前的連線狀態
    public static final int STATE_NONE = 0;       // 當前沒有可用的連線
    public static final int STATE_LISTEN = 1;     // 現在偵聽傳入的連線
    public static final int STATE_CONNECTING = 2; // 現在開始傳出聯絡
    public static final int STATE_CONNECTED = 3;  // 現在連線到遠端裝置
    public static final int STATAE_CONNECT_FAILURE = 4;
    public static boolean bRun = true;
    public static final int MESSAGE_DISCONNECTED = 5;
    public static final int STATE_CHANGE = 6;
    public static final String DEVICE_NAME = "device_name";
    public static final int MESSAGE_READ = 7;
    public static final int MESSAGE_WRITE= 8;
    public static final String READ_MSG = "read_msg";
    /**
     * 建構函式。準備一個新的bluetoothchat會話。
     * @param context  使用者介面活動的背景
     */
    private BluetoothChatUtil(Context context) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;       
    }

    public static BluetoothChatUtil getInstance(Context c){
    	if(null == mBluetoothChatUtil){
    		mBluetoothChatUtil = new BluetoothChatUtil(c);
    	}
    	return mBluetoothChatUtil;
    }
    public void registerHandler(Handler handler){
    	mHandler = handler;
    }
    
    public void unregisterHandler(){
    	mHandler = null;
    }
    /**
     * 設定當前狀態的聊天連線
     * @param state  整數定義當前連線狀態
     */
    private synchronized void setState(int state) {
        if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
        mState = state;
        // 給新狀態的處理程式,介面活性可以更新
        mHandler.obtainMessage(STATE_CHANGE, state, -1).sendToTarget();
    }

    /**
     * 返回當前的連線狀態。 */
    public synchronized int getState() {
        return mState;
    }
    
    public BluetoothDevice getConnectedDevice(){
    	return mConnectedBluetoothDevice;
    }
    /**
     * 開始聊天服務。特別acceptthread開始    開始
     * 會話聽力(伺服器)模式。所謂的活動onresume() */
    public synchronized void start() {
        if (D) Log.d(TAG, "start");
        //取消任何執行緒試圖建立連線
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
        // 取消任何執行緒正在執行的連線
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
        // 啟動執行緒來聽一個bluetoothserversocket
        if (mAcceptThread == null) {
            mAcceptThread = new AcceptThread();
            mAcceptThread.start();
        }
        setState(STATE_LISTEN);
    }
   
    //連線按鍵響應函式
    /**
     * 開始connectthread啟動連線到遠端裝置。
     * @param 裝置連線的藍芽裝置
     */
    public synchronized void connect(BluetoothDevice device) {
        if (D) Log.d(TAG, "connect to: " + device);
        // 取消任何執行緒試圖建立連線
        if (mState == STATE_CONNECTING) {
            if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
        }
        // 取消任何執行緒正在執行的連線
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

        //啟動執行緒連線的裝置
        mConnectThread = new ConnectThread(device);
        mConnectThread.start();
        setState(STATE_CONNECTING);
    }

    /**
     * 開始connectedthread開始管理一個藍芽連線
     * @param bluetoothsocket插座上連線了
     * @param 裝置已連線的藍芽裝置
     */
    @SuppressWarnings("unused")
	public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
        if (D) Log.d(TAG, "connected");
        // 取消執行緒完成連線
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
        //取消任何執行緒正在執行的連線
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

        // 取消接受執行緒只因為我們要連線到一個裝置
        if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}

        // 啟動執行緒管理連線和傳輸
        mConnectedThread = new ConnectedThread(socket);
        mConnectedThread.start();
        //把名字的連線裝置到Activity
        mConnectedBluetoothDevice =  device;
        Message msg = mHandler.obtainMessage(STATE_CONNECTED);
        Bundle bundle = new Bundle();
        bundle.putString(DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        setState(STATE_CONNECTED);
       }

    /**
     * 停止所有的執行緒
     */
    public synchronized void stop() {
        if (D) Log.d(TAG, "stop");
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
        if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
        setState(STATE_NONE);
        //start();
    }

    /**
     * Write to the ConnectedThread in an unsynchronized manner
     * @param out The bytes to write
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        //建立臨時物件
        ConnectedThread r;
        // 同步副本的connectedthread
        synchronized (this) {
            if (mState != STATE_CONNECTED) return;
            r = mConnectedThread;
        }
        // 執行寫同步
        r.write(out);
    }

    /**
     * Indicate that the connection attempt failed and notify the UI Activity.
     */
    private void connectionFailed() {
        setState(STATE_LISTEN);
        // 傳送失敗的資訊帶回活動
        Message msg = mHandler.obtainMessage(STATAE_CONNECT_FAILURE);
        mHandler.sendMessage(msg);
        mConnectedBluetoothDevice = null;
    }

    /**
     * Indicate that the connection was lost and notify the UI Activity.
     */
    private void connectionLost() {
        setState(STATE_LISTEN);
        // 傳送失敗的資訊帶回Activity
        Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECTED);
        mHandler.sendMessage(msg);
        mConnectedBluetoothDevice = null;
        stop();
    }

    /**
    *本線同時偵聽傳入的連線。它的行為
    *喜歡一個伺服器端的客戶端。它執行直到連線被接受
    *(或取消)。
     */
    private class AcceptThread extends Thread {
        // 本地伺服器套接字
        private final BluetoothServerSocket mServerSocket;
        public AcceptThread() {       	
            BluetoothServerSocket tmp = null;
            // 建立一個新的偵聽伺服器套接字
            try {
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "listen() failed", e);
            }
            mServerSocket = tmp;
        }

        public void run() {
            if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
            setName("AcceptThread");
            BluetoothSocket socket = null;
            // 迴圈,直到連線成功
            while (mState != STATE_CONNECTED) {
                try {
                    // 這是一個阻塞呼叫和將只返回一個
                    // 成功的連線或例外
                    socket = mServerSocket.accept();
                } catch (IOException e) {
                    Log.e(TAG, "accept() failed", e);
                    break;
                }
                // 如果連線被接受
                if (socket != null) {
                    synchronized (BluetoothChatUtil.this) {
                        switch (mState) {
                        case STATE_LISTEN:
                        case STATE_CONNECTING:
                            // 正常情況。啟動連線螺紋。
                            connected(socket, socket.getRemoteDevice());
                            break;
                        case STATE_NONE:
                        case STATE_CONNECTED:
                            // 沒有準備或已連線。新插座終止。
                            try {
                                socket.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Could not close unwanted socket", e);
                            }
                            break;
                        }
                    }
                }
            }
            if (D) Log.i(TAG, "END mAcceptThread");
        }

        public void cancel() {
            if (D) Log.d(TAG, "cancel " + this);
            try {
                mServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of server failed", e);
            }
        }
    }


    /**
     * 本線在試圖使傳出聯絡
     *與裝置。它徑直穿過連線;或者
     *成功或失敗。
     */
    private class ConnectThread extends Thread {
        private BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
        public ConnectThread(BluetoothDevice device) {
            mmDevice = device;
            BluetoothSocket tmp = null;
            // 得到一個bluetoothsocket
            try {
            	mmSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "create() failed", e);
                mmSocket = null;
            }
        }

        public void run() {
            Log.i(TAG, "BEGIN mConnectThread");
            setName("ConnectThread");
            mAdapter.cancelDiscovery();
            // 使一個連線到bluetoothsocket
            try {
                // socket 連線
                mmSocket.connect();
            } catch (IOException e) {
                connectionFailed();
                //關閉這個socket
                try {
                    mmSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() socket during connection failure", e2);
                }
                // 啟動服務在重新啟動聆聽模式
                BluetoothChatUtil.this.start();
                return;
            }
            // 因為我們所做的connectthread復位
            synchronized (BluetoothChatUtil.this) {
                mConnectThread = null;
            }
            // 啟動連線執行緒
            connected(mmSocket, mmDevice);
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }

    /**
     * 本線在連線與遠端裝置。
     * 它處理所有傳入和傳出的傳輸。
     */
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        
        public ConnectedThread(BluetoothSocket socket) {
            Log.d(TAG, "create ConnectedThread");
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
            // 獲得bluetoothsocket輸入輸出流
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "沒有建立臨時sockets", e);
            }
            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }  
       
        public void run() {
            Log.i(TAG, "BEGIN mConnectedThread");
            int bytes;
            // 繼續聽InputStream同時連線
            while (true) {
                try {
                	 byte[] buffer = new byte[1024];
                    // 讀取輸入流
                    bytes = mmInStream.read(buffer);

                    // 傳送獲得的位元組的使用者介面
                    Message msg = mHandler.obtainMessage(MESSAGE_READ);
                    Bundle bundle = new Bundle();
                    bundle.putByteArray(READ_MSG, buffer);
                    msg.setData(bundle);
                    mHandler.sendMessage(msg);          
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    connectionLost();
                    break;
                }
            }
       }
        /**
         * 寫輸出的連線。
         * @param buffer  這是一個位元組流
         */
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);
                // 分享傳送的資訊到Activity
                mHandler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
            
        }
 
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }
}


自己修改後的程式碼下載地址是:http://download.csdn.net/detail/u200814342a/9839396,記得要改一下連線的藍芽地址或者名稱!