簡體   English   中英

連接到 BLE 設備

[英]Connect to BLE device

所以我制作了這個應用程序,在那里我可以找到所有帶有名稱的 BLE 設備。 但是,如何使特定字段之一可點擊並自動連接到設備,以便我可以開始寫入/讀取?

適配器

public class ListAdapter_BTLE_Devices extends ArrayAdapter<BTLE_Device> {

    Activity activity;
    int layoutResourceID;
    ArrayList<BTLE_Device> devices;

    public ListAdapter_BTLE_Devices(Activity activity, int resource, ArrayList<BTLE_Device> objects) {
        super(activity.getApplicationContext(), resource, objects);
        this.activity = activity;
        layoutResourceID = resource;
        devices = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            LayoutInflater inflater =
                    (LayoutInflater) activity.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(layoutResourceID, parent, false);
        }

        BTLE_Device device = devices.get(position);
        String name = device.getName();
        String address = device.getAddress();
        int rssi = device.getRSSI();

        TextView BLE_name = (TextView) convertView.findViewById(R.id.BLE_name);
        if (name != null && name.length() > 0) {
            BLE_name.setText(device.getName());
        }
        else {
            BLE_name.setText("No Name");
        }

        TextView BLE_rssi = (TextView) convertView.findViewById(R.id.BLE_rssi);
        BLE_rssi.setText("RSSI: " + Integer.toString(rssi));

        TextView BLE_macaddr = (TextView) convertView.findViewById(R.id.BLE_macaddr);
        if (address != null && address.length() > 0) {
            BLE_macaddr.setText("MAC-addr: "+device.getAddress());
        }
        else {
            BLE_macaddr.setText("No Address");
        }

        return convertView;
    }
}

編輯

我想我現在可能已經連接到 GATT,所以我所做的是..首先我從Mainactivity 中獲取 MAC-addr,然后我將它保存在一個意圖中,並在點擊時啟動另一個活動。 在這里我做了以下DeviceAddress = intent.getStringExtra(MainActivity.EXTRAS_BLE_ADDRESS);

BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(DeviceAddress);

device.connectGatt(this, false, mGattCallback);

當我調用 connectGatt 時,它會打印消息Log.d(TAG, "Connection State: 1"); ,這是正確的做法嗎?


private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.d(TAG, "Connection State Change: "+status+" -> "+connectionState(newState));
            if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
                /*
                 * Once successfully connected, we must next discover all the services on the
                 * device before we can read and write their characteristics.
                 */
                Log.d(TAG, "Connection State: 1");
                gatt.discoverServices();
            } else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED) {
                /*
                 * If at any point we disconnect, send a message to clear the weather values
                 * out of the UI
                 */
                Log.d(TAG, "Connection State: 2");
            } else if (status != BluetoothGatt.GATT_SUCCESS) {
                /*
                 * If there is a failure at any stage, simply disconnect
                 */
                Log.d(TAG, "Connection State: 3");
                gatt.disconnect();
            }
        }

要首先連接到設備,您必須執行 BLE 掃描(如果您使用啟動代碼)運行回調並將其添加到找到的設備列表中。

添加過濾器以僅允許您正在尋找的設置設備。 當 BLE 通告一個最多 31 字節的數據包時,您應該在這里有一些數據來識別您的設備,例如制造商 ID 或數據等。或者,如果您正在處理一個簡單的項目,您可以在設備地址中以編程方式硬編碼。

然后,當從掃描中發現此設備時,您可以停止 BLE 掃描並自動將連接請求排隊。 這將要求發出 GATT 請求,從而授予您訪問 GATT 服務以及設備特性的權限。

如果你有藍牙 LE 的問題,我建議你使用我的藍牙 le 庫(不要重新發明輪子,我花了大約 3/4 個月來制作這個庫,藍牙 le 通信真的很難制作),它是開源的,所以你也可以看到有實現示例的代碼,我鏈接你github頁面: https : //github.com/niedev/BluetoothCommunicator

