Android BLE4.0(設(shè)備搜索)

接上一篇Android BLE4.0(基本知識)罩缴,本篇記錄在Android中的藍牙4.0開發(fā)他爸。要想與藍牙設(shè)備進行通訊,首先要連接到相應的設(shè)備夕膀,連接到相應的設(shè)備之前虚倒,我們要能夠搜索到它美侦。所以我們先從找到設(shè)備開始。

1魂奥、申請權(quán)限

在Android中要想使用藍牙菠剩,需要添加以下兩個權(quán)限

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

一般情況下,添加上面兩個權(quán)限應該是可以了耻煤,但是老司機們都應該知道Android 6.0采用新的權(quán)限機制來保護用戶的隱私具壮,將權(quán)限分為Normal Permissions (不涉及用戶隱私,不需要用戶授權(quán))Dangerous Permission (涉及用戶隱私哈蝇,使用時需要用戶實時授權(quán))兩種棺妓。

藍牙權(quán)限本身不屬于用戶隱私的權(quán)限,但是在Android 6.0之后要用藍牙還需要添加一個模糊定位的權(quán)限

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

這個權(quán)限就屬于隱私權(quán)限的范圍了炮赦。怜跑。。吠勘。一股淡淡的憂傷性芬。。剧防。
所以想要兼容6.0還要在代碼中檢測權(quán)限:

1.1植锉、Android 6.0 檢測并申請權(quán)限
/*
 * 檢測并申請權(quán)限
 */
private void checkBluetoothPermission() {
    if (Build.VERSION.SDK_INT >= 23) {
        //校驗是否已具有模糊定位權(quán)限
        if (ContextCompat.checkSelfPermission(TYMposActivity.this,
                Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
           //申請模糊定位權(quán)限
           ActivityCompat.requestPermissions(TYMposActivity.this,
                   new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
        } else {
           //具有權(quán)限
            connectBluetooth();
        }
    } else {
         //系統(tǒng)不高于6.0直接執(zhí)行
         connectBluetooth();
    }
}

這里用到了兩個API

  • ContextCompat.checkSelfPermission
    主要用于檢測某個權(quán)限是否已經(jīng)被授予,
    返回值為PackageManager.PERMISSION_DENIED
    或者是PackageManager.PERMISSION_GRANTED峭拘。當返回DENIED就需要進行申請授權(quán)了

  • ActivityCompat.requestPermissions
    這是個異步方法汽煮,有三個參數(shù)
    第一個參數(shù)是Context,這個不多說棚唆;
    第二個參數(shù)是需要申請的權(quán)限的字符串數(shù)組暇赤;
    第三個參數(shù)為requestCode,主要用于回調(diào)的時候檢測宵凌。
    可以從方法名requestPermissions以及第二個參數(shù)看出鞋囊,是支持一次性申請多個權(quán)限的,系統(tǒng)會通過對話框 逐一 詢問用戶是否授權(quán)瞎惫。

1.2溜腐、授權(quán)返回處理:

對授權(quán)返回值進行處理,有點類似于startActivityForResult

@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION: {
            // 如果請求被取消瓜喇,則結(jié)果數(shù)組為空.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //已授權(quán)
            } else {
                // 未授權(quán)
            }
            return;
        }
    }
}

關(guān)于6.0的權(quán)限申請到此結(jié)束挺益,另外補充一下:
如果想聲明你的app只為具有BLE的設(shè)備提供,在manifest文件中包括:

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

但如果想讓你的app提供給那些不支持BLE的設(shè)備乘寒,需要在manifest中包括上面代碼并設(shè)置required="false"望众,然后在運行時可以通過使用PackageManager.hasSystemFeature()確定BLE的可用性。

2、檢查設(shè)備是否支持藍牙

注意:Android系統(tǒng)版本在4.3及以上才能使用藍牙4.0烂翰。
使用此檢查確定BLE是否支持在設(shè)備上夯缺,然后你可以有選擇性禁用BLE相關(guān)的功能

if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
    Toast.makeText(this, "設(shè)備不支持藍牙4.0", Toast.LENGTH_SHORT).show();
    finish();
}

3、藍牙搜索

大致步驟

  • **獲取BluetoothManager **
  • 獲取BluetoothAdapter
  • 調(diào)用BluetoothAdapter.startLeScan開始掃描設(shè)備

獲取BluetoothManager:

BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);

獲取BluetoothAdapter
獲取BluetoothAdapter有兩種方式:

  • 第一種:
BluetoothAdapter adapter = manager.getAdapter();
  • 第二種
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 

掃描附近BLE設(shè)備
在開始掃描之前先打開藍牙,打開之前需要先判斷藍牙是否已經(jīng)打開:

/**
 * 藍牙是否打開
 *
 * @return
 */
public boolean isBleOpen() {
   if (adapter == null) {
      return false;
   }
   return adapter.isEnabled();
}

打開藍牙有兩種方式

  • 跳轉(zhuǎn)到系統(tǒng)的界面甘耿,手動打開
/**
 * 系統(tǒng)打開藍牙
 */
public void sysOpenBLE(Activity activity, int requestCode) {
   Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
   activity.startActivityForResult(intent, requestCode);
}
  • 自動打開藍牙
/**
 * 打開藍牙
 */
public boolean openBLE() {
   if (adapter == null) {
      return false;
   }
   return adapter.enable();
}

確保藍牙打開之后開始掃描設(shè)備:
通過adapter.startLeScan()方法來進行掃描踊兜。這里有兩個方法:

