国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android藍牙BLE開發(fā)

這篇具有很好參考價值的文章主要介紹了Android藍牙BLE開發(fā)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

最近正在研究Android的藍牙BLE開發(fā)學習,以下是自己做的個人總結

1.1何為BLE?

首先得說明什么是低功耗藍牙BLE,BLE的全稱為Bluetooth low energy(或稱Blooth LE,BLE),從英文全稱便可以知曉其是一種低功耗的藍牙技術,是藍牙技術聯(lián)盟設計和銷售的一種個人局域網(wǎng)技術,旨在用于醫(yī)療保健、運動健身、信標、安防、家庭娛樂等領域的新興應用。相較經(jīng)典藍牙,低功耗藍牙旨在保持同等通信范圍的同時顯著降低功耗和成本。而正因為其低功耗的優(yōu)點,可以讓Android APP可以具有與低功耗要求的BLE設備通信,如近距離傳感器、心臟速率監(jiān)視器、健身設備等

1.2基礎術語和概念

在正式開發(fā)前,要對基本的藍牙的術語和概念要有個大致的認識,因為我本人學習的也不長,就是個簡單的總結先:

Generic Attribute Profile:簡稱為GATT,現(xiàn)在的低功耗BLE的連接都是建立在GATT協(xié)議之上實現(xiàn)的,藍牙技術聯(lián)盟規(guī)定了許多低功耗設備的配置文件,配置文件是設備如何在特定的應用程序在工作的規(guī)格,而一個設備中可以有多個配置文件。
Generic Access Profile:Profile可以視為一種規(guī)范,一個標準的通信協(xié)議,它存在于從機中,藍牙技術聯(lián)盟規(guī)定了一些標準的profile,例如防丟器 ,心率計等。每個profile中會包含多個service,每個service代表從機的一種能力。
Service:服務,在BLE從機中,可以有多個服務,例如:電量信息服務,而Service中又有多個Characteristic特征值,而每個具體的特征值才是BLE通信的重點,例如在1電量信息服務中,當前的電量為80%,所以會通過電量的特征值存在從機的profile里,這樣主機就可以通過這個特征值來讀取80%這個數(shù)據(jù)
Characteristic:特征值,ble主從機通信都是通過特征值實現(xiàn)的,類似于標簽key,可以通過這個key值來獲取信息和數(shù)據(jù)
UUID:統(tǒng)一識別碼,服務和特征值都需要一個唯一的UUID來標識整理,而每個從機都會有一個叫做profile的東西存在,不管是上面的自定義的simpleprofile,還是標準的防丟器profile,他們都是由一些列service組成,然后每個service又包含了多個characteristic,主機和從機之間的通信,均是通過characteristic來實現(xiàn)。

1.3初始化配置

講完了大概的概念之后便是基本的操作了,以下內(nèi)容會結合代碼和流程圖進行展示

Android藍牙BLE開發(fā)

1.3.1權限

想要使用BLE開發(fā),就得先獲得藍牙必要的權限,需要先在AndroidManifest.xml中設置權限

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

如果想聲明你的app只為具有BLE的設備提供,在manifest文件中包括:

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

除此之外,如果是Android 6.0以上的手機僅僅是添加以上的藍牙權限是不足的,這樣會造成無法掃描到其他設備,因而還需要添加位置權限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-feature android:name="android.hardware.location.gps" />

1.3.2是否支持藍牙BLE

required=true只能是讓支持BLE的Android設備上安裝運行,不支持的則不行,如果想在Java實現(xiàn)上述功能,可以通過下述代碼:

// 手機硬件支持藍牙
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
    Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
    finish();
}

1.3.3初始化藍牙適配器

所有的藍牙活動都需要藍牙適配器,BluetoothAdapter代表設備本身的藍牙適配器。整個系統(tǒng)只有一個藍牙適配器,而且app需要藍牙適配器與系統(tǒng)交互。下面的代碼片段顯示了如何得到適配器。

注意該方法使用getSystemService()返回BluetoothManager,然后將其用于獲取適配器的一個實例。Android 4.3(API 18)引入BluetoothManager

final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
else
    mBluetoothAdapter = bluetoothManager.getAdapter();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();

1.3.4開啟藍牙

要操作藍牙,必須先在設備中開啟藍牙。如果當前未啟用藍牙,則可以通過觸發(fā)一個Intent調(diào)用系統(tǒng)顯示一個對話框來要求用戶啟用藍牙權限

