Android 普通藍芽學習筆記
Android 普通藍芽學習
雖然做開發有一段時間了,但是有關藍芽方面一直接觸的不多,正好目前有一個關於藍芽開發的需求,雖然是用到的BLE和普通藍芽有些區別,但是既然學習了就順便把普通藍芽也學習一下,也為了以後自己少走些彎路,先將這些學習筆記學習下來。官方文件
本例的原始碼已經上傳,檢視原始碼
需要的許可權
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
類
藍芽有關的所有的類如下:
普通藍芽用到的幾個關鍵的類:
BluetoothAdapter 藍芽介面卡
Represents the local device Bluetooth adapter. The BluetoothAdapter lets you perform fundamental Bluetooth tasks, such as initiate device discovery,
query a list of bonded (paired) devices, instantiate a BluetoothDevice using a known MAC address, and create a BluetoothServerSocket to listen for
connection requests from other devices, and start a scan for Bluetooth LE devices.
根據官方文件的說明,
BluetoothAdapter
可以執行基本的藍芽任務,比如啟動裝置發現,查詢已配對的藍芽列表,使用已知的地址例項化一個BluetoothDevice
,建立一個BluetoothServerSocket
監聽連結請求等。
BluetoothDevice 藍芽裝置
Represents a remote Bluetooth device. A BluetoothDevice lets you create a connection with the respective device or query information about it,
such as the name, address, class, and bonding state.
代表一個遠端藍芽裝置。
BluetoothDevice
允許建立一個連線的裝置或查詢相關資訊,如名稱、地址、階級和配對的狀態。BluetoothSocket
The interface for Bluetooth Sockets is similar to that of TCP sockets: Socket and ServerSocket.
顧名思義藍芽連線
BluetoothServerSocket
The interface for Bluetooth Sockets is similar to that of TCP sockets: Socket and ServerSocket.
藍芽服務連結,後兩者都是和TCP埠類似的一個
socket
。
首先開啟藍芽開始搜尋等;
主要用到的幾個方法:
getDefaultAdapter() 獲取一個介面卡物件
getName() 獲取本地藍芽名稱
getAddress() 獲取本地藍芽的地址
enable() 開啟本地藍芽(低版本中不會提示使用者)
isEnabled() 判斷藍芽是否已經開啟
disable() 關閉本地藍芽
startDiscovery() 開始搜尋(發現)
cancelDiscovery() 取消裝置搜尋(發現)
isDiscovering() 返回當前是否是在搜尋裝置
listenUsingRfcommWithServiceRecord(String name, UUID uuid) 建立一個安全的
BluetoothServerSocket
開啟藍芽
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//開啟藍芽 方法一
if (!bluetoothAdapter.isEnabled()) {
bluetoothAdapter.enable();
}
//方法二 推薦
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler, REQUEST_ENABLE);
開始搜尋裝置
呼叫startDiscovery()
開始搜尋裝置,但是僅僅呼叫此方法是沒有任何作用的,startDiscovery()
是非同步呼叫,立即返回,需要註冊一個廣播接收者
來接受搜尋的結果。整個搜尋過程持續12秒。
//註冊
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, intentFilter);
//廣播接收者
BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//找到裝置
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d("MainActivity", "搜尋到裝置");
//在列表中顯示搜尋出的裝置
adapter.add("name : " + device.getName() + "\n address : " + device.getAddress());
bluetoothDevices.add(device);
}
//搜尋完成
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
Log.d("MainActivity", "搜尋結束");
} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {
Log.d("MainActivity", "開始搜尋");
}
}
};
連線裝置
建立連線,Android sdk
支援的藍芽連線是通過BluetoothSocket
建立連線,伺服器端(BluetoothServerSocket
)和客戶端(BluetoothSocket
)需指定同樣的UUID,才能建立連線,因為建立連線的方法會阻塞執行緒,所以伺服器端和客戶端都應啟動新執行緒連線。
UUID
的格式如下:
String uuid = "a60f35f0-b93a-11de-8a39-08002009c666";
建立伺服器端程式碼如下:
首先建立伺服器,獲取BluetoothServerSocket
物件,通過BluetoothAdapter
的listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
方法和listenUsingRfcommWithServiceRecord(String name, UUID uuid)
方法,其中前者是不安全的連結,後者是安全的連結。
然後使用BluetoothServerSocket.accept()
方法接受客戶端連線,當連線成功返回一個BluetoothSocket
物件。
private class ServiceThread extends Thread {
@Override
public void run() {
BluetoothServerSocket serverSocket = null;
try {
serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord("my_test_lianjie", UUID.fromString(uuid));
Log.d("ServiceThread", "建立伺服器成功");
} catch (IOException e) {
e.printStackTrace();
Log.d("ServiceThread", "建立伺服器失敗");
}
try {
socket = serverSocket.accept();
Log.d("ServiceThread", "客戶端連線成功");
new ReadThread().start();
} catch (IOException e) {
e.printStackTrace();
Log.d("ServiceThread", "客戶端連線失敗");
}
}
}
建立客戶端連結程式碼如下:
這裡需要注意的是要對首先檢測裝置是否進行了配對,只有首先進行配對才能進行連線。藍芽配對是通過反射的方法呼叫BluetoothDevice.creMethod()
方法。
建立連線首先獲取BluetoothSocket
物件,呼叫BluetoothDevice
的createInsecureRfcommSocketToServiceRecord(UUID uuid)
或者createRfcommSocketToServiceRecord(UUID uuid)
方法,其中前者是不安全的連結,後者是安全的連結。
然後呼叫BluetoothSocket.connect()
方法進行連線。
private class ConnectThread extends Thread {
BluetoothDevice device;
public ConnectThread(BluetoothDevice device) {
this.device = device;
}
@Override
public void run() {
try {
socket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
} catch (IOException e) {
e.printStackTrace();
}
if (device.getBondState() == BluetoothDevice.BOND_BONDED) { //已配對裝置 直接進行連結
connectSocket();
} else if (device.getBondState() == BluetoothDevice.BOND_NONE) { //未配對裝置 先配對再連結
Method creMethod = null;
try {
creMethod = BluetoothDevice.class.getMethod("createBond");
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Log.e("TAG", "開始配對");
try {
creMethod.invoke(device);
} catch (IllegalAccessException e) {
e.printStackTrace();
Log.e("TAG", "配對失敗");
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
private void connectSocket() {
try {
socket.connect();
Log.e("TAG", "連線成功");
new ReadThread().start();
} catch (IOException e) {
e.printStackTrace();
Log.e("TAG", "連線失敗");
}
}
public void cancel() {
try {
socket.close();
socket = null;
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
}
注意
客戶端建立連線的方式有很多種,這裡使用的是先獲得一個socket
然後再檢查是否需要進行配對,再建立連線。
還可以通過反射的方法,通過埠進行連線。
進行通訊
藍芽通訊是通過流的方式進行的:
OutputStream outS = socket.getOutputStream();
InputStream inS = socket.getInputStream();
傳送的方法如:
OutputStream os = null;
try {
os = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
try {
os.write("你好".getBytes());
Log.d("MainActivity", "傳送成功");
} catch (IOException e) {
e.printStackTrace();
Log.d("MainActivity", "傳送失敗");
}
接受的方法如:
private class ReadThread extends Thread {
@Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
InputStream mmInStream = null;
try {
mmInStream = socket.getInputStream();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while (true) {
try {
// Read from the InputStream
if ((bytes = mmInStream.read(buffer)) > 0) {
byte[] buf_data = new byte[bytes];
for (int i = 0; i < bytes; i++) {
buf_data[i] = buffer[i];
}
String s = new String(buf_data);
Log.d("ReadThread", s);
}
} catch (IOException e) {
try {
mmInStream.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
break;
}
}
}
}
至此,普通藍芽的基本發現、連線、通訊功能就完成了,當然還有許多需要完善的地方。
寫的可能有些混亂,不足之處,還請指正,不喜忽噴。
相關推薦
Android 普通藍芽學習筆記
Android 普通藍芽學習 雖然做開發有一段時間了,但是有關藍芽方面一直接觸的不多,正好目前有一個關於藍芽開發的需求,雖然是用到的BLE和普通藍芽有些區別,但是既然學習了就順便把普通藍芽也學習一下,也為了以後自己少走些彎路,先將這些學習筆記學習下來。官方文件
藍芽學習筆記之例項廣播資料的解析
轉載自:https://blog.csdn.net/sinat_23338865/article/details/52170581 BLE 裝置工作的第一步就是向外廣播資料。廣播資料中帶有裝置相關的資訊。 本文主要說一下 BLE 的廣播中的資料的規範以及廣播包的解析,這是我們專案中的廣播資料
nrf51822藍芽學習筆記之例項分析PPI和SHORT
首先開啟PPI程式看到如下 刪除串列埠初始化部分方便檢視: 一、初始化定時器的方式 TIMER可以處於兩種模式: 1定時模式(Timer mode) 2計數模式(Counter mode)
Android BLE 藍芽學習總結(一):手機作為周邊BluetoothGattServer的實現
低功耗藍芽的基本概念: 在BLE協議中,有兩個角色,周邊(Periphery)和中央(Central)。周邊是資料的提供者,中央是資料的使用和處理者。在Android SDK裡面,Android4.3以後手機可以作為中央使用;Android5.0以後手機才可以
藍芽學習筆記之建立藍芽連線的過程
傳送廣播資料包的叫廣播發起者(advertisers),在廣播通道接收廣播資料包但沒意向連線廣播發起裝置的叫掃描者( scanners), 需要連線到另一個裝置的裝置叫做 initiators,它監聽可連線的廣播資料包。如果advertiser正在使用一個可連線的廣播事件
Android APK安裝過程學習筆記
屏蔽 組成 學習 二進制 替換 壓縮包 基於 壓縮 方式 1.什麽是APK APK,即Android Package,Android安裝包。不同平臺的安裝文件格式都不同,類似於Windows的安裝包是二進制的exe格式,Mac的安裝包是dmg格式。APK可以再Andro
Android異步載入學習筆記之四:利用緩存優化網絡載入圖片及ListView載入優化
角度 thread 下午 出發 easy code cat height back 假設不做不論什麽處理。直接用網絡載入圖片在網速快的情況下可能沒什麽不好的感覺。可是假設使用移動流量或是網絡不好的時候。問題就來了,要麽用戶會抱怨流量使用太多。要麽抱怨圖
Android Bluetooth 藍芽強度Rssi
轉自 https://blog.csdn.net/lhc1105/article/details/54585632 轉自 https://blog.csdn.net/jasonwang18/article/details/73131020 轉自 http://www.cnblogs.co
Android獲取藍芽地址(非mac地址)
方法: public static String getBlueToothAddress(Context context){ return android.provider.Settings.Secure.getString(context.getContentResol
Android BLE 藍芽快速開發框架。
FastBle 專案地址:Jasonchenlijian/FastBle 簡介:Android BLE 藍芽快速開發框架。 更多:作者 提 Bug 標籤: 藍芽- Thanks to th
Android手機藍芽總結之傳統藍芽
出處:Android手機藍芽總結之傳統藍芽 最近,公司有一個專案時關於手機藍芽和硬體藍芽相互通訊的需求。基於之前很久沒有學習硬體的知識,這次記錄下來,以備下次需要時使用。 首先,需要搞清楚一些基本的概要,藍芽3.0以前的是傳統藍芽,4.0以後的是低功耗藍芽,Android藍
Android BLE藍芽4.0開發—Android手機與BLE終端通訊
轉載自: https://blog.csdn.net/fu908323236/article/details/76208997 這篇部落格主要講解AndroidBLE藍芽4.0的基本概念,以及基礎用法。 BLE 即 Bluetooth Low Energy,藍芽低功耗技術,是藍芽
《Android群英傳》學習筆記之Android體系與系統架構
一、Android系統架構 1.Linux核心層 Android核心系統服務依賴於Linux2.6核心,如安全性、記憶體管理、程序管理、網路協議棧和驅動模型。Linux核心也是作為硬體與軟體棧的抽象層
《Android群英傳》學習筆記之Android控制元件架構與自定義控制元件詳解
一、Android控制元件架構: 控制元件大致分為兩類:ViewGroup控制元件與View控制元件。View是繪製在螢幕上的使用者能與之互動的一個物件。而ViewGroup則是一個用於存放其他Vi
《Android群英傳》學習筆記之Activity與Activity呼叫棧分析
一、Activity 1、Activity形態: Active/Running 處於棧頂,可互動。 Paused 被遮擋但未被完全覆蓋,失去焦點,不可互動。 Stopped 被完全覆蓋,但保持了所有狀
藍芽學習 (8)配對raspberryPi和SensorTag CC2650
這裡我們利用gatttool來配對。 [email protected]:~ $ gatttool --help Usage: gatttool [OPTION...] Application Options: -i, --adapter=
藍芽學習(五)-- 低功耗藍芽(BLE)主機:屬性、服務
在BLE中服務、屬性、特性、行為很難理解。講得極其抽象,讓我疑惑的是它是一種邏輯上面的概念還是資料結構上的概念? 服務是一種或多種特性的組合,特性則由一種或多種屬性組成 BLE的對於服務上的概念上居然是來源於“面向物件程式設計(OOP)”: 類 物件 屬
藍芽學習(四)-- 低功耗藍芽(BLE)鏈路層資料包
octet : 八位位元組 鏈路層定義了兩個裝置如何利用無線電傳輸資訊。它包含了報文、廣播資料通道的詳細定義,也規定了發現其他裝置的流程、廣播的資料、連線的建立、連線的管理以及連線中的資料傳輸。 下圖是報文的基本結構,適用於所有的報文,無論其用途是什麼。報文一開始是一小段訓練
藍芽學習(二)
通訊距離 路徑損耗是指發射機天線到接收機天線的能量消耗,路徑損耗與距離的關係: p a
藍芽學習--關係
簡寫 GAP : Generic Access Profile GATT : Generic Attribute Profile ATT : Attribute Protocol HCI : Host-Controller Interface