久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

[轉(zhuǎn)載]藍(lán)牙4.0

 飲茶仙人 2016-11-16

安卓4.3(API 18)為BLE的核心功能提供平臺支持和API,App可以利用它來發(fā)現(xiàn)設(shè)備,、查詢服務(wù)和讀寫特性。相比傳統(tǒng)的藍(lán)牙,,BLE更顯著的特點(diǎn)是低功耗,。這一優(yōu)點(diǎn)使android App可以與具有低功耗要求的BLE設(shè)備通信,如近距離傳感器,、心臟速率監(jiān)視器,、健身設(shè)備等。

關(guān)鍵術(shù)語和概念

Generic Attribute Profile(GATT)—GATT配置文件是一個(gè)通用規(guī)范,,用于在BLE鏈路上發(fā)送和接收被稱為“屬性”的數(shù)據(jù)塊,。目前所有的BLE應(yīng)用都基于GATT。 藍(lán)牙SIG規(guī)定了許多低功耗設(shè)備的配置文件,。配置文件是設(shè)備如何在特定的應(yīng)用程序中工作的規(guī)格說明,。注意一個(gè)設(shè)備可以實(shí)現(xiàn)多個(gè)配置文件,。例如,一個(gè)設(shè)備可能包括心率監(jiān)測儀和電量檢測,。
Attribute Protocol(ATT)—GATT在ATT協(xié)議基礎(chǔ)上建立,,也被稱為GATT/ATT。ATT對在BLE設(shè)備上運(yùn)行進(jìn)行了優(yōu)化,,為此,,它使用了盡可能少的字節(jié)。每個(gè)屬性通過一個(gè)唯一的的統(tǒng)一標(biāo)識符(UUID)來標(biāo)識,,每個(gè)String類型UUID使用128 bit標(biāo)準(zhǔn)格式,。屬性通過ATT被格式化為characteristics和services。
Characteristic 一個(gè)characteristic包括一個(gè)單一變量和0-n個(gè)用來描述characteristic變量的descriptor,,characteristic可以被認(rèn)為是一個(gè)類型,,類似于類。
Descriptor Descriptor用來描述characteristic變量的屬性,。例如,,一個(gè)descriptor可以規(guī)定一個(gè)可讀的描述,或者一個(gè)characteristic變量可接受的范圍,,或者一個(gè)characteristic變量特定的測量單位,。
Service service是characteristic的集合。例如,,你可能有一個(gè)叫“Heart Rate Monitor(心率監(jiān)測儀)”的service,,它包括了很多characteristics,如“heart rate measurement(心率測量)”等,。你可以在bluetooth.org 找到一個(gè)目前支持的基于GATT的配置文件和服務(wù)列表,。
角色和責(zé)任

以下是Android設(shè)備與BLE設(shè)備交互時(shí)的角色和責(zé)任:

中央 VS 外圍設(shè)備。 適用于BLE連接本身,。中央設(shè)備掃描,,尋找廣播;外圍設(shè)備發(fā)出廣播,。
GATT 服務(wù)端 VS GATT 客戶端,。決定了兩個(gè)設(shè)備在建立連接后如何互相交流。
為了方便理解,,想象你有一個(gè)Android手機(jī)和一個(gè)用于活動跟蹤BLE設(shè)備,,手機(jī)支持中央角色,活動跟蹤器支持外圍(為了建立BLE連接你需要注意兩件事,,只支持外圍設(shè)備的兩方或者只支持中央設(shè)備的兩方不能互相通信),。

當(dāng)手機(jī)和運(yùn)動追蹤器建立連接后,他們開始向另一方傳輸GATT數(shù)據(jù),。哪一方作為服務(wù)器取決于他們傳輸數(shù)據(jù)的種類,。例如,,如果運(yùn)動追蹤器想向手機(jī)報(bào)告?zhèn)鞲衅鲾?shù)據(jù),運(yùn)動追蹤器是服務(wù)端,。如果運(yùn)動追蹤器更新來自手機(jī)的數(shù)據(jù),,手機(jī)會作為服務(wù)端。

在這份文檔的例子中,,android app(運(yùn)行在android設(shè)備上)作為GATT客戶端,。app從gatt服務(wù)端獲得數(shù)據(jù),gatt服務(wù)端即支持Heart Rate Profile(心率配置)的BLE心率監(jiān)測儀,。但是你可以自己設(shè)計(jì)android app去扮演GATT服務(wù)端角色,。更多信息見BluetoothGattServer。

BLE權(quán)限