要在項目中使用該庫,您必須將 jitpack.io 添加到您的根 build.gradle(項目):

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

然后將最新版本的 BluetoothCommunicator 添加到您的應用 build.gradle

dependencies {
        implementation 'com.github.niedev:BluetoothCommunicator:1.0.6'
}

要使用此庫,請將這些權限添加到您的清單中:

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

然后將 android:largeHeap="true" 添加到清單中的應用程序標簽:
例子

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

<application
    android:name="com.bluetooth.communicatorexample.Global"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:largeHeap="true"
    android:theme="@style/Theme.Speech">
    <activity android:name="com.bluetooth.communicatorexample.MainActivity"
        android:configChanges="orientation|screenSize">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

一旦你下載了庫並設置了清單,你需要創建一個藍牙通信器對象,它是處理藍牙低功耗庫所有操作的對象,如果你想在多個活動中管理藍牙連接我建議你保存此對象作為自定義類的屬性,擴展 Application 並創建 getter,以便您可以從任何活動或服務訪問 bluetoothCommunicator:

((custom class name) getApplication()).getBluetoothCommunicator();

下一步是初始化bluetoothCommunicator,參數是:一個上下文,其他設備將看到我們的名稱(限制為18個字符,並且只能是BluetoothTools.getSupportedUTFCharacters(context)中列出的字符,因為廣告信標的字節數是有限的)和策略(目前唯一支持的策略是 BluetoothCommunicator.STRATEGY_P2P_WITH_RECONNECTION)

bluetoothCommunicator = new BluetoothCommunicator(this, "device name", BluetoothCommunicator.STRATEGY_P2P_WITH_RECONNECTION);

然后添加藍牙通訊器回調,回調會監聽藍牙通訊器的所有事件:

bluetoothCommunicator.addCallback(new BluetoothCommunicator.Callback() {
    @Override
    public void onBluetoothLeNotSupported() {
        super.onBluetoothLeNotSupported();
        
        Notify that bluetooth low energy is not compatible with this device
    }
   
    @Override
    public void onAdvertiseStarted() {
        super.onAdvertiseStarted();

        Notify that advertise has started, if you want to do something after the start of advertising do it here, because
        after startAdvertise there is no guarantee that advertise is really started (it is delayed)
    }

    @Override
    public void onDiscoveryStarted() {
        super.onDiscoveryStarted();

        Notify that discovery has started, if you want to do something after the start of discovery do it here, because
        after startDiscovery there is no guarantee that discovery is really started (it is delayed)
    }

    @Override
    public void onAdvertiseStopped() {
        super.onAdvertiseStopped();

        Notify that advertise has stopped, if you want to do something after the stop of advertising do it here, because
        after stopAdvertising there is no guarantee that advertise is really stopped (it is delayed)
    }

    @Override
    public void onDiscoveryStopped() {
        super.onDiscoveryStopped();

        Notify that discovery has stopped, if you want to do something after the stop of discovery do it here, because
        after stopDiscovery there is no guarantee that discovery is really stopped (it is delayed)
    }

    @Override
    public void onPeerFound(Peer peer) {
        super.onPeerFound(peer);
        
        Here for example you can save peer in a list or anywhere you want and when the user
        choose a peer you can call bluetoothCommunicator.connect(peer founded) but if you want to
        use a peer for connect you have to have peer updated (see onPeerUpdated or onPeerLost), if you use a
        non updated peer the connection might fail
        instead if you want to immediate connect where peer is found you can call bluetoothCommunicator.connect(peer) here
    }

    @Override
    public void onPeerLost(Peer peer){
        super.onPeerLost(peer);
        
        It means that a peer is out of range or has interrupted the advertise,
        here you can delete the peer lost from a eventual collection of founded peers
    }

    @Override
    public void onPeerUpdated(Peer peer,Peer newPeer){
        super.onPeerUpdated(peer,newPeer);

        It means that a founded peer (or connected peer) has changed (name or address or other things),
        if you have a collection of founded peers, you need to replace peer with newPeer if you want to connect successfully to that peer.

        In case the peer updated is connected and you have saved connected peers you have to update the peer if you want to successfully
        send a message or a disconnection request to that peer.
    }

    @Override
    public void onConnectionRequest(Peer peer){
        super.onConnectionRequest(peer);

        It means you have received a connection request from another device (peer) (that have called connect)
        for accept the connection request and start connection call bluetoothCommunicator.acceptConnection(peer);
        for refusing call bluetoothCommunicator.rejectConnection(peer); (the peer must be the peer argument of onConnectionRequest)
    }

    @Override
    public void onConnectionSuccess(Peer peer,int source){
        super.onConnectionSuccess(peer,source);

        This means that you have accepted the connection request using acceptConnection or the other
        device has accepted your connection request and the connection is complete, from now on you
        can send messages or data (or disconnection request) to this peer until onDisconnected

        To send messages to all connected peers you need to create a message with a context, a header, represented by a single character string
        (you can use a header to distinguish between different types of messages, or you can ignore it and use a random
        character), the text of the message, or a series of bytes if you want to send any kind of data and the peer you want to send the message to
        (must be connected to avoid errors), example: new Message(context,"a","hello world",peer);
        If you want to send message to a specific peer you have to set the sender of the message with the corresponding peer.

        To send disconnection request to connected peer you need to call bluetoothCommunicator.disconnect(peer);
    }

    @Override
    public void onConnectionFailed(Peer peer,int errorCode){
        super.onConnectionFailed(peer,errorCode);

        This means that your connection request is rejected or has other problems,
        to know the cause of the failure see errorCode (BluetoothCommunicator.CONNECTION_REJECTED
        means rejected connection and BluetoothCommunicator.ERROR means generic error)
    }

    @Override
    public void onConnectionLost(Peer peer){
        super.onConnectionLost(peer);

        This means that a connected peer has lost the connection with you and the library is trying
        to restore it, in this case you can update the gui to notify this problem.

        You can still send messages in this situation, all sent messages are put in a queue
        and sent as soon as the connection is restored
    }

    @Override
    public void onConnectionResumed(Peer peer){
        super.onConnectionResumed(peer);
        
        Means that connection lost is resumed successfully
    }

    @Override
    public void onMessageReceived(Message message,int source){
        super.onMessageReceived(message,source);

        Means that you have received a message containing TEXT, for know the sender you can call message.getSender() that return
        the peer that have sent the message, you can ignore source, it indicate only if you have received the message
        as client or as server
    }

    @Override
    public void onDataReceived(Message data,int source){
        super.onDataReceived(data,source);

        Means that you have received a message containing DATA, for know the sender you can call message.getSender() that return
        the peer that have sent the message, you can ignore source, it indicate only if you have received the message
        as client or as server
    }

    @Override
    public void onDisconnected(Peer peer,int peersLeft){
        super.onDisconnected(peer,peersLeft);

        Means that the peer is disconnected, peersLeft indicate the number of connected peers remained
    }

    @Override
    public void onDisconnectionFailed(){
        super.onDisconnectionFailed();

        Means that a disconnection is failed, super.onDisconnectionFailed will reactivate bluetooth for forcing disconnection
        (however the disconnection will be notified in onDisconnection)
    }
});

最后,您可以開始發現和/或廣告:

bluetoothCommunicator.startAdvertising();
bluetoothCommunicator.startDiscovery();

所有其他可以做的動作都用我之前寫的回調代碼中的注釋來解釋。

您可以向您的持有人添加一個視圖並為其設置一個點擊偵聽器。 視圖可以是圍繞您的顯示卡(或您使用的任何東西)的透明矩形。

我建議這個深度閱讀關於BLE使用。 在單擊偵聽器上,您可以將連接請求排隊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM