中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

android藍牙簡單開發的方法是什么

發布時間:2021-12-08 15:14:02 來源:億速云 閱讀:153 作者:iii 欄目:開發技術

本篇內容介紹了“android藍牙簡單開發的方法是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

概述

前段時間學習了一些藍牙開發的知識,記錄一下Android中藍牙的簡單開發。下面是最重要的兩個類。

BluetoothAdapter : 藍牙適配器,通過getDefaultAdapter ()去獲取一個實例,如果設備不支持藍牙的話,返回的是一個null對象,通過它,可以打開、關閉藍牙,掃描設備、向指定設備創建socket通道…

BluetoothDevice : 代表一個設備對象,可以通過它獲取設備的名字、地址、類型等,也可以創建匹配,建立socket通道等等。

1、權限申請

<uses-permission android:name="android.permission.BLUETOOTH"/> 使用藍牙所需要的權限
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 使用掃描和設置藍牙的權限(申明這一個權限必須申明上面一個權限)

Android6以上版本,掃描其他藍牙還需要位置權限

// Android 9 以下版本
<user-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
// Android 9 以上
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

2、打開藍牙

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 如果設備不支持藍牙
if (mBluetoothAdapter == null){
    return;
}
// 設備支持藍牙功能,調用startActivityForResult去啟動藍牙
if (!mBluetoothAdapter.isEnabled()){
    startBlueTooth.launch(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));
}

打開藍牙功能是通過startActivity去啟動的,但是startActivity這個函數已經過期了,所以我使用官方推薦的Activity Result替代它

ActivityResultLauncher<Intent> startBlueTooth = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
            new ActivityResultCallback<ActivityResult>() {
                @Override
                public void onActivityResult(ActivityResult result) {
                    if (result==null){
                        Toast.makeText(BlueToothActivity.this, "open failed", Toast.LENGTH_SHORT).show();
                    }else {
                        if (result.getResultCode() == RESULT_CANCELED){
                            Toast.makeText(BlueToothActivity.this,"用戶取消",Toast.LENGTH_SHORT);
                        }
                    }
                }
            });

3、接收藍牙狀態的改變

通過廣播去接收藍牙狀態的改變

class BluetoothStateChangeReceiver extends BroadcastReceiver{
    public int DEFAULT_VALUE_BLUETOOTH = 1000;

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){
            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,DEFAULT_VALUE_BLUETOOTH);

            switch(state){
                case BluetoothAdapter.STATE_ON:
                    Log.d(TAG, "onReceive: open");
                    break;
                case BluetoothAdapter.STATE_OFF:
                    Log.d(TAG, "onReceive: off");
                    break;
                case BluetoothAdapter.STATE_TURNING_ON :
                    Log.d(TAG, "onReceive: 正在打開");
                    break;
                case BluetoothAdapter.STATE_TURNING_OFF:
                    Log.d(TAG, "onReceive: 正在關閉");
                    break;
            }
        }
    }
}

別忘了廣播的注冊和解注冊

IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
stateReceiver = new BluetoothStateChangeReceiver() ;
registerReceiver(stateReceiver,filter);

4、掃描其他的設備

同樣通過廣播接收,action是BluetoothDevice.ACTION_FOUND

class MyReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {

            String action = intent.getAction();

            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // 從intent對象中獲取藍牙設備的信息
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // 當發現新設備不存在于配對列表中時添加
                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                    blueNames.add(device.getName()+"\t"+device.getAddress());
                }
                blueAdpater.notifyDataSetChanged();
                Log.d(TAG, "onReceive: " + device.getName());
            }
        }
    }

動態注冊廣播

IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver,filter);

開啟掃描

mBluetoothAdapter.startDiscovery();

5、藍牙配對

public class BondReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())){
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                switch(device.getBondState()){
                    case BluetoothDevice.BOND_BONDED:
                        Log.d(TAG, "onReceive: 配對完成");
                        break;
                    case BluetoothDevice.BOND_BONDING:
                        Log.d(TAG, "onReceive: 正在配對");
                        break;
                    case BluetoothDevice.BOND_NONE:
                        Log.d(TAG, "onReceive: 取消配對");
                        break;
                }
            }
        }
    }

6、獲取已經配對的設備

已經配對的設備會被存儲起來,通過BluetoothAdpater直接獲取即可

Set<BluetoothDevice> paireDevices = mBluetoothAdapter.getBondedDevices();
if (paireDevices.size()>0){
                        for (BluetoothDevice pairedDevice : pairedDevices) {
                        blueNames.add(pairedDevice.getName()+"  "+pairedDevice.getAddress());
                        Log.d(TAG, "onClick: "+pairedDevice.getName());
                    }
}

7、連接設備

想要在兩臺設備之間創建連接,必須實現客戶端和服務端機制,他們之間使用套接字機制進行連接,服務端開放服務器套接字,客戶端通過MAC地址向服務端發起連接。客戶端和服務端以不同的方式獲得BluetoothSocket,當客戶端和服務端在同一個RFCOMM通道上分別擁有已連接的BluetoothSocket時,將他們視為彼此已經連接,于是每臺設備都獲得輸入和輸出流式傳輸,并開始傳輸數據。

連接技術

一種實現技術是自動將每臺設備準備為一個服務器,從而使每臺設備開放一個服務套接字并偵聽連接,在此情況下,任何一臺設備都可以發起與另一臺設備的連接并稱為客戶端。

服務器

設置服務器套接字并接受連接,步驟依次如下

1、調用listenUsingRfcommWithServiceRecord()獲取一個BluetoothServerSocket, 該函數需要兩個參數,第一個是服務器的名稱,自己取一個即可,第二個是UUID,用來對信息做唯一性標識,我們可以從網上眾多UUID生成器中隨機的生成一個,然后使用UUID.fromString(String)初始化一個UUID。