// 打開藍牙權限
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(
        BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

1.3.5初始化ListView列表適配器

/**
  * @Description: TODO<自定義適配器Adapter,作為listview的適配器>
  */
private class LeDeviceListAdapter extends BaseAdapter {
    private ArrayList<BluetoothMessage> mLeDevices;
    
    private LayoutInflater mInflator;
    
    public LeDeviceListAdapter()
    {
        super();
        //rssis = new ArrayList<Integer>();
        mLeDevices = new ArrayList<BluetoothMessage>();
        mInflator = getLayoutInflater();
     }
    public void addDevice(BluetoothMessage device)
    {
        for (BluetoothMessage mLeDevice : mLeDevices) {
            
            if(mLeDevice.getDevice().getAddress().equals(device.getDevice().getAddress())){
                return;    
            }    
        }    
        mLeDevices.add(device);
        //rssis.add(rssi);
    }
    public BluetoothMessage getDevice(int position)
    {
    	return mLeDevices.get(position);
    }
    public void clear()
    {
        mLeDevices.clear();
        //rssis.clear();
    }
    @Override
    public int getCount()
    {
    	return mLeDevices.size();
    }
	@Override
    public Object getItem(int i)
    {
        return mLeDevices.get(i);
    }
    @Override
    public long getItemId(int i)
    {
        return i;
    }

    /**  
      * 重寫getview
      *
      * **/
   @Override
    public View getView(int i, View view, ViewGroup viewGroup)
    {
        // General ListView optimization code.
        // 加載listview每一項的視圖
        BluetoothMessage bluetoothMessage = mLeDevices.get(i);
        return view;
    }
}

1.3.6發(fā)現(xiàn)BLE設備(掃描設備)

如果要發(fā)現(xiàn)BLE設備,使用startLeScan()方法進行掃描,掃描的話就要傳入true執(zhí)行scanLeDvice(true)方法,然后藍牙適配器就調(diào)用startLeScan()方法進行掃描,LeScanCallback是掃描回調(diào),也就是返回掃描結果。

1.3.6.1掃描結果:

private void scanLeDevice(final boolean enable) {
    if (mBluetoothAdapter == null){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        else {
            BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();
        }
  	}
    if (mBluetoothLeScanner == null){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
        }
    if (enable) {
        // Stops scanning after a pre-defined scan period.
        mHandler.postDelayed(new Runnable()
        {
            @Override
            public void run()
            {
                mScanning = false;
                scan_flag = true;
                scan_btn.setText("掃描設備");
                Log.i("SCAN", "stop.....................");
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                    mBluetoothLeScanner.stopScan(mScanCallback);
                else
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
             }
         }, SCAN_PERIOD);
         /* 開始掃描藍牙設備,帶mLeScanCallback 回調(diào)函數(shù) */
            Log.i("SCAN", "begin.....................");
            mScanning = true;
            scan_flag = false;
            scan_btn.setText("停止掃描");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                mBluetoothLeScanner.startScan(mScanCallback);
            else
                mBluetoothAdapter.startLeScan(mLeScanCallback);
     } else {
            Log.i("Stop", "stoping................");
            mScanning = false;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                mBluetoothLeScanner.stopScan(mScanCallback);
            else
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            scan_flag = true;
      }
}

1.3.6.2回調(diào)方法:

在這里回家上面的掃描方法的掃描結果回調(diào),也就是傳回來。其中在onLeScan方法是重點,藍牙掃描成功后的結果會返回此方法中,然后就可以處理BluetoothDevice拿到設備信息,最后展示到前面初始化的ListView列表中:

  • 第一個參數(shù)device,表示一個遠程藍牙設備,里面有它獨有的藍牙地址Address和Name等,所以后續(xù)需要進行連接藍牙操作也需要用到這里獲取的藍牙Address
  • 第二個參數(shù)rssi表示掃描到的設備信號強度,這里應該可以用來判斷距離的遠近。
  • 第三個參數(shù)scanRecord表示遠程設備提供的廣告記錄的內(nèi)容。
// 這個是官方demo的源碼
// 是掃描的Callback的回調(diào),其中的onLeScan方法,藍牙掃描成功之后會將結果會返回此方法中
// 然后就可以處理BluetoothDevice拿到設備信息 最后展示到前面初始化的listview列表中
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback()
{
    @Override
    public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord)
    {
        // TODO Auto-generated method stub
	    runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                // 講掃描到設備的信息輸出到listview的適配器
                BluetoothMessage bluetoothMessage = new BluetoothMessage(device);
                mleDeviceListAdapter.addDevice(bluetoothMessage);
                mleDeviceListAdapter.notifyDataSetChanged();
             }
         });
    }
};

至此已經(jīng)完成初始化配置、一些設備的判斷邏輯和掃描操作了,如果能成功地掃描到設備并展示到界面上的話,下一步如果用戶點擊了列表,將進行藍牙連接和相關的讀寫操作!

1.4創(chuàng)建BluetoothLeService服務類并初始化藍牙連接

創(chuàng)建了一個BluetoothLeService服務類并繼承了Service,用來完成藍牙設備的初始化、連接、斷開連接、讀取特征值、寫入特征值、設置特征值變化通知以及獲取已連接藍牙的所有服務等操作

1.4.1創(chuàng)建服務

首先,我們得進行第一步,在onCreate()方法中,執(zhí)行bindService開啟一個服務

這里因為是項目需要,使用了一個虛擬按鈕來進行初始化的連接

//藍牙service,負責后臺的藍牙服務
private static BluetoothLeService mBluetoothLeService;
Intent gattServiceIntent;
/**
     * --------------------------------------------onCreate方法-----------------------------------------------------
     */
@Override
public void onCreate(Bundle savedInstanceState)
{
    ...
        /* 啟動藍牙service */
        gattServiceIntent = new Intent(this, BluetoothLeService.class);
    //模擬按鍵點擊事件觸發(fā)藍牙連接
    rev_tv.post(new Runnable() {
        @Override
        public void run() {
            scan_btn.performClick();
        }
    });

    //監(jiān)聽scan_btn
    scan_btn.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            if (scan_flag)
            {
                mleDeviceListAdapter = new LeDeviceListAdapter();
                //lv.setAdapter(mleDeviceListAdapter);
                scanLeDevice(true);
            } else {
                scanLeDevice(false);
                scan_btn.setText("掃描設備");
            }
            if (mScanning) {
                /* 停止掃描設備 */
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
                    mBluetoothLeScanner.stopScan(mScanCallback);
                else
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                mScanning = false;
            }
            bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
        }
    });
    ...
}

開啟服務成功后,便會一樣進行服務回調(diào),當服務回調(diào)已經(jīng)成功連接時,便會獲取一個BlueToohtLeService的實例,接著就執(zhí)行藍牙連接操作:

/* BluetoothLeService綁定的回調(diào)函數(shù) */
// 獲取BluetoothLeService的實例,進行藍牙連接操作
// 以下都是Android官方的demo源碼
private final ServiceConnection mServiceConnection = new ServiceConnection()
{

    @Override
    public void onServiceConnected(ComponentName componentName,
                                   IBinder service)
    {
        mBluetoothLeService = ((BluetoothLeService.LocalBinder) service)
            .getService();
        if (!mBluetoothLeService.initialize())
        {
            //Log.e(TAG, "Unable to initialize Bluetooth");
            finish();
        }
        mBluetoothLeService.connect(mDeviceAddress);
    }
    @Override
    public void onServiceDisconnected(ComponentName componentName)
    {
        mBluetoothLeService = null;
    }
};

這個時候,需要單獨創(chuàng)建一個BlueToothService類,因為BlueToohtLeService類既然是服務類,那它父類肯定是繼承于Service

public class BluetoothLeService extends Service {
	...
}

這里的BlueToothService類是BindService服務,用于綁定一個服務。這樣當bindService(intent,conn,flags)后,就會綁定一個服務。這樣做可以獲得這個服務對象本身,而用StartService(intent)的方法只能啟動服務。

BindService方法的一般過程:

1.4.1.1開啟BindService服務

// bindService區(qū)別于startService,用于綁定服務,可以獲得這個服務對象本身
public class LocalBinder extends Binder {
    public BluetoothLeService getService()
    {
        return BluetoothLeService.this;
    }
}
// onBind()是使用bindService開啟的服務才會有回調(diào)的一個方法
// onBind()方法給MainActivity返回了BluetoothLeService實例
// 用于方便MainActivity后續(xù)的連接和讀寫操作
@Override
public IBinder onBind(Intent intent)
{
    return mBinder;
}

1.4.1.2關閉BindService,關閉藍牙

當服務調(diào)用unbindService時,服務的生命周期將會進入onUnbind()方法,接著執(zhí)行了關閉藍牙的方法

@Override
public boolean onUnbind(Intent intent)
{
    close();
    return super.onUnbind(intent);
}

private final IBinder mBinder = new LocalBinder();

1.4.2初始化藍牙

這個方法是BlueToohtLeService服務類創(chuàng)建之后在MainActivity通過拿到BlueToohtLeService實例調(diào)用的,也是官方的源碼

/* service 中藍牙初始化 */
public boolean initialize()
{
    // For API level 18 and above, get a reference to BluetoothAdapter
    // through
    // BluetoothManager.
    if (mBluetoothManager == null)
    {   //獲取系統(tǒng)的藍牙管理器
        //使用 getSystemService(java.lang.String)與 BLUETOOTH_SERVICE創(chuàng)建一個 BluetoothManager
        // 然后調(diào)用 getAdapter()以獲得 BluetoothAdapter
        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        if (mBluetoothManager == null)
        {
            Log.e(TAG, "Unable to initialize BluetoothManager.");
            return false;
        }
    }

    //BluetoothManager 的變量調(diào)用 getAdapter()以獲得 BluetoothAdapter 進而對整體藍牙進行管理
    mBluetoothAdapter = mBluetoothManager.getAdapter();
    if (mBluetoothAdapter == null)
    {
        Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
        return false;
    }

    return true;
}

1.4.3執(zhí)行connect()和connectGatt

connect()和connectGatt都是連接BLE設備的方法,但二者用法不同

connectGatt是BluetoothDevice類下的方法,功能是向BLE設備發(fā)起連接,然后得到一個BluetoothGatt類型的返回值,利用這個返回值可以進行下一步操作。

connect是BluetoothGatt類下的方法,功能是重新連接。如果BLE設備和APP已經(jīng)連接過,但是因為設備超出了藍牙的連接范圍而斷掉,那么當設備重新回到連接范圍內(nèi)時,可以通過connect()重新連接

// 連接遠程藍牙
    public boolean connect(final String address)
    {
        // 適配器為空或者地址為空就會提示
        if (mBluetoothAdapter == null || address == null)
        {
            Log.w(TAG,
                    "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }

        // Previously connected device. Try to reconnect.
        if (mBluetoothDeviceAddress != null
                && address.equals(mBluetoothDeviceAddress)
                && mBluetoothGatt != null)
        {
            Log.d(TAG,
                    "Trying to use an existing mBluetoothGatt for connection.");
            //mBluetoothGatt.connect()表示連接回遠程設備
            //在連接斷開后,此方法的功能在于“重新連接到遠程設備”
            //如果設備曾經(jīng)連接過,但目前不在范圍內(nèi)
            //則一旦設備回到范圍內(nèi),則可以通過connect重新連接。
            if (mBluetoothGatt.connect())//連接藍牙,其實就是調(diào)用BluetoothGatt的連接方法
            {
                mConnectionState = STATE_CONNECTING;
                return true;
            } else
            {
                return false;
            }
        }
        /* 獲取遠端的藍牙設備 */
        //mBluetoothAdapter.getRemoteDevice
        //藍牙適配器通過調(diào)用getRemoteDevice()方法獲取給定的藍牙硬件地址的BluetoothDevice對象
        //有效的藍牙地址必須是6個字節(jié),即使沒有找到設備,也得返回有效的6個字節(jié),當然,估計就是6個0
        final BluetoothDevice device = mBluetoothAdapter
                .getRemoteDevice(address);
        if (device == null)
        {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        // We want to directly connect to the device, so we are setting the
        // autoConnect
        // parameter to false.
        /* 調(diào)用device中的connectGatt連接到遠程設備 */
        //connectGatt是BluetoothDevice類下的方法
        //功能是向BLE設備發(fā)起連接,然后得到一個BluetoothGatt類型的返回值,利用這個返回值可以進行下一步操作
        //connectGatt方法往往是和BluetoothGatt類的connect方法一起使用
        //兩個方法的運行邏輯是:
        //先使用connectGatt方法發(fā)起連接,連接狀態(tài)的改變會回調(diào)callback對象中的onConnectionStateChange
        // (需要自己定義一個BluetoothGattCallBack對象并重寫onConnectionStateChange)
        // 并返回一個BluetoothGatt對象,這時BluetoothGatt已經(jīng)實例化,下一次連接可以調(diào)用connect重新連接。
        mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
        Log.d(TAG, "Trying to create a new connection.");
        mBluetoothDeviceAddress = address;
        mConnectionState = STATE_CONNECTING;
        System.out.println("device.getBondState==" + device.getBondState());
        return true;
    }

取消連接

/**
     * @Title: disconnect
     * @Description: TODO(取消藍牙連接)
     * @return void
     * @throws
     */
public void disconnect()
{
    if (mBluetoothAdapter == null || mBluetoothGatt == null)
    {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    mBluetoothGatt.disconnect();

}

1.4.4 BluetoothGattCallback 回調(diào)

這個回調(diào)十分重要,主要對BluetoothGatt的藍牙連接、斷開、讀、寫、特征值變化等的回調(diào)監(jiān)聽,然后我們可以將這些回調(diào)信息通過廣播機制傳播回給廣播監(jiān)聽器

/* 連接遠程設備的回調(diào)函數(shù) */
// BluetoothGattCallback是一個抽象類,目的是用于實現(xiàn) BluetoothGatt的回調(diào)
// 用于將結果傳遞給用戶,例如連接狀態(tài)等,以及任何進一步對GATT客戶端的操作
// 因為BluetoothGattCallback是一個抽象類,因此需要對里面的方法進行重寫
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
{
    // 連接狀態(tài)變化時回調(diào),用來檢測藍牙是否連接成功與否,成功失敗兩種情況的操作在這里設置
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                        int newState)
    {
        String intentAction;
        if (newState == BluetoothProfile.STATE_CONNECTED)//連接成功
        {   // 連接成功后的操作
            intentAction = ACTION_GATT_CONNECTED;   // 連接外設成功(GATT服務端)
            mConnectionState = STATE_CONNECTED;     // 設備連接完畢
            /* 通過廣播更新連接狀態(tài) */
            broadcastUpdate(intentAction);          // 廣播更新,查看是否有數(shù)據(jù)更新
            Log.i(TAG, "Connected to GATT server.");
            // Attempts to discover services after successful connection.
            Log.i(TAG, "Attempting to start service discovery:"
                  + mBluetoothGatt.discoverServices());

        } else if (newState == BluetoothProfile.STATE_DISCONNECTED)//連接失敗
        {   //連接失敗后的操作
            intentAction = ACTION_GATT_DISCONNECTED;// 連接外設失?。℅ATT服務端)
            mConnectionState = STATE_DISCONNECTED;  // 設備無法連接
            Log.i(TAG, "Disconnected from GATT server.");
            broadcastUpdate(intentAction);
        }
    }
    /*
         * 重寫onServicesDiscovered,發(fā)現(xiàn)藍牙服務 會在藍牙連接的時候調(diào)用
         *
         * */
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status)
    {   // GATT_SUCCESS表示GATT操作完成
        if (status == BluetoothGatt.GATT_SUCCESS)//發(fā)現(xiàn)藍牙服務成功
        {
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            Log.i(TAG, "--onServicesDiscovered called--");
        } else
        {
            Log.w(TAG, "onServicesDiscovered received: " + status);
            System.out.println("onServicesDiscovered received: " + status);
        }
    }
    /*
         * 特征值的讀寫
         * */
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,
                                     BluetoothGattCharacteristic characteristic, int status)
    {
        if (status == BluetoothGatt.GATT_SUCCESS)
        {
            Log.i(TAG, "--onCharacteristicRead called--");
            //從特征值讀取數(shù)據(jù)
            // characteristic是特征值,而特征值是用16bit或者128bit,16bit是官方認證過的,128bit是可以自定義的
            // 這里的兩步操作第一步獲得二進制的特征值,第二步將其變成字符串
            byte[] sucString = characteristic.getValue();
            String string = new String(sucString);
            //將數(shù)據(jù)通過廣播到Ble_Activity
            //broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

    }
    /*
         * 特征值的改變
         * */
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic)
    {
        System.out.println("++++++++++++++++");
        broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        // ACTION_DATA_AVAILABLE: 接受來自設備的數(shù)據(jù),可以通過讀或通知操作獲得
    }
    /*
         * 特征值的寫
         * */
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
                                      BluetoothGattCharacteristic characteristic, int status) {

        super.onCharacteristicWrite(gatt, characteristic, status);
        if (status == BluetoothGatt.GATT_SUCCESS) {//發(fā)送完成
            mSendState = true;
            Log.d("AppRun"+getClass().getSimpleName(),"發(fā)送完成");
        }
    }
    /*
         * 讀描述值
         * */
    @Override
    public void onDescriptorRead(BluetoothGatt gatt,
                                 BluetoothGattDescriptor descriptor, int status)
    {
        // TODO Auto-generated method stub
        // super.onDescriptorRead(gatt, descriptor, status);
        Log.w(TAG, "----onDescriptorRead status: " + status);
        byte[] desc = descriptor.getValue();
        if (desc != null)
        {
            Log.w(TAG, "----onDescriptorRead value: " + new String(desc));
        }

    }
    /*
         * 寫描述值
         * */
    @Override
    public void onDescriptorWrite(BluetoothGatt gatt,
                                  BluetoothGattDescriptor descriptor, int status)
    {
        // TODO Auto-generated method stub
        // super.onDescriptorWrite(gatt, descriptor, status);
        Log.w(TAG, "--onDescriptorWrite--: " + status);
    }
    /*
         * 讀寫藍牙信號值
         * */
    // Rssi是藍牙的接受信號強度
    @Override
    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status)
    {
        // TODO Auto-generated method stub
        // super.onReadRemoteRssi(gatt, rssi, status);
        Log.w(TAG, "--onReadRemoteRssi--: " + status);
        broadcastUpdate(ACTION_DATA_AVAILABLE, rssi);
    }

    @Override
    public void onReliableWriteCompleted(BluetoothGatt gatt, int status)
    {
        // TODO Auto-generated method stub
        // super.onReliableWriteCompleted(gatt, status);
        Log.w(TAG, "--onReliableWriteCompleted--: " + status);
    }

};