為了在app中使用藍(lán)牙功能,,必須聲明藍(lán)牙權(quán)限BLUETOOTH,。利用這個(gè)權(quán)限去執(zhí)行藍(lán)牙通信,例如請求連接,、接受連接,、和傳輸數(shù)據(jù)。

如果想讓你的app啟動設(shè)備發(fā)現(xiàn)或操縱藍(lán)牙設(shè)置,,必須聲明BLUETOOTH_ADMIN權(quán)限,。注意:如果你使用BLUETOOTH_ADMIN權(quán)限,你也必須聲明BLUETOOTH權(quán)限,。

在你的app manifest文件中聲明藍(lán)牙權(quán)限,。

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>"
如果想聲明你的app只為具有BLE的設(shè)備提供,,在manifest文件中包括:

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
但是如果想讓你的app提供給那些不支持BLE的設(shè)備,,需要在manifest中包括上面代碼并設(shè)置required="false",然后在運(yùn)行時(shí)可以通過使用PackageManager.hasSystemFeature()確定BLE的可用性,。
// 使用此檢查確定BLE是否支持在設(shè)備上,,然后你可以有選擇性禁用BLE相關(guān)的功能
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}

設(shè)置BLE

你的app能與BLE通信之前,你需要確認(rèn)設(shè)備是否支持BLE,,如果支持,,確認(rèn)已經(jīng)啟用。注意如果<uses-feature.../>設(shè)置為false,,這個(gè)檢查才是必需的,。

如果不支持BLE,那么你應(yīng)該適當(dāng)?shù)亟貌糠諦LE功能,。如果支持BLE但被禁用,,你可以無需離開應(yīng)用程序而要求用戶啟動藍(lán)牙。使用BluetoothAdapter兩步完成該設(shè)置,。

獲取 BluetoothAdapter

所有的藍(lán)牙活動都需要藍(lán)牙適配器,。BluetoothAdapter代表設(shè)備本身的藍(lán)牙適配器(藍(lán)牙無線),。整個(gè)系統(tǒng)只有一個(gè)藍(lán)牙適配器,而且你的app使用它與系統(tǒng)交互,。下面的代碼片段顯示了如何得到適配器,。注意該方法使用getSystemService()]返回BluetoothManager,然后將其用于獲取適配器的一個(gè)實(shí)例,。Android 4.3(API 18)引入BluetoothManager,。

// 初始化藍(lán)牙適配器
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();

開啟藍(lán)牙

接下來,你需要確認(rèn)藍(lán)牙是否開啟,。調(diào)用isEnabled())去檢測藍(lán)牙當(dāng)前是否開啟,。如果該方法返回false,藍(lán)牙被禁用。下面的代碼檢查藍(lán)牙是否開啟,,如果沒有開啟,,將顯示錯(cuò)誤提示用戶去設(shè)置開啟藍(lán)牙。

// 確保藍(lán)牙在設(shè)備上可以開啟
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

發(fā)現(xiàn)BLE設(shè)備

為了發(fā)現(xiàn)BLE設(shè)備,,使用startLeScan())方法,。這個(gè)方法需要一個(gè)參數(shù)BluetoothAdapter.LeScanCallback。你必須實(shí)現(xiàn)它的回調(diào)函數(shù),,那就是返回的掃描結(jié)果,。因?yàn)閽呙璺浅O碾娏浚銘?yīng)當(dāng)遵守以下準(zhǔn)則:

只要找到所需的設(shè)備,,停止掃描,。
不要在循環(huán)里掃描,并且對掃描設(shè)置時(shí)間限制,。以前可用的設(shè)備可能已經(jīng)移出范圍,,繼續(xù)掃描消耗電池電量。
下面代碼顯示了如何開始和停止一個(gè)掃描:

// 掃描和顯示可以提供的藍(lán)牙設(shè)備.

public class DeviceScanActivity extends ListActivity {
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;


// 10秒后停止尋找.
private static final long SCAN_PERIOD = 10000;
...
private void scanLeDevice(final boolean enable) {
    if (enable) {
        // 經(jīng)過預(yù)定掃描期后停止掃描
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
        }, SCAN_PERIOD);

        mScanning = true;
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
    ...
}

...
}
如果你只想掃描指定類型的外圍設(shè)備,,可以改為調(diào)用startLeScan(UUID[], BluetoothAdapter.LeScanCallback)),需要提供你的app支持的GATT services的UUID對象數(shù)組,。

作為BLE掃描結(jié)果的接口,下面是BluetoothAdapter.LeScanCallback的實(shí)現(xiàn),。

private LeDeviceListAdapter mLeDeviceListAdapter;
...
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};