2、通過accept()函數開始偵聽連接請求

只有遠程設備發送的連接請求中UUID與使用此套接字注冊的UUID相匹配時服務器才會接受請求,accept函數會返回已連接的BluetoothSocket

3、連接成功后調用close()關閉BluetoothSocket

 private class AcceptThread extends Thread{

        private final BluetoothServerSocket mmServerSocket;
        private String mSocketType;

        public AcceptThread(boolean secure){
            BluetoothServerSocket tmp = null;
            mSocketType = secure ? "secure" : "Insercure";
            try{
                if (secure){
                    tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,MY_UUID_SECURE);
                }else{
                    tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME_INSECURE,MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG,"socket type"+ mSocketType + "listen() failed",e);
            }

            mmServerSocket = tmp;
        }

        @Override
        public void run() {
            Log.d(TAG, "Socket Type: " + mSocketType +
                    "BEGIN mAcceptThread" + this);
            setName("AcceptThread"+ mSocketType);

            BluetoothSocket socket = null;
            Log.d(TAG, "run: 開始監聽");
            while (true){
                try{
                    socket = mmServerSocket.accept();
                    Log.d("acceptThread", "run: 連接成功");
                    connected(socket,socket.getRemoteDevice(),mSocketType);
                } catch (IOException e) {
                    Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
                    break;
                }

            }
            Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);
        }

        public void cancel() {
            Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
            }
        }
    }

上面的secure和Insecure只是使用了不同的UUID而已。

客戶端

遠程設備開啟監聽后,我們就發起向此設備的連接,首先必須先獲得遠程設備的BluetoothDevice對象,然后獲取BluetoothSocket發起連接。

基本步驟如下

1、使用BluetoothDevice通過調用createRfcommSocketToServiceRecord(UUID) 獲取 BluetoothSocket

2、通過connect發起連接

private class ConnectThread extends Thread{
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
        private String mSocketType;

        public ConnectThread(BluetoothDevice device, boolean secure){
            mmDevice = device;
            BluetoothSocket tmp = null;
            mSocketType = secure ? "Secure" : "Insecure";
            try {
                if (secure){
                    tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
                }else {
                    tmp = device.createRfcommSocketToServiceRecord(MY_UUID_INSECURE);
                }
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
            }
            mmSocket = tmp;
        }

        @Override
        public void run() {
            Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
            setName("ConnectThred"+mSocketType);

            // 總是取消發現,因為它會減慢連接
            bluetoothAdapter.cancelDiscovery();
            // connect
            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                mmSocket.connect();
                Log.d(TAG, "run: socket連接成功");
            } catch (IOException e) {
                // Close the socket
                Log.d(TAG, "run: 關閉socket");
                try {
                    mmSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() " + mSocketType +
                            " socket during connection failure", e2);
                }

                return;
            }

            connected(mmSocket,mmDevice,mSocketType);
        }

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

    }

發送數據

連接成功后,我們就可以通過socket發送數據了,客戶端的Socket對象是BluetoothSocket, 服務端的socket是BluetoothServerSocket,特別注意不要混淆了。使用getInputStreamgetOutputStream分別獲取通過套接字處理數據傳輸的InputStreamOutputStream。寫數據比較簡單,但是讀數據就需要一個單獨的線程一直監聽才行。

private class ConnectedThread extends Thread{
        private final BluetoothSocket mmSocket;
        private InputStream mmInStream;
        private OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket, String socketType) throws IOException {
            Log.d(TAG, "create ConnectedThread: " + socketType);
            mmSocket = socket;

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try{
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();

                if (socket != null){
                    tmpOut.write(new String("hello").getBytes());
                    Log.d(TAG, "ConnectedThread: socket不是null");
                }
            } catch (IOException e) {
                Log.e(TAG,"temp socket not created", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;

            // mmOutStream.write(new String("hello").getBytes());
        }

        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
        @Override
        public void run() {
            Log.i(TAG, "BEGIN mConnectedThread");
            byte[] buffer = new byte[1024];
            int bytes;

            while (true){
                try{
                    bytes = mmInStream.read(buffer);
                    // send the bytes to the ui Activity
                    String text = encodeByteToString(buffer,bytes);
                    Log.d(TAG, "run: 收到消息:"+ text);
                    chatItems.add(text);
                    mHandler.sendMessage(mHandler.obtainMessage());
                } catch (IOException e) {
                    Log.d(TAG, "run: 沒有收到消息");
                    e.printStackTrace();
                    break;
                }
            }
        }

        public String encodeByteToString(byte[] data,int length) {
            byte[] temp = new byte[length];
            for (int i = 0; i < length; i++) {
                temp[i] = data[i];
            }
            try {
                return new String(temp,"utf-8");
            } catch (UnsupportedEncodingException e) {
                return "";
            }
        }


        public void write(byte[] buffer){
            try{
                mmOutStream.write(buffer);

                // mHandler.obtainMessage(Constants.MESSAGE_WRITE,-1,-1,buffer).sendToTarget();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

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

“android藍牙簡單開發的方法是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

彩票| 辽阳市| 定南县| 河东区| 呼和浩特市| 屯昌县| 佛山市| 图们市| 任丘市| 聂荣县| 张掖市| 高淳县| 西畴县| 稷山县| 贡山| 莒南县| 正阳县| 天气| 三门县| 老河口市| 阳新县| 平邑县| 邢台县| 克山县| 崇阳县| 保康县| 郸城县| 辰溪县| 恩施市| 仙桃市| 无锡市| 定远县| 关岭| 宜良县| 青海省| 玉田县| 三河市| 平塘县| 遂宁市| 霍州市| 札达县|