/**
 *
 */
public boolean startLeScan(LeScanCallback callback) {
    return startLeScan(null, callback);
}

/**
 * @param serviceUuids Array of services to look for
 * 需要過濾的UUID服務(wù),掃描的時候佳恬,只返回與指定UUID相同的設(shè)備
 */
public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
    if (DBG) Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
    if (callback == null) {
        if (DBG) Log.e(TAG, "startLeScan: null callback");
        return false;
    }
    BluetoothLeScanner scanner = getBluetoothLeScanner();
    if (scanner == null) {
        if (DBG) Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
        return false;
    }
  ......
}

以上代碼摘自Android源碼捏境,這兩個不多說什么,重點在 serviceUuids這里毁葱,大家都知道每個藍牙都有一個服務(wù)UUID,這個參數(shù)就是針對這個UUID進行過濾的典蝌,掃描返回結(jié)果的時候,只會返回與UUID相同的設(shè)備头谜,另外一個LeScanCallback**骏掀,這個是返回搜索結(jié)果的回調(diào),如果這個LeScanCallback不傳柱告,掃描是不會啟動的截驮。

BluetoothAdapter.LeScanCallback scanCallback = new BluetoothAdapter.LeScanCallback() {
   @Override
   public void onLeScan(BluetoothDevice bluetoothDevice, int rssi, byte[] scanRecord) {
     
   }
};

在這個掃描回調(diào)中,回調(diào)了三個參數(shù):

  • BluetoothDevice

/**
 * Represents a remote Bluetooth device. A {@link BluetoothDevice} lets you
 * create a connection with the respective device or query information about
 * it, such as the name, address, class, and bonding state.
 * 藍牙信息相關(guān)的類际度,可以獲取藍牙的名稱葵袭,地址,已經(jīng)綁定狀態(tài)等
 */
public final class BluetoothDevice implements Parcelable {

.....
//綁定狀態(tài)相關(guān)
/**
 * Indicates the remote device is not bonded (paired).
 * <p>There is no shared link key with the remote device, so communication
 * (if it is allowed at all) will be unauthenticated and unencrypted.
 */
public static final int BOND_NONE = 10;
/**
 * Indicates bonding (pairing) is in progress with the remote device.
 */
public static final int BOND_BONDING = 11;
/**
 * Indicates the remote device is bonded (paired).
 * <p>A shared link keys exists locally for the remote device, so
 * communication can be authenticated and encrypted.
 * <p><i>Being bonded (paired) with a remote device does not necessarily
 * mean the device is currently connected. It just means that the pending
 * procedure was completed at some earlier time, and the link key is still
 * stored locally, ready to use on the next connection.
 * </i> 
*/
public static final int BOND_BONDED = 12;

.....

//設(shè)備類型
/**
 * Bluetooth device type, Unknown
 */
public static final int DEVICE_TYPE_UNKNOWN = 0;
/**
 * Bluetooth device type, Classic - BR/EDR devices乖菱,傳統(tǒng)
 */
public static final int DEVICE_TYPE_CLASSIC = 1;
/**
 * Bluetooth device type, Low Energy - LE-only 坡锡,低功耗
 */
public static final int DEVICE_TYPE_LE = 2;
/**
 * Bluetooth device type, Dual Mode - BR/EDR/LE 雙模式
 */
public static final int DEVICE_TYPE_DUAL = 3;

............

}

其實就是藍牙的設(shè)備的一個實體類。沒什么可以說的窒所。

  • rssi
    RSSI的值作為對遠程藍牙設(shè)備信號值鹉勒,正常為負值; 值越大信號越強;
  • scanRecord
    遠程設(shè)備提供的配對號,一般用不到吵取。

小結(jié)

如果不出意外禽额,到這里是可以掃描到周邊的藍牙設(shè)備了,對于藍牙開發(fā)已經(jīng)算是邁出了第一步皮官,也有了一個初步了解脯倒,接下來記錄怎么連接到一個搜索到的設(shè)備。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捺氢,一起剝皮案震驚了整個濱河市藻丢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摄乒,老刑警劉巖悠反,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件残黑,死亡現(xiàn)場離奇詭異,居然都是意外死亡问慎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門挤茄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來如叼,“玉大人,你說我怎么就攤上這事穷劈×。” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵歇终,是天一觀的道長社证。 經(jīng)常有香客問我,道長评凝,這世上最難降的妖魔是什么追葡? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮奕短,結(jié)果婚禮上宜肉,老公的妹妹穿的比我還像新娘。我一直安慰自己翎碑,他們只是感情好谬返,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著日杈,像睡著了一般遣铝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上莉擒,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天酿炸,我揣著相機與錄音,去河邊找鬼涨冀。 笑死梁沧,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蝇裤。 我是一名探鬼主播廷支,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼栓辜!你這毒婦竟也來了恋拍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤藕甩,失蹤者是張志新(化名)和其女友劉穎施敢,沒想到半個月后周荐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡僵娃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年概作,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片默怨。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡讯榕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出匙睹,到底是詐尸還是另有隱情愚屁,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布痕檬,位于F島的核電站霎槐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏梦谜。R本人自食惡果不足惜丘跌,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唁桩。 院中可真熱鬧碍岔,春花似錦、人聲如沸朵夏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仰猖。三九已至捏肢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饥侵,已是汗流浹背鸵赫。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留躏升,地道東北人辩棒。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像膨疏,于是被迫代替她去往敵國和親一睁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容