注意:只能掃描BLE設(shè)備或者掃描傳統(tǒng)藍(lán)牙設(shè)備,,不能同時(shí)掃描BLE和傳統(tǒng)藍(lán)牙設(shè)備。

連接到GATT服務(wù)端

與一個(gè)BLE設(shè)備交互的第一步就是連接它——更具體的,,連接到BLE設(shè)備上的GATT服務(wù)端,。為了連接到BLE設(shè)備上的GATT服務(wù)端,需要使用connectGatt( )方法,。這個(gè)方法需要三個(gè)參數(shù):一個(gè)Context對象,,自動連接(boolean值,表示只要BLE設(shè)備可用是否自動連接到它),和BluetoothGattCallback調(diào)用,。

mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
連接到GATT服務(wù)端時(shí),,由BLE設(shè)備做主機(jī),,并返回一個(gè)BluetoothGatt實(shí)例,然后你可以使用這個(gè)實(shí)例來進(jìn)行GATT客戶端操作,。請求方(Android app)是GATT客戶端,。BluetoothGattCallback用于傳遞結(jié)果給用戶,例如連接狀態(tài),,以及任何進(jìn)一步GATT客戶端操作,。

在這個(gè)例子中,這個(gè)BLE APP提供了一個(gè)activity(DeviceControlActivity)來連接,,顯示數(shù)據(jù),,顯示該設(shè)備支持的GATT services和characteristics。根據(jù)用戶的輸入,,這個(gè)activity與BluetoothLeService通信,,通過Android BLE API實(shí)現(xiàn)與BLE設(shè)備交互。

//通過BLE API服務(wù)端與BLE設(shè)備交互
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName();


private BluetoothManager mBluetoothManager; //藍(lán)牙管理器
private BluetoothAdapter mBluetoothAdapter; //藍(lán)牙適配器
private String mBluetoothDeviceAddress; //藍(lán)牙設(shè)備地址
private BluetoothGatt mBluetoothGatt; 
private int mConnectionState = STATE_DISCONNECTED;

private static final int STATE_DISCONNECTED = 0; //設(shè)備無法連接
private static final int STATE_CONNECTING = 1;  //設(shè)備正在連接狀態(tài)
private static final int STATE_CONNECTED = 2;   //設(shè)備連接完畢

public final static String ACTION_GATT_CONNECTED =
        "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
        "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
        "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
        "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
        "com.example.bluetooth.le.EXTRA_DATA";

public final static UUID UUID_HEART_RATE_MEASUREMENT =
        UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);

//通過BLE API的不同類型的回調(diào)方法
private final BluetoothGattCallback mGattCallback =
        new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,
            int newState) {//當(dāng)連接狀態(tài)發(fā)生改變
        String intentAction;
        if (newState == BluetoothProfile.STATE_CONNECTED) {//當(dāng)藍(lán)牙設(shè)備已經(jīng)連接
            intentAction = ACTION_GATT_CONNECTED;
            mConnectionState = STATE_CONNECTED;
            broadcastUpdate(intentAction);
            Log.i(TAG, "Connected to GATT server.");
            Log.i(TAG, "Attempting to start service discovery:" +
                    mBluetoothGatt.discoverServices());

        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {//當(dāng)設(shè)備無法連接
            intentAction = ACTION_GATT_DISCONNECTED;
            mConnectionState = STATE_DISCONNECTED;
            Log.i(TAG, "Disconnected from GATT server.");
            broadcastUpdate(intentAction);
        }
    }

    @Override
    // 發(fā)現(xiàn)新服務(wù)端
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
        } else {
            Log.w(TAG, "onServicesDiscovered received: " + status);
        }
    }

    @Override
    // 讀寫特性
    public void onCharacteristicRead(BluetoothGatt gatt,
            BluetoothGattCharacteristic characteristic,
            int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }
    }
 ...
};

...
}
當(dāng)一個(gè)特定的回調(diào)被觸發(fā)的時(shí)候,,它會調(diào)用相應(yīng)的broadcastUpdate()輔助方法并且傳遞給它一個(gè)action,。注意在該部分中的數(shù)據(jù)解析按照藍(lán)牙心率測量配置文件規(guī)格進(jìn)行。

private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}

private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);


// 這是心率測量配置文件,。
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
    int flag = characteristic.getProperties();
    int format = -1;
    if ((flag & x01) != 0) {
        format = BluetoothGattCharacteristic.FORMAT_UINT16;
        Log.d(TAG, "Heart rate format UINT16.");
    } else {
        format = BluetoothGattCharacteristic.FORMAT_UINT8;
        Log.d(TAG, "Heart rate format UINT8.");
    }
    final int heartRate = characteristic.getIntValue(format, 1);
    Log.d(TAG, String.format("Received heart rate: %d", heartRate));
    intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
} else {
    // 對于所有其他的配置文件,,用十六進(jìn)制格式寫數(shù)據(jù)
    final byte[] data = characteristic.getValue();
    if (data != null && data.length > 0) {
        final StringBuilder stringBuilder = new StringBuilder(data.length);
        for(byte byteChar : data)
            stringBuilder.append(String.format("%02X ", byteChar));
        intent.putExtra(EXTRA_DATA, new String(data) + "\n" +
                stringBuilder.toString());
    }
}
sendBroadcast(intent);

}
返回DeviceControlActivity, 這些事件由一個(gè)BroadcastReceiver來處理:

// 通過服務(wù)控制不同的事件
// ACTION_GATT_CONNECTED: 連接到GATT服務(wù)端
// ACTION_GATT_DISCONNECTED: 未連接GATT服務(wù)端.
// ACTION_GATT_SERVICES_DISCOVERED: 未發(fā)現(xiàn)GATT服務(wù).
// ACTION_DATA_AVAILABLE: 接受來自設(shè)備的數(shù)據(jù),可以通過讀或通知操作獲得,。
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)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.
ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// 在用戶接口上展示所有的services and characteristics
displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};

讀取BLE變量

你的android app完成與GATT服務(wù)端連接和發(fā)現(xiàn)services后,,就可以讀寫支持的屬性。例如,,這段代碼通過服務(wù)端的services和 characteristics迭代,,并且將它們顯示在UI上。

public class DeviceControlActivity extends Activity {
...
// 演示如何遍歷支持GATT Services/Characteristics
// 這個(gè)例子中,,我們填充綁定到UI的ExpandableListView上的數(shù)據(jù)結(jié)構(gòu)
private void displayGattServices(List<BluetoothGattService> gattServices) {
if (gattServices == null) return;
String uuid = null;
String unknownServiceString = getResources().
getString(R.string.unknown_service);
String unknownCharaString = getResources().
getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData =
new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
mGattCharacteristics =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();


    // 循環(huán)可用的GATT Services.
    for (BluetoothGattService gattService : gattServices) {
        HashMap<String, String> currentServiceData =
                new HashMap<String, String>();
        uuid = gattService.getUuid().toString();
        currentServiceData.put(
                LIST_NAME, SampleGattAttributes.
                        lookup(uuid, unknownServiceString));
        currentServiceData.put(LIST_UUID, uuid);
        gattServiceData.add(currentServiceData);

        ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
                new ArrayList<HashMap<String, String>>();
        List<BluetoothGattCharacteristic> gattCharacteristics =
                gattService.getCharacteristics();
        ArrayList<BluetoothGattCharacteristic> charas =
                new ArrayList<BluetoothGattCharacteristic>();
       // 循環(huán)可用的Characteristics.
        for (BluetoothGattCharacteristic gattCharacteristic :
                gattCharacteristics) {
            charas.add(gattCharacteristic);
            HashMap<String, String> currentCharaData =
                    new HashMap<String, String>();
            uuid = gattCharacteristic.getUuid().toString();
            currentCharaData.put(
                    LIST_NAME, SampleGattAttributes.lookup(uuid,
                            unknownCharaString));
            currentCharaData.put(LIST_UUID, uuid);
            gattCharacteristicGroupData.add(currentCharaData);
        }
        mGattCharacteristics.add(charas);
        gattCharacteristicData.add(gattCharacteristicGroupData);
     }
...
}

...
}
接收GATT通知

當(dāng)設(shè)備上的特性改變時(shí)會通知BLE應(yīng)用程序,。這段代碼顯示了如何使用setCharacteristicNotification( )給一個(gè)特性設(shè)置通知。

private BluetoothGatt mBluetoothGatt;
BluetoothGattCharacteristic characteristic;
boolean enabled;
...
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
...
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);

如果對一個(gè)特性啟用通知,當(dāng)遠(yuǎn)程藍(lán)牙設(shè)備特性發(fā)送變化,,回調(diào)函數(shù)onCharacteristicChanged( ))被觸發(fā)。

@Override
// 廣播更新
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}

關(guān)閉客戶端App

當(dāng)你的app完成BLE設(shè)備的使用后,,應(yīng)該調(diào)用close( )),,系統(tǒng)可以合理釋放占用資源。


public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}</code

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多