1.4.5設置特征值變化通知

為了讓手機APP接收藍牙設備發(fā)送的數(shù)據(jù),必須要設置這個setCharacteristicNotification()方法,這個十分重要。否則,手機APP將無法接受藍牙設備的數(shù)據(jù)

  • MainActivity代碼

    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    
  • BluetoothLeService類的代碼

    /**
         * @Title: setCharacteristicNotification
         * @Description: TODO(設置特征值通變化通知)
         * @param @param characteristic(特征值)
         * @param @param enabled (使能)
         * @return void
         * @throws
         */
    public void setCharacteristicNotification(
        BluetoothGattCharacteristic characteristic, boolean enabled)
    {
        if (mBluetoothAdapter == null || mBluetoothGatt == null)
        {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    
        BluetoothGattDescriptor clientConfig = characteristic
            .getDescriptor(UUID
                           .fromString("00002902-0000-1000-8000-00805f9b34fb"));
        // 其中UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"是HC-08藍牙設備的監(jiān)聽UUID
        if (enabled)
        {
            clientConfig
                .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        } else
        {
            clientConfig
                .setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        }
        mBluetoothGatt.writeDescriptor(clientConfig);
    }
    

1.4.6讀取特征值

開啟對特征值的讀

  • MainActivity代碼

    mBluetoothGatt.readCharacteristic(characteristic);
    
  • BluetoothLeService類的代碼

    /**
         * @Title: readCharacteristic
         * @Description: TODO(讀取特征值)
         * @param @param characteristic(要讀的特征值)
         * @return void    返回類型
         * @throws
         */
    public void readCharacteristic(BluetoothGattCharacteristic characteristic)
    {
        if (mBluetoothAdapter == null || mBluetoothGatt == null)
        {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.readCharacteristic(characteristic);
    
    }
    

在藍牙設備連接成功后自動讀一次特征值,如果讀成功,將返回BluetoothLeService類中的OnDataAvailableListener接口,并進入如下的方法

public void onCharacteristicRead(BluetoothGatt gatt,
                                 BluetoothGattCharacteristic characteristic, int status);

1.4.7寫入特征值

開啟對特征值的寫,也就是向藍牙外設寫入數(shù)據(jù)

  • MainActivity代碼

    mBluetoothLeService.writeCharacteristic(gattCharacteristic);
    
  • BluetoothLeService類的代碼

    // 寫入特征值
    public void writeCharacteristic(byte[] bytes)
    {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mList.add(bytes);
        //mBluetoothGatt.writeCharacteristic(characteristic);
    }
    

這是完成手機APP向藍牙設備寫數(shù)據(jù)的操作

1.4.8獲取已連接藍牙的所有服務

/**
     * @Title: getSupportedGattServices
     * @Description: TODO(得到藍牙的所有服務)
     * @param @return    無
     * @return List<BluetoothGattService>
     * @throws
     */
public List<BluetoothGattService> getSupportedGattServices()
{
    if (mBluetoothGatt == null)
        return null;
    return mBluetoothGatt.getServices();

}

返回已經(jīng)連接藍牙設備的所有服務

1.4.9讀取藍牙設備的RSSI值

該方法返回的是已連接的藍牙設備的信號值(RSSI),而RSSI值是藍牙的信號值,離得越遠信號越小,反之亦然

// 讀取RSSi
public void readRssi()
{
    if (mBluetoothAdapter == null || mBluetoothGatt == null)
    {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    mBluetoothGatt.readRemoteRssi();
}

該方法返回的是已連接的藍牙設備的信號值(RSSI

1.4.10發(fā)送廣播

通過廣播的形式將數(shù)據(jù)發(fā)出去,在MainActivity中通過設置過濾器接收對應的廣播

//廣播意圖
private void broadcastUpdate(final String action, int rssi)
{
    final Intent intent = new Intent(action);
    intent.putExtra(EXTRA_DATA, String.valueOf(rssi));
    sendBroadcast(intent);
}
//廣播意圖
private void broadcastUpdate(final String action)
{
    final Intent intent = new Intent(action);
    sendBroadcast(intent);
}

/* 廣播遠程發(fā)送過來的數(shù)據(jù) */
public void broadcastUpdate(final String action,
                            final BluetoothGattCharacteristic characteristic)
{
    final Intent intent = new Intent(action);
    //從特征值獲取數(shù)據(jù)
    final byte[] data = characteristic.getValue();
    MainActivity.revDataForCharacteristic =data;
    if (data != null && data.length > 0)
    {
        final StringBuilder stringBuilder = new StringBuilder(data.length);
        for (byte byteChar : data)
        {
            stringBuilder.append(String.format("%02X ", byteChar));

            Log.i(TAG, "***broadcastUpdate: byteChar = " + byteChar);

        }
        Log.e("AppRunTime","測試一");
        intent.putExtra("BLE_BYTE_DATA", data);
        intent.putExtra(EXTRA_DATA, new String(data));
        System.out.println("broadcastUpdate for  read data:"
                           + new String(data));
    }
    sendBroadcast(intent);
}

1.5廣播監(jiān)聽器:

廣播的目的:

  • 讓別人能發(fā)現(xiàn)自己,對于一個不廣播的設備,周圍設備感覺不到其存在的,因此,要讓別的設備能發(fā)現(xiàn),則必須向外廣播,在廣播中可以帶上豐富的數(shù)據(jù),比如設備的能力,設備名字以及其他自定義的數(shù)據(jù),這也就有了第二種可能
  • 給不需要建立連接的應用廣播數(shù)據(jù),比如一個BLE溫度計,其本身可以不接收任何連接,而可以選擇通過廣播將溫度發(fā)送出去。檢測者只要監(jiān)聽廣播就能獲取當前的溫度

掃描者只有在收到廣播數(shù)據(jù)后,才能去與廣播者建立連接。廣播是周期性的將廣播數(shù)據(jù)從廣播通道上發(fā)送出去

意圖過濾器:

IntentFilter翻譯成中文就是“意圖過濾器”,主要用來過濾隱式意圖。當用戶進行一項操作的時候,Android系統(tǒng)會根據(jù)配置的 “意圖過濾器” 來尋找可以響應該操作的組件,服務。這里的意圖過濾器就是讓用戶對服務端也就是硬件外設進行操作

1.5.1注冊/取消注冊廣播監(jiān)聽

在官方Demo中,便用了廣播來作為activity和service之間的數(shù)據(jù)傳遞;MainActivity開啟了前面的服務之后,就在MainActivity中注冊了這個mGattUpdateReceiver廣播,以下代碼是MainActivity中的

// 取消注冊廣播和IntentFilter
@Override
protected void onDestroy()
{
    super.onDestroy();
    //解除廣播接收器
    unregisterReceiver(mGattUpdateReceiver);
    mBluetoothLeService = null;
}

// Activity出來時候,綁定廣播接收器,監(jiān)聽藍牙連接服務傳過來的事件
// 在官方demo中,廣播接收器也叫廣播監(jiān)聽器,用廣播實現(xiàn)activity和service的數(shù)據(jù)傳遞
// 在MainActivity執(zhí)行了bindService,開啟了藍牙服務
// 而在這里,就通過registerReceiver注冊了mGattUpdateReceiver廣播和IntentFilter
@Override
protected void onResume()
{
    super.onResume();
    //綁定廣播接收器
    registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
    if (mBluetoothLeService != null)
    {
        //根據(jù)藍牙地址,建立連接
        final boolean result = mBluetoothLeService.connect(mDeviceAddress);
    }
}
/* 意圖過濾器 */
private static IntentFilter makeGattUpdateIntentFilter()
{
    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
    intentFilter
        .addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
    intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
    return intentFilter;
}

上述代碼利用registerReceiver()和unregisterReceiver()方法完成注冊和取消注冊廣播,下面的代碼是設置廣播接收和過濾器

1.5.2廣播回調(diào)監(jiān)聽

廣播回調(diào)監(jiān)聽,便是MainActivity接收從Service發(fā)送過來的信息,上面說到的上文有說到BluetoothService類的方法BluetoothGattCallback,就是從這里發(fā)送廣播的

/**
     * 廣播接收器,負責接收BluetoothLeService類發(fā)送的數(shù)據(jù)
     */
// 下面是對前面注冊的廣播的回調(diào)監(jiān)聽,作用是接受從Service發(fā)送回來的信息
// 從BluetoothGattCallback中發(fā)送廣播,這里接受信息
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        final String action = intent.getAction();
        if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))//Gatt連接成功
        {
            mConnected = true;
            //status = "connected";
            //更新連接狀態(tài)
            //updateConnectionState(status);
            System.out.println("BroadcastReceiver :" + "device connected");

        } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED//Gatt連接失敗
                   .equals(action))
        {
            mConnected = false;
            //status = "disconnected";
            //更新連接狀態(tài)
            //updateConnectionState(status);
            System.out.println("BroadcastReceiver :"
                               + "device disconnected");

        } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED//發(fā)現(xiàn)GATT服務器
                   .equals(action))
        {
            // Show all the supported services and characteristics on the
            // user interface.
            //獲取設備的所有藍牙服務
            //這里留意一下:當連接成功后,首先service那邊會發(fā)現(xiàn)服務特征值,通過廣播傳輸回來,然后執(zhí)行下面的方法
            displayGattServices(mBluetoothLeService
                                .getSupportedGattServices());
            System.out.println("BroadcastReceiver :"
                               + "device SERVICES_DISCOVERED");
        } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))//有效數(shù)據(jù)
        {
            //處理發(fā)送過來的數(shù)據(jù)
            try {
                if (intent.getExtras().getString(
                    BluetoothLeService.EXTRA_DATA)!=null) {
                    displayData(intent.getExtras().getString(
                        BluetoothLeService.EXTRA_DATA), intent);
                    System.out.println("BroadcastReceiver onData:"
                                       + intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
};

在接收廣播的代碼中,displayGattServices()是進一步的完成發(fā)現(xiàn)服務,而displayData()則是進一步的完成數(shù)據(jù)接收處理

1.5.3處理數(shù)據(jù)的輸入和獲取

private static BluetoothGattCharacteristic target_chara = null;
//藍牙service,負責后臺的藍牙服務
private static BluetoothLeService mBluetoothLeService;
private Handler mhandler = new Handler();
/**
     * @Title: displayGattServices
     * @Description: TODO(處理藍牙服務)
     * @param
     * @return void
     * @throws
     */
// 處理數(shù)據(jù)的輸入和獲取
private void displayGattServices(List<BluetoothGattService> gattServices)
{

    if (gattServices == null)
        return;
    String uuid = null;
    String unknownServiceString = "unknown_service";
    String unknownCharaString = "unknown_characteristic";

    // 服務數(shù)據(jù),可擴展下拉列表的第一級數(shù)據(jù)
    ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();

    // 特征數(shù)據(jù)(隸屬于某一級服務下面的特征值集合)
    ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();

    // 部分層次,所有特征值集合
    mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

    // Loops through available GATT Services.
    for (BluetoothGattService gattService : gattServices)
    {

        // 獲取服務列表
        HashMap<String, String> currentServiceData = new HashMap<String, String>();
        uuid = gattService.getUuid().toString();

        // 查表,根據(jù)該uuid獲取對應的服務名稱。SampleGattAttributes這個表需要自定義。

        gattServiceData.add(currentServiceData);

        System.out.println("Service uuid:" + uuid);

        ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>();

        // 從當前循環(huán)所指向的服務中讀取特征值列表
        List<BluetoothGattCharacteristic> gattCharacteristics = gattService
            .getCharacteristics();

        ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();

        // Loops through available Characteristics.
        // 對于當前循環(huán)所指向的服務中的每一個特征值
        for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
        {
            charas.add(gattCharacteristic);
            HashMap<String, String> currentCharaData = new HashMap<String, String>();
            uuid = gattCharacteristic.getUuid().toString();

            if (gattCharacteristic.getUuid().toString()
                .equals(HEART_RATE_MEASUREMENT))
            {
                // 測試讀取當前Characteristic數(shù)據(jù),會觸發(fā)mOnDataAvailable.onCharacteristicRead()
                mhandler.postDelayed(new Runnable()
                                     {

                                         @Override
                                         public void run()
                                         {
                                             // TODO Auto-generated method stub
                                             mBluetoothLeService
                                                 .readCharacteristic(gattCharacteristic);
                                         }
                                     }, 200);

                // 接受Characteristic被寫的通知,收到藍牙模塊的數(shù)據(jù)后會觸發(fā)mOnDataAvailable.onCharacteristicWrite()
                mBluetoothLeService.setCharacteristicNotification(
                    gattCharacteristic, true);
                target_chara = gattCharacteristic;
                // 設置數(shù)據(jù)內(nèi)容
                // 往藍牙模塊寫入數(shù)據(jù)
                // mBluetoothLeService.writeCharacteristic(gattCharacteristic);
            }
            List<BluetoothGattDescriptor> descriptors = gattCharacteristic
                .getDescriptors();
            for (BluetoothGattDescriptor descriptor : descriptors)
            {
                System.out.println("---descriptor UUID:"
                                   + descriptor.getUuid());
                // 獲取特征值的描述
                mBluetoothLeService.getCharacteristicDescriptor(descriptor);
                // mBluetoothLeService.setCharacteristicNotification(gattCharacteristic,
                // true);
            }

            gattCharacteristicGroupData.add(currentCharaData);
        }
        // 按先后順序,分層次放入特征值集合中,只有特征值
        mGattCharacteristics.add(charas);
        // 構件第二級擴展列表(服務下面的特征值)
        gattCharacteristicData.add(gattCharacteristicGroupData);

    }

}

1.5.4數(shù)據(jù)的接收

下面的代碼完成數(shù)據(jù)的接收,將其顯示到scrollview中

/**
     * @Title: displayData
     * @Description: TODO(接收到的數(shù)據(jù)在scrollview上顯示)
     * @param @param rev_string(接受的數(shù)據(jù))
     * @return void
     * @throws
     */
private void displayData(String rev_string, Intent intent)
{
    try {
        byte[] data = intent.getByteArrayExtra("BLE_BYTE_DATA");
        if(data==null)
            System.out.println("data is null!!!!!!");
        if (receptionHex)
            rev_string = bytesToHexString(data);
        else
            rev_string = new String(data, 0, data.length, "GB2312");//GB2312編碼
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    bluedata = rev_string;
    //更新UI
    runOnUiThread(new Runnable()
                  {
                      @Override
                      public void run()
                      {
                          //                rev_tv.setText(bluedata);
                          if(bluedata.length() == RFID )
                          {
                              rfid = bluedata;
                              rev_tv.setText(rfid);

                          }
                          else if(bluedata.length() == DISTANCE )
                          {
                              Log.d("data","*"+bluedata+"*");
                              int a = bluedata.charAt(1) - '0';
                              int b = bluedata.charAt(4) - '0';
                              int c = bluedata.charAt(7) - '0';
                              distance = a * 100 + b * 10 + c;
                              if(distance>100 && distance < 500 )takephoto = false;
                              rev_tv.setText(new Integer(distance).toString());
                          }
                      }
                  });

}

1.5.5發(fā)送數(shù)據(jù)

下面的代碼是在BluetoothLeService類中,用于給外設的藍牙模塊寫入數(shù)據(jù)的方法

// 發(fā)送數(shù)據(jù)
public void startSend(final BluetoothGattCharacteristic characteristic){
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }
    Log.d("AppRun"+getClass().getSimpleName(),"添加完成,開始發(fā)送");
    if (mList.size() != 0){
        new Thread(new Runnable() {
            @Override
            public void run() {


                for (int i = 0;i<mList.size();) {
                    try {
                        if (mSendState) {
                            Thread.sleep(5);
                            characteristic.setValue(mList.get(i));
                            mSendState = false;
                            mBluetoothGatt.writeCharacteristic(characteristic);
                            ++i;
                        } else {
                            Log.d("AppRun"+getClass().getSimpleName(),"等待中..");
                            Thread.sleep(20);
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
                Log.d("AppRun"+getClass().getSimpleName(),"發(fā)送完畢..");
                mList.clear();
            }
        }).start();
    }
}


下面是將數(shù)據(jù)進行分包,因為每次藍牙傳輸數(shù)據(jù)只能是20個字節(jié),如果一個數(shù)據(jù)超過20個字節(jié),必須要分成n個存放20字節(jié)的包文章來源地址http://www.zghlxwxcb.cn/news/detail-407380.html

/**
     * 將數(shù)據(jù)分包
     *
     * **/
public int[] dataSeparate(int len)
{
    int[] lens = new int[2];
    lens[0]=len/20;
    lens[1]=len%20;
    return lens;
}

/**
     * 將16進制字符串轉換為byte[]
     */
public static byte[] hexString2ByteArray(String bs) {
    if (bs == null) {
        return null;
    }
    int bsLength = bs.length();
    if (bsLength % 2 != 0) {
        bs = "0"+bs;
        bsLength = bs.length();
    }
    byte[] cs = new byte[bsLength / 2];
    String st;
    for (int i = 0; i < bsLength; i = i + 2) {
        st = bs.substring(i, i + 2);
        cs[i / 2] = (byte) Integer.parseInt(st, 16);
    }
    return cs;
}

//byte數(shù)組轉String
public static String bytesToHexString(byte[] bArray) {
    StringBuffer sb = new StringBuffer(bArray.length);
    String sTemp;
    for (int i = 0; i < bArray.length; i++) {
        sTemp = Integer.toHexString(0xFF & bArray[i]);
        if (sTemp.length() < 2)
            sb.append(0);
        sb.append(sTemp.toUpperCase());
    }
    int length = sb.length();
    if (length == 1||length == 0){
        return sb.toString();
    }
    if (length%2==1){
        sb.insert(length-1," ");
        length= length-1;
    }
    for (int i = length;i>0;i=i-2){
        sb.insert(i," ");
    }
    return sb.toString();
}

到了這里,關于Android藍牙BLE開發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Android Ble藍牙App(七)掃描過濾

    Android Ble藍牙App(七)掃描過濾

    ??在上一篇文章中了解了MTU的相關知識以及對于設備操作信息的展示,本篇文章中將增加掃描設備的過濾功能讓你更方便的掃描想要找的低功耗藍牙設備。 Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務 Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Bl

    2024年02月09日
    瀏覽(25)
  • Android Ble藍牙App(五)數(shù)據(jù)操作

    Android Ble藍牙App(五)數(shù)據(jù)操作

    ??關于低功耗藍牙的服務、特性、屬性、描述符都已經(jīng)講清楚了,而下面就是使用這些知識進行數(shù)據(jù)的讀取、寫入、通知等操作。 Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務 Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Ble藍牙App(五)數(shù)據(jù)操作 ?

    2024年02月13日
    瀏覽(21)
  • Android Ble藍牙App(三)特性和屬性

    Android Ble藍牙App(三)特性和屬性

    ??在上一篇中我們完成了連接和發(fā)現(xiàn)服務兩個動作,那么再發(fā)現(xiàn)服務之后要做什么呢?發(fā)現(xiàn)服務只是讓你知道設備有什么服務,可以做什么事情。 Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務 Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Ble藍牙App(五

    2024年02月14日
    瀏覽(22)
  • Android Ble藍牙App(二)連接與發(fā)現(xiàn)服務

    Android Ble藍牙App(二)連接與發(fā)現(xiàn)服務

    ??在上一篇中我們進行掃描設備的處理,本文中進行連接和發(fā)現(xiàn)服務的數(shù)據(jù)處理,運行效果圖如下所示: Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務 Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Ble藍牙App(五)數(shù)據(jù)操作 ??現(xiàn)在我們從MainActivity進

    2024年01月16日
    瀏覽(27)
  • Flutter:BLE藍牙開發(fā)

    說明: 使用flutter_blue_plus插件實現(xiàn)低功耗藍牙開發(fā)。 一、添加藍牙權限: 1.Android網(wǎng)絡權限(工程/android/app/src/main/AndroidManifest.xml): 2.iOS藍牙權限(工程/ios/Runner/Info.plist): 二、實現(xiàn)掃描/連接/接收BLE設備數(shù)據(jù): 1.添加flutter_blue_plus插件依賴,在pubspec.yaml中: 2.實現(xiàn)BLE藍牙設備掃

    2024年02月11日
    瀏覽(24)
  • Android Ble藍牙App(四)UI優(yōu)化和描述符

    Android Ble藍牙App(四)UI優(yōu)化和描述符

    ??上一篇中了解了特性和屬性,同時顯示設備藍牙服務下的特性和屬性,本文中就需要來使用這些特性和屬性來完成一些功能。 Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務 Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Ble藍牙App(五)數(shù)據(jù)操作 ??

    2024年02月13日
    瀏覽(16)
  • 微信小程序:BLE藍牙開發(fā)

    一、添加藍牙權限: 1.添加藍牙權限(工程/app.json): 二、實現(xiàn)掃描/連接/接收BLE設備數(shù)據(jù): 1.實現(xiàn)BLE藍牙設備掃描: 2.實現(xiàn)連接設備/接收數(shù)據(jù): 3.調(diào)用例子:

    2024年02月12日
    瀏覽(106)
  • Android Ble藍牙App(六)請求MTU與顯示設備信息

    Android Ble藍牙App(六)請求MTU與顯示設備信息

    ??在上一篇文章中已經(jīng)了解了數(shù)據(jù)操作的方式,而數(shù)據(jù)交互的字節(jié)長度取決于我們手機與藍牙設備的最大支持長度。 Ble藍牙App(一)掃描 Ble藍牙App(二)連接與發(fā)現(xiàn)服務 Ble藍牙App(三)特性和屬性 Ble藍牙App(四)UI優(yōu)化和描述符 Ble藍牙App(五)數(shù)據(jù)操作 Ble藍牙App(六)

    2024年02月04日
    瀏覽(25)
  • 【Bluetooth藍牙開發(fā)】九、BLE協(xié)議之GATT

    個人主頁:董哥聊技術 我是董哥,嵌入式領域新星創(chuàng)作者 創(chuàng)作理念:專注分享高質量嵌入式文章,讓大家讀有所得! ? 【所有文章匯總】 ?

    2024年01月22日
    瀏覽(24)
  • 微信小程序低功耗藍牙BLE快速開發(fā)js

    微信小程序低功耗藍牙BLE快速開發(fā)js

    目的: 1、為了能三分鐘快速開發(fā)BLE模塊,特此做一個筆記,按照筆記的順序開發(fā),能夠簡單、快速、規(guī)范。 2、如果以后覺得有必要改動的地方就在這里更改。 3、主要是記錄BLE連接的步驟。 https://note.youdao.com/ynoteshare/index.html?id=d662c9c1c58121ec28901d78d9aa5e80 比較完整的微信小程

    2024年02月10日
    瀏覽(109)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包