1. 程式人生 > >android 手機與藍芽裝置之間連線與通訊,附DEMO下載地址

android 手機與藍芽裝置之間連線與通訊,附DEMO下載地址

下載地址為文章最後面。。。

該文章主要用於手機藍芽App介面的操作和通訊,儲存到本地的通訊後資料txt文字檔案

1.主要包括介面

          

2.AndroidManifest.xml需要用到的許可權

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- SD卡操作許可權 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

3.主要的藍芽工具類:

package com.example.bluetooth;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import com.example.main.MainActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
/**
 * 藍芽服務類,包括藍芽連線監聽執行緒、連線執行緒、已連線執行緒
 * @author Administrator
 *
 */
public class BluetoothService {
    
    private static final String TAG = "Service";
    private static final boolean DEBUG = true;

    // 藍芽埠名
    private static final String BT_NAME = "XULANG";

    // 獲取裝置UUID				 				
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private final BluetoothAdapter mAdapter;
    private final Handler mHandler;
    private AcceptThread mAcceptThread;
    private ConnectThread mConnectThread;
    private ConnectedThread mConnectedThread;
    private int BtState;
    //藍芽狀態常量
    public static final int IDLE = 0;       // 閒置
    public static final int LISTENING = 1;  // 監聽
    public static final int CONNECTING = 2; // 正在連線
    public static final int CONNECTED = 3;  // 已連線

    public static boolean allowRec=true;
    /**
     * @param handler  線上程與UI間通訊
     */
    public BluetoothService(Handler handler) {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        BtState = IDLE;
        mHandler = handler;
    }

    /**
     * 設定當前藍芽狀態
     * @param state  當前藍芽狀態
     */
    private synchronized void setState(int state) {
        BtState = state;
    }

    /**
     * 獲取當前藍芽狀態
     * @return 當前藍芽狀態
     */
    public synchronized int getState() {
        return BtState;
    }

    /**
     * 啟動本地藍芽接收監聽
     */
    public synchronized void acceptWait() {
        if (DEBUG) Log.e(TAG, "進入acceptWait");
        // 開啟外主藍芽接收監聽執行緒
        if (mAcceptThread == null&&mConnectedThread==null) {
            mAcceptThread = new AcceptThread();
            mAcceptThread.start();
        }
        setState(LISTENING);
    }

    /**
     * 開啟連線執行緒方法
     * @param device  欲連線的裝置
     */
    public synchronized void connect(BluetoothDevice device) {
        if (DEBUG) Log.e(TAG, "正在連線" + device);

        //關閉所有可能的藍芽服務執行緒以便開啟連線執行緒
        cancelAllBtThread();
        // 開啟連線執行緒
        mConnectThread = new ConnectThread(device);
        mConnectThread.start();
        setState(CONNECTING);
    }

    /**
     * 開啟已連線執行緒的方法
     * @param socket  已建立連線的藍芽埠
     * @param device  已連線的藍芽裝置
     */
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
        if (DEBUG) Log.e(TAG, "connected");

        //關閉所有可能的藍芽服務執行緒以便開啟已連線執行緒
        cancelAllBtThread();

        // 開啟已連線執行緒
        mConnectedThread = new ConnectedThread(socket);
        mConnectedThread.start();

        //傳送已連線裝置名回UI
        sendString2UI(MainActivity.CONNECTED_DEVICE_NAME,
        				MainActivity.DEVICE_NAME,device.getName());
        setState(CONNECTED);
    }

    /**
     * 關閉所有藍芽服務執行緒
     */
    public synchronized void cancelAllBtThread() {
        if (DEBUG) Log.e(TAG, "cancelAllBtThread方法");
        if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
        if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
        if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;}
        setState(IDLE);
    }

    /**
     * 寫輸出資料
     * @param out 輸出位元組流
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        //                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              object
        ConnectedThread r;
        // 同步
        synchronized (this) {
            if (BtState != CONNECTED) return;
            r = mConnectedThread;
        }
        r.write(out);
    }

    /**
     * 連線失敗處理方法
     */
    private void connectionFailed() {
        setState(LISTENING);
        mConnectedThread=null;
        BluetoothService.this.acceptWait();
        //向UI傳送連線失敗通知
        sendString2UI(MainActivity.BT_TOAST,MainActivity.TOAST,"連線失敗");
    }
    /**
     * 傳送字串會UI
     * @param what 什麼型別
     * @param key  關鍵字
     * @param str  字串
     */
    private void sendString2UI(int what,String key,String str){
    	Message msg = mHandler.obtainMessage(what);
        Bundle bundle = new Bundle();
        bundle.putString(key, str);
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }
    /**
     * 連線斷開處理方法
     */
    private void connectionBreak() {
        setState(LISTENING);
        mConnectedThread=null;
        BluetoothService.this.acceptWait();
        // 向UI傳送連線斷開通知
        sendString2UI(MainActivity.BT_TOAST,MainActivity.TOAST,"連線斷開");
    }

    /**
     * 監聽外部主藍芽裝置執行緒
     */
    private class AcceptThread extends Thread {
       
        private final BluetoothServerSocket mBtServSocket;

        public AcceptThread() {
            BluetoothServerSocket bss = null;
            // 獲取藍芽監聽埠
            try {
                bss = mAdapter.listenUsingRfcommWithServiceRecord(BT_NAME, MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "listen() failed", e);
            }
            mBtServSocket = bss;
        }

        public void run() {
            if (DEBUG) Log.e(TAG, "Begin mAcceptThread");
            setName("AcceptThread");
            BluetoothSocket socket = null;
            // 監聽埠直到連線上
            while (BtState != CONNECTED) {
                try {
                    //成功連線時退出迴圈
                    socket = mBtServSocket.accept();
                } catch (IOException e) {
                    Log.e(TAG, "accept() failed", e);
                    break;
                }
                // 成功接收主裝置
                if (socket != null) {
                    synchronized (BluetoothService.this) {
                        switch (BtState) {
                        case LISTENING:
                        case CONNECTING:
                            // 啟動已連線執行緒
                            connected(socket, socket.getRemoteDevice());
                            break;
                        case IDLE:
                        case CONNECTED:
                            try {
                                socket.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Could not close unwanted socket", e);
                            }
                            break;
                        }
                    }
                }
            }
            if (DEBUG) Log.e(TAG, "End mAcceptThread");
        }

        public void cancel() {
            if (DEBUG) Log.e(TAG, "cancel " + this);
            try {
            	mBtServSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of server failed", e);
            }
        }
    }
    /**
     * 連線藍芽裝置的執行緒
     */
    private class ConnectThread extends Thread {
        private final BluetoothSocket mBtSocket;
        private final BluetoothDevice mBtDevice;

        public ConnectThread(BluetoothDevice device) {
        	mBtDevice = device;
            BluetoothSocket bs = null;

            // 根據UUID獲取欲連線裝置
            try {
                bs = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) {
                Log.e(TAG, "create() failed", e);
            }
            mBtSocket = bs;
        }

        public void run() {
        	if (DEBUG) Log.e(TAG, "Begin mConnectThread");
            setName("ConnectThread");
            // 嘗試連線藍芽埠
            try {
            	mBtSocket.connect();
            } catch (IOException e) {
                // 當連線失敗或異常
                connectionFailed();
                try {
                	mBtSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "close() fail", e2);
                }
                // 重新開啟連線監聽執行緒並退出連線執行緒
                BluetoothService.this.acceptWait();
                if (DEBUG) Log.d(TAG, "End mConnectThread");
                return;
            }

            synchronized (BluetoothService.this) {
                mConnectThread = null;
            }
            // 啟動已連線執行緒
            connected(mBtSocket, mBtDevice);
            if (DEBUG) Log.d(TAG, "End mConnectThread");
        }

        public void cancel() {
            if (DEBUG) Log.e(TAG, "cancel " + this);
            try {
            	mBtSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() fail", e);
            }
        }
    }

    /**
     * 已連線的相關處理執行緒
     */
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mBtSocket;
        private final InputStream mInputStream;
        private final OutputStream mOutputStream;

        public ConnectedThread(BluetoothSocket socket) {
        	if (DEBUG) Log.d(TAG, "construct ConnectedThread");
            mBtSocket = socket;
            InputStream is = null;
            OutputStream os = null;

            // 獲取輸入輸出流
            try {
            	is = socket.getInputStream();
            	os = socket.getOutputStream();
            } catch (IOException e) {
                Log.i(TAG, "get Stream fail", e);
            }

            mInputStream = is;
            mOutputStream = os;
        }

        public void run() {
        	if (DEBUG) Log.i(TAG, "Begin mConnectedThread");
            byte[] buffer=new byte[1024];
            int bytes;

            // 監聽輸入流以備獲取資料
            while (true) {
                try {
                    bytes = mInputStream.read(buffer);
                    // 將接受資料發回UI處理
                    if(bytes!=-1&&allowRec){
                    mHandler.obtainMessage(MainActivity.REC_DATA,bytes,-1,buffer).sendToTarget();
                    }
                } catch (IOException e) {
                    Log.e(TAG, "connection break", e);
                    connectionBreak();
                    break;
                }
                try {
                	//執行緒睡眠20ms以避免過於頻繁工作  50ms->20ms 2017.12.2
                	//導致UI處理髮回的資料不及時而阻塞
					Thread.sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }
            if (DEBUG) Log.i(TAG, "End mConnectedThread");
        }

        /**
         * 寫輸出流以傳送資料
         * @param buffer 欲輸出位元組流
         */
        public void write(byte[] buffer) {
            try {
            	mOutputStream.write(buffer);

            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }

        public void cancel() {
            if (DEBUG) Log.e(TAG, "cancel " + this);
            try {
            	mBtSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() fail", e);
            }
        }
    }
}