国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

學習筆記之經典藍牙開發

2019-11-09 17:16:13
字體:
來源:轉載
供稿:網友

概述

去年公司的項目需要用到藍牙開發的相關內容,因此查閱了Google官方文檔的內容并進行二次整理。本文只涉及經典藍牙(Classic Bluetooth)的開發,并不涉及低功耗藍牙(BLE)的開發,本文應用場景為藍牙單聊。

官方項目:GoogleSamples-android-BluetoothChat

Bluetooth Low Energy:學習筆記之低功耗藍牙開發

效果圖A-小米4手機

效果圖B-魅藍2手機

權限

經典藍牙需要用到2個權限

允許程序連接到已配對的藍牙設備<uses-permission android:name="android.permission.BLUETOOTH"/>允許程序發現和配對藍牙設備<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

在AndroidManifest加上這個2個權限

打開藍牙

(1)判斷該設備是否支持藍牙、藍牙功能是否被打開

public boolean openBluetooth() {        if (adapter == null) {            Toast.makeText(this, "該設備不支持藍牙", Toast.LENGTH_LONG).show();            return false;        } else {            if (!adapter.isEnabled()) { // 打開藍牙                   // 設置藍牙可見性,最多300秒                   Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);                intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);                startActivityForResult(intent, 0);                return false;            }        }        return true;    }

(2)在onActivityResult方法處理回調結果

@Override    PRotected void onActivityResult(int requestCode, int resultCode, Intent data) {        switch (resultCode) {            case RESULT_OK:                Toast.makeText(this, "開啟藍牙成功", Toast.LENGTH_SHORT).show();                break;            case RESULT_CANCELED:                Toast.makeText(this, "開啟藍牙失敗", Toast.LENGTH_SHORT).show();                break;        }    }

發現/搜索設備

(1)通過getBondedDevice()方法的獲得已經匹配的設備。然后調用startDiscovery()方法來開始設備的搜索

public void addBluetooth(ArrayList<BluetoothDevice> mainList) {        Set<BluetoothDevice> pairedDevices = adapter.getBondedDevices();        if (pairedDevices.size() > 0) {            for (BluetoothDevice device : pairedDevices) {                if (!mainList.contains(device)) {                    mainList.add(device);                }            }        }        // 尋找藍牙設備,android會將查找到的設備以廣播形式發出去           adapter.startDiscovery();    }(2)通過廣播的形式來添加搜索附近藍牙設備
private 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) {//已匹配的設備                    if (device != null) {                        if (!mainList.contains(device)) {                            mainList.add(device);                            lvAdapter.notifyDataSetChanged();                        }                    }                }*/                if(device!=null){                if (!mainList.contains(device)) {//未包含則添加                        mainList.add(device);                    lvAdapter.notifyDataSetChanged();                }                }            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {//搜索結束                stopAnimation(fab);            }            Log.e("BLUE", "size = " + mainList.size());            lvAdapter.notifyDataSetChanged();        }    };(3)動態注冊并設置廣播,記得銷毀activity時銷毀

private void initReceiver() {        IntentFilter intentFilter = new IntentFilter();// 設置廣播信息過濾           intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//掃描發現設備廣播        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//設備連接狀態改變的廣播        intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);//掃描模式變化廣播        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//開關模式變化廣播        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//掃描結束        // 注冊廣播接收器,接收并處理搜索結果           registerReceiver(receiver, intentFilter);    }

設備配對與解除

注意事項

①藍牙設備之間自動配對,需要兩個設備都安裝進行配對的apk

②由于BluetoothDevice配對的方法都是hide的,所以我們需要通過反射調用被隱藏的方法(現在基本都是通用的工具,網上模板基本一樣,參考這里)

(1)配對事件

protected void connectDevice(BluetoothDevice mBluetoothDevice) {        try {            if (mBluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE) {//未配對                ClsUtils.createBond(mBluetoothDevice.getClass(), mBluetoothDevice);            }else if(mBluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDING){//配對中                ClsUtils.cancelBondProcess(BluetoothDevice.class, mBluetoothDevice);            } else {                ClsUtils.removeBond(BluetoothDevice.class, mBluetoothDevice);                Toast.makeText(this, "藍牙配對解除", Toast.LENGTH_SHORT).show();            }        } catch (Exception e) {            e.printStackTrace();        }    }

(2)藍牙配對廣播接收

public class BuletoothPairingReceiver extends BroadcastReceiver {    String strPsw = "0000";    final String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";    @Override    public void onReceive(Context context, Intent intent) {        if (intent.getAction().equals(ACTION_PAIRING_REQUEST)) {            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);            if (device.getBondState() != BluetoothDevice.BOND_BONDED) {                try {                    abortBroadcast();//如果沒有將廣播終止,則會出現一個一閃而過的配對框。                    //確認配對                    ClsUtils.setPairingConfirmation(device.getClass(), device, true);                    //調用setPin方法進行配對...                    boolean ret = ClsUtils.setPin(device.getClass(), device, strPsw);//                  Toast.makeText(context, "配對信息" + device.getName()+"=="+ret, Toast.LENGTH_LONG).show();                } catch (Exception e) {                    Toast.makeText(context, "請求連接錯誤...", Toast.LENGTH_LONG).show();                }            }        }    }}

(3)AndroidManifest靜態注冊廣播

<receiver android:name=".receiver.PairingRequest">            <intent-filter android:priority="1000">                <action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />            </intent-filter>        </receiver>

(4)設置藍牙設備可見性

static public void setDiscoverableTimeout(BluetoothAdapter adapter, int timeout) {        try {            Method setDiscoverableTimeout = BluetoothAdapter.class.getMethod("setDiscoverableTimeout", int.class);            setDiscoverableTimeout.setaccessible(true);            Method setScanMode = BluetoothAdapter.class.getMethod("setScanMode", int.class, int.class);            setScanMode.setAccessible(true);            setDiscoverableTimeout.invoke(adapter, timeout);            setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, timeout);        } catch (Exception e) {            e.printStackTrace();        }    }

(5)關閉藍牙設備可見性

static public void closeDiscoverableTimeout(BluetoothAdapter adapter) {        try {            Method setDiscoverableTimeout = BluetoothAdapter.class.getMethod("setDiscoverableTimeout", int.class);            setDiscoverableTimeout.setAccessible(true);            Method setScanMode = BluetoothAdapter.class.getMethod("setScanMode", int.class, int.class);            setScanMode.setAccessible(true);            setDiscoverableTimeout.invoke(adapter, 1);            setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE, 1);        } catch (Exception e) {            e.printStackTrace();        }    }

連接通信

(1)基本流程

①主動連接:通過調用BluetoothDevice的createRfcommSocketToServiceRecord(UUID)方法,獲得一個BluetoothSocket對象。通過調用connect()方法來初始化連接。在這個調用中,為了找到匹配的UUID,系統會在遠程的設備上執行一個SDP查詢。如果查詢成功,并且遠程設備接收了該連接請求,那么它會在連接期間共享使用RFCOMM通道,并且connect()方法會返回。這個方法是一個阻塞調用。如果因為某些原因,連接失敗或連接超時(大約在12秒之后),就會拋出一個異常。 

②被動連接:通過調用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String name, UUID uuid),獲得BluetoothServerSocket對象。該方法中的String參數是一個可識別的你的服務端的名稱,系統會自動的把它寫入設備上的Service Discovery Protocol(SDP)數據庫實體(該名稱是任意的,并且可以簡單的使用你的應用程序的名稱)。UUID參數也會被包含在SDP實體中,并且是跟客戶端設備連接的基本協議。也就是說,當客戶端嘗試跟服務端連接時,它會攜帶一個它想要連接的服務端能夠唯一識別的UUID。只有在這些UUID完全匹配的情況下,連接才可能被接收。通過調用accept()方法,啟動連接請求。這是一個阻塞調用。只有在連接被接收或發生異常的情況下,該方法才返回。只有在發送連接請求的遠程設備所攜帶的UUID跟監聽服務套接字所注冊的一個UUID匹配的時候,該連接才被接收。連接成功,accept()方法會返回一個被連接的BluetoothSocket對象。 除非你想要接收其他連接,否則在接收到一個連接套接字之后,立即調用BluetoothServerSocket對象的close()方法。該方法會釋放服務套接字以及它所占用的所有資源,但不會關閉被連接的已經有accept()方法所返回的BluetoothSocket對象。

③數據傳輸:當你成功的連接了兩個(或更多)設備時,每一個設備都有一個被連接的BluetoothSocket對象。使用BluetoothSocket對象分別通過getInputStream()和getOutputStream()方法來獲得通過套接字來處理傳輸任務的InputStream和OutputStream對象; 用read(byte[])和write(byte[])方法來讀寫流中的數據。 

(2)Google的藍牙聊天源碼的分析

ConnectThread:主動發起藍牙連接線程,此線程在試圖與設備進行傳出連接時運行,它直接通過連接成功或失敗

ConnectedThread:藍牙連接成功后啟動,此線程在與遠程設備連接期間運行。它處理所有傳入和傳出的傳輸

AcceptThread:監聽來自其他設備的藍牙連接,此線程在偵聽傳入連接時運行,它一直運行到連接被接收(或者直到被取消)

關鍵代碼

@SuppressLint("NewApi")public class ChatService {    private static final String TAG = "ChatService";    private static final String NAME_SECURE = "Bluetooth Secure";    private static final UUID UUID_ANDROID_DEVICE =            UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");    private static final UUID UUID_OTHER_DEVICE =            UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");//藍牙串口服務    private final BluetoothAdapter mAdapter;    private final Handler mHandler;    private AcceptThread mSecureAcceptThread;    private ConnectThread mConnectThread;    private ConnectedThread mConnectedThread;    private int mState;    Context context;    /**     * 準備一個新的bluetoothchat會話     *     * @param context     * @param handler     * @param mAdapter     */    public ChatService(Context context, Handler handler, BluetoothAdapter mAdapter) {        this.mAdapter = mAdapter;        mState = ChatState.STATE_NONE;        mHandler = handler;        this.context = context;    }    /**     * 設置聊天連接的當前狀態     *     * @param state     */    private synchronized void setState(int state) {        Log.d(TAG, "setState() " + mState + " -> " + state);        mHandler.obtainMessage(ChatState.MESSAGE_STATE_CHANGE, state, mState).sendToTarget();        mState = state;    }    /**     * 返回當前連接狀態     *     * @return     */    public synchronized int getState() {        return mState;    }    /**     * 開始聊天     */    public synchronized void start() {        /**         * 取消試圖連接的任何線程         */        if (mConnectThread != null) {            mConnectThread.cancel();            mConnectThread = null;        }        /**         *取消當前運行連接的任何線程         */        if (mConnectedThread != null) {            mConnectedThread.cancel();            mConnectedThread = null;        }        setState(ChatState.STATE_LISTEN);        /**         * 啟動線程監聽一個bluetoothserversocket         */        if (mSecureAcceptThread == null) {            mSecureAcceptThread = new AcceptThread();            mSecureAcceptThread.start();        }    }    /**     * 開始connectthread發起一個連接到一個遠程設備     *     * @param device 連接的藍牙設備     */    public synchronized void connect(BluetoothDevice device) {        /**         * 取消試圖連接的任何線程         */        if (mState == ChatState.STATE_CONNECTING) {            if (mConnectThread != null) {                mConnectThread.cancel();                mConnectThread = null;            }        }        /**         * 取消當前運行連接的任何線程         */        if (mConnectedThread != null) {            mConnectedThread.cancel();            mConnectedThread = null;        }        /**         *啟動線程與給定設備連接         */        mConnectThread = new ConnectThread(device);        mConnectThread.start();        setState(ChatState.STATE_CONNECTING);    }    /**     * 開始connectedthread開始管理藍牙連接     *     * @param socket     * @param device 已連接的藍牙設備     */    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {        Log.i(TAG, "connected");        /**         * 取消完成連接的線程         */        if (mConnectThread != null) {            mConnectThread.cancel();            mConnectThread = null;        }        /**         * 取消當前運行連接的任何線程         */        if (mConnectedThread != null) {            mConnectedThread.cancel();            mConnectedThread = null;        }        /**         * 取消接受線程,因為我們只想連接到一個設備         */        if (mSecureAcceptThread != null) {            mSecureAcceptThread.cancel();            mSecureAcceptThread = null;        }        /**         * 啟動線程管理連接并執行傳輸         */        mConnectedThread = new ConnectedThread(socket);        mConnectedThread.start();        /**         * 將連接的設備的名稱返回到UI活動.         */        Message msg = mHandler.obtainMessage(ChatState.MESSAGE_DEVICE_INFO);        Bundle bundle = new Bundle();        bundle.putString(ChatState.DEVICE_NAME, device.getName());        bundle.putString(ChatState.DEVICE_ADDRESS, device.getAddress());        msg.setData(bundle);        mHandler.sendMessage(msg);        setState(ChatState.STATE_CONNECTED);    }    /**     * 停止所有的線程     */    public synchronized void stop() {        if (mConnectThread != null) {            mConnectThread.cancel();            mConnectThread = null;        }        if (mConnectedThread != null) {            mConnectedThread.cancel();            mConnectedThread = null;        }        if (mSecureAcceptThread != null) {            mSecureAcceptThread.cancel();            mSecureAcceptThread.kill();            mSecureAcceptThread = null;        }        setState(ChatState.STATE_NONE);    }    /**     * 寫入     *     * @param out     */    public void write(byte[] out) {        Log.e(TAG, "write string out=" + Bytes2HexString(out));        ConnectedThread r;        synchronized (this) {            if (mState != ChatState.STATE_CONNECTED) return;            r = mConnectedThread;        }        r.write(out);    }    /**     * byte[]轉string     */    public static String Bytes2HexString(byte[] b) {        String ret = "";        for (int i = 0; i < b.length; i++) {            String hex = Integer.toHexString(b[i] & 0xFF);            if (hex.length() == 1) {                hex = '0' + hex;            }            ret += hex.toUpperCase();        }        return ret;    }    /**     * 指示連接嘗試失敗,重新連接     */    private void connectionFailed() {        ChatService.this.start();    }    /**     * 此線程在偵聽傳入連接時運行。它的行為像一個服務器端客戶端。它一直運行到連接被接收(或者直到被取消)     */    private class AcceptThread extends Thread {        private BluetoothServerSocket mmServerSocket;        boolean isRunning = true;        private boolean mmss() {            if (mmServerSocket == null) {                return false;            }            return true;        }        public AcceptThread() {            BluetoothServerSocket tmp = null;            /**             *創建一個新的BluetoothServerSocket監聽服務器套接字             */            try {                if (ChatState.DEVICE_ANDROID)                    tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_ANDROID_DEVICE);                else                    tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_OTHER_DEVICE);            } catch (IOException e) {                try {                    throw new SocketException(context, "error-AcceptThread", e);                } catch (SocketException e1) {                    e1.printStackTrace();                    Log.e("soketException", "error-AcceptThread");                }            }            mmServerSocket = tmp;        }        public void run() {            setName("AcceptThread");            BluetoothSocket socket = null;            Log.i(TAG, "run");            /**             * 如果沒有連接,監聽服務器套接字             */            while (mState != ChatState.STATE_CONNECTED && isRunning) {                try {                    /**                     * 這是一個阻塞調用,只會返回成功的連接或異常                     */                    if (mmss())                        socket = mmServerSocket.accept();                } catch (IOException e) {                    try {                        throw new SocketException(context, "error-AcceptThread-run1", e);                    } catch (SocketException e1) {                        e1.printStackTrace();                        Log.e("soketException", "error-AcceptThread-run1");                    }                    break;                }                /**                 * 如果一個連接被接受                 */                if (socket != null) {                    synchronized (ChatService.this) {                        switch (mState) {                            case ChatState.STATE_LISTEN:                            case ChatState.STATE_CONNECTING:                                /**                                 * 正常情況。啟動連接的線程                                 */                                connected(socket, socket.getRemoteDevice());                                break;                            case ChatState.STATE_NONE:                            case ChatState.STATE_CONNECTED:                                /**                                 * 要么沒有準備好,要么已經連接。終止新套接字。                                 */                                try {                                    socket.close();                                } catch (IOException e) {                                    try {                                        throw new SocketException(context, "error-AcceptThread-run2", e);                                    } catch (SocketException e1) {                                        e1.printStackTrace();                                        Log.e("soketException", "error-AcceptThread-run2");                                    }                                }                                break;                        }                    }                }            }        }        /**         * 關閉Socket         */        public void cancel() {            try {                if (mmss()) {                    mmServerSocket.close();                }                mmServerSocket = null;            } catch (IOException e) {                try {                    throw new SocketException(context, "error-cancel", e);                } catch (SocketException e1) {                    e1.printStackTrace();                    Log.e("soketException", "error-cancel");                }            }        }        public void kill() {            isRunning = false;        }    }    /**     * 此線程在試圖與設備進行傳出連接時運行。它直接通過連接成功或失敗     */    private class ConnectThread extends Thread {        private final BluetoothSocket mmSocket;        private final BluetoothDevice mmDevice;        private boolean mms() {            if (mmSocket == null) {                return false;            }            return true;        }        public ConnectThread(BluetoothDevice device) {            mmDevice = device;            BluetoothSocket tmp = null;            /**             * 得到一個與給定的藍牙設備連接BluetoothSocket             */            try {                if (ChatState.DEVICE_ANDROID)                    tmp = device.createRfcommSocketToServiceRecord(UUID_ANDROID_DEVICE);                else                    tmp = device.createRfcommSocketToServiceRecord(UUID_OTHER_DEVICE);            } catch (IOException e) {                try {                    throw new SocketException(context, "error-ConnectThread", e);                } catch (SocketException e1) {                    e1.printStackTrace();                    Log.e("soketException", "error-ConnectThread");                }            }            mmSocket = tmp;        }        public void run() {            /**             * 關閉藍牙掃描,因為它會減慢連接速度             */            mAdapter.cancelDiscovery();            /**             * 連接BluetoothSocket             */            try {                /**                 * 這是一個阻塞調用,只會返回成功的連接或異常                 */                if (mms())                    mmSocket.connect();            } catch (IOException e) {                cancel();                connectionFailed();                return;            }            /**             * 用完復位 ConnectThread             */            synchronized (ChatService.this) {                mConnectThread = null;            }            connected(mmSocket, mmDevice);        }        /**         * 關閉Socket         */        public void cancel() {            try {                if (mms())                    mmSocket.close();            } catch (IOException e) {                try {                    throw new SocketException(context, "error-cancel", e);                } catch (SocketException e1) {                    e1.printStackTrace();                    Log.e("soketException", "error-cancel");                }            }        }    }    /**     * 此線程在與遠程設備連接期間運行。它處理所有傳入和傳出的傳輸     *     */    private class ConnectedThread extends Thread {        private final BluetoothSocket mmSocket;        private final InputStream mmInStream;        private final OutputStream mmOutStream;        private boolean mms() {            if (mmSocket == null) {                return false;            }            return true;        }        public ConnectedThread(BluetoothSocket socket) {            mmSocket = socket;            InputStream tmpIn = null;            OutputStream tmpOut = null;            Log.i(TAG, "ConnectedThread");            /**             * 得到BluetoothSocket的輸入和輸出流             */            try {                tmpIn = socket.getInputStream();                tmpOut = socket.getOutputStream();            } catch (IOException e) {                try {                    throw new SocketException(context, "error-ConnectedThread", e);                } catch (SocketException e1) {                    e1.printStackTrace();                    Log.e("soketException", "error-ConnectedThread");                }            }            mmInStream = tmpIn;            mmOutStream = tmpOut;            Log.i(TAG, "ConnectedThread mmInStream=" + mmInStream);            Log.i(TAG, "ConnectedThread mmOutStream=" + mmOutStream);        }        public void run() {            byte[] buffer;            ArrayList<Integer> arr_byte = new ArrayList<Integer>();            int before = 0;            /**             * 循環讀取輸入流             */            while (true) {                try {                    int data = mmInStream.read();                    if (data == 0x0D && before == 0x0A) {                        buffer = new byte[arr_byte.size()];                        for (int i = 0; i < buffer.length; i++) {                            buffer[i] = arr_byte.get(i).byteValue();                        }                        Log.i(TAG, "run arr_byte=" + arr_byte);                        Log.i(TAG, "run arr_byte.size()=" + arr_byte.size());                        Log.i(TAG, "run buffer=" + buffer);                        Log.i(TAG, "run buffer=" + buffer.length);                        mHandler.obtainMessage(ChatState.MESSAGE_READ                                , buffer.length, -1, buffer).sendToTarget();                        arr_byte = new ArrayList<Integer>();                    } else {                        arr_byte.add(data);                    }                    before = data;                } catch (IOException e) {                    connectionFailed();                    break;                }            }        }        /**         * 寫入輸出流         *         * @param buffer         */        public void write(byte[] buffer) {            Log.i(TAG, "write buffer=" + buffer);            Log.i(TAG, "write buffer.length=" + buffer.length);            try {                byte[] buffer2 = new byte[buffer.length + 2];                for (int i = 0; i < buffer.length; i++)                    buffer2[i] = buffer[i];                buffer2[buffer2.length - 2] = 0x0A;                buffer2[buffer2.length - 1] = 0x0D;                Log.i(TAG, "write buffer2.length=" + buffer2.length);                mmOutStream.write(buffer2);                Log.i(TAG, "write mmOutStream=" + mmOutStream);                mHandler.obtainMessage(ChatState.MESSAGE_WRITE                        , -1, -1, buffer).sendToTarget();            } catch (IOException e) {                try {                    throw new SocketException(context, "error-write", e);                } catch (SocketException e1) {                    e1.printStackTrace();                    Log.e("soketException", "error-write");                }            }        }        /**         * 關閉Socket         */        public void cancel() {            try {                if (mms())                    mmSocket.close();            } catch (IOException e) {                try {                    throw new SocketException(context, "error-cancel", e);                } catch (SocketException e1) {                    e1.printStackTrace();                    Log.e("soketException", "error-cancel");                }            }        }    }}

(2)在ChatConnectControl負責接收Handler消息進行處理,提供若干函數供UI使用。

public class ChatConnectControl {    public static String TAG = "ChatConnectControl";    /**     * 藍牙會話監聽     */    private BluetoothChatListener mBluetoothChatListener = null;    /**     * 藍牙默認的適配器     */    private BluetoothAdapter mBluetoothAdapter = null;    /**     * 藍牙聊天服務     */    private ChatService mChatService = null;    private String mDeviceName = null;    private String mDeviceAddress = null;    /**     * 是否已連接     */    private boolean isConnected = false;    /**     * 是否福連接中     */    private boolean isConnecting = false;    private Context mContext;    public ChatConnectControl(Context context, BluetoothAdapter mBluetoothAdapter) {        mContext = context;        this.mBluetoothAdapter = mBluetoothAdapter;    }    /**     * 服務是否啟動     *     * @return     */    public boolean isServiceAvailable() {        return mChatService != null;    }    /**     * 初始化藍牙聊天服務     */    public void setupService() {        mChatService = new ChatService(mContext, mHandler, mBluetoothAdapter);    }    /**     * 藍牙聊天當前連接狀態     *     * @return     */    public int getServiceState() {        if (mChatService != null)            return mChatService.getState();        else            return -1;    }    /**     * 啟動     */    public void startService() {        if (mChatService != null) {            if (mChatService.getState() == ChatState.STATE_NONE) {                mChatService.start();            }        }    }    /**     * 停止     */    public void stopService() {        if (mChatService != null) {            mChatService.stop();        }        new Handler().postDelayed(new Runnable() {            public void run() {                if (mChatService != null) {                    mChatService.stop();                }            }        }, 500);    }    /**     * 重啟/切換     */    public void setDeviceTarget() {        stopService();        startService();    }    /**     * 連接     *     * @param address     */    public void connect(String address) {        Log.e(TAG, "connect address=" + address);        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);        mChatService.connect(device);    }    /**     * 斷開     */    public void disconnect() {        Log.i(TAG, "disconnect");        if (mChatService != null) {            mChatService.stop();            if (mChatService.getState() == ChatState.STATE_NONE) {                mChatService.start();            }        }    }    /**     * 發送     *     * @param data     */    public void send(String data) {        if (mChatService.getState() == ChatState.STATE_CONNECTED) {            Log.i(TAG, "send data.getBytes()=" + data.getBytes());            mChatService.write(data.getBytes());        }    }    /**     * 配置監聽     *     * @param listener     */    public void setBluetoothChatListener(BluetoothChatListener listener) {        mBluetoothChatListener = listener;    }    /**     * 處理Handler接收的內容     */    @SuppressLint("HandlerLeak")    private final Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {                case ChatState.MESSAGE_WRITE:                    byte[] readBuf_write = (byte[]) msg.obj;                    Log.i(TAG, "MESSAGE_READ readBuf_write=" + readBuf_write);                    Log.i(TAG, "MESSAGE_READ readBuf_write.length=" + readBuf_write.length);                    Log.i(TAG, "MESSAGE_WRITE");                    break;                case ChatState.MESSAGE_READ:                    Log.i(TAG, "MESSAGE_READ");                    byte[] readBuf = (byte[]) msg.obj;                    String readMessage = new String(readBuf);                    Log.i(TAG, "MESSAGE_READ readBuf=" + readBuf);                    Log.i(TAG, "MESSAGE_READ readBuf.length=" + readBuf.length);                    Log.i(TAG, "MESSAGE_READ readMessage=" + readMessage);                    Log.i(TAG, "MESSAGE_READ readMessage.length=" + readMessage.length());                    if (readBuf != null && readBuf.length > 0) {                        if (mBluetoothChatListener != null) {                            Log.i(TAG, "MESSAGE_READ onDataReceived");                            mBluetoothChatListener.onDataReceived(readBuf, readMessage);                        }                    }                    break;                case ChatState.MESSAGE_DEVICE_INFO:                    mDeviceName = msg.getData().getString(ChatState.DEVICE_NAME);                    mDeviceAddress = msg.getData().getString(ChatState.DEVICE_ADDRESS);                    if (mBluetoothChatListener != null)                        mBluetoothChatListener.onDeviceConnected(mDeviceName, mDeviceAddress);                    Log.i(TAG, "MESSAGE_DEVICE_NAME" + mDeviceName);                    Log.i(TAG, "MESSAGE_DEVICE_NAME" + mDeviceAddress);                    isConnected = true;                    break;                case ChatState.MESSAGE_STATE_CHANGE:                    Log.i(TAG, "MESSAGE_STATE_CHANGE:" + msg.arg2 + "->" + msg.arg1);                    if (mBluetoothChatListener != null)                        mBluetoothChatListener.onServiceStateChanged(msg.arg2 + "->" + msg.arg1);                    if (isConnected && msg.arg1 != ChatState.STATE_CONNECTED) {                        if (mBluetoothChatListener != null)                            mBluetoothChatListener.onDeviceDisconnected();                        isConnected = false;                        mDeviceName = null;                        mDeviceAddress = null;                    }                    if (!isConnecting && msg.arg1 == ChatState.STATE_CONNECTING) {                        isConnecting = true;                    } else if (isConnecting) {                        if (msg.arg1 != ChatState.STATE_CONNECTED) {                            if (mBluetoothChatListener != null)                                mBluetoothChatListener.onDeviceConnectionFailed();                        }                        isConnecting = false;                    }                    break;            }        }    };}(3)配置藍牙聊天監聽接口回調供UI展示
public interface BluetoothChatListener {    /**     * 設備連接中     *     * @param name     * @param address     */    void onDeviceConnected(String name, String address);    /**     * 設備斷開連接     */    void onDeviceDisconnected();    /**     * 設備連接失敗     */    void onDeviceConnectionFailed();    /**     * 聊天狀態     *     * @param state     */    void onServiceStateChanged(String state);    /**     * 接收消息     *     * @param data     * @param message     */    void onDataReceived(byte[] data, String message);}

小結

剩余UI部分這里就不貼出來了,項目已經上傳至GitHub,項目包含經典藍牙與BLE以及ibeacon,請自行閱讀需要的模塊,經典藍牙模塊基本實現從藍牙配對到單聊的功能。

①關于配對在Android4.4以上(Android6.0(小米4)、Android5.1(魅藍2)/、Andro4id.4.4.2(vivo))測試可用且不彈配對框,但是在Android4.2.2(oppo)還是會彈配對框......

②聊天傳輸符號有個別不識別,在Android4.2.2(oppo)接收表情不識別......

以上便關于經典藍牙的主要內容,如果有任何不妥之處,還請各位指出。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 体育| 沙洋县| 调兵山市| 大丰市| 浪卡子县| 八宿县| 盈江县| 彭州市| 时尚| 汕头市| 尖扎县| 江口县| 新野县| 昌宁县| 赣榆县| 佛坪县| 晋城| 舒城县| 武平县| 余庆县| 含山县| 海盐县| 博罗县| 乐陵市| 衡阳市| 海南省| 连山| 玉林市| 淅川县| 安泽县| 于田县| 祁东县| 定结县| 龙口市| 南木林县| 方山县| 砀山县| 榆林市| 香港| 乌兰浩特市| 隆昌县|