天天看點

Android Bluetooth Low Energy (BLE)簡單友善的藍牙開源庫——EasyBLE

源碼傳送門

最新版本

Android Bluetooth Low Energy (BLE)簡單友善的藍牙開源庫——EasyBLE

功能

  • 支援多裝置同時連接配接
  • 支援廣播包解析
  • 支援連接配接同時配對
  • 支援搜尋系統已連接配接裝置
  • 支援搜尋器設定
  • 支援自定義搜尋過濾條件
  • 支援自動重連、最大重連次數限制、直接重連或搜尋到裝置再重連控制
  • 支援請求延時及發送延時設定
  • 支援分包大小設定、最大傳輸單元設定
  • 支援觀察者監聽或回調方式。注意:觀察者監聽和回調隻能取其一!
  • 支援使用注解@RunOn控制回調線程,使用注解@Observe控制觀察者的方法執行線程
  • 支援設定回調或觀察者的方法預設執行線程
  • 支援發送設定(是否等待發送結果回調再發送下一包)
  • 支援寫入模式設定
  • 支援設定連接配接的傳輸方式
  • 支援連接配接逾時設定

配置

  1. 因為使用了jdk8的一些特性,需要在module的build.gradle裡添加如下配置:
//純java的項目
android {
	compileOptions {
		sourceCompatibility JavaVersion.VERSION_1_8
		targetCompatibility JavaVersion.VERSION_1_8
	}
}

//有kotlin的項目還需要在project的build.gradle裡添加
allprojects {
    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8

        kotlinOptions {
            jvmTarget = \'1.8\'
            apiVersion = \'1.3\'
            languageVersion = \'1.3\'
        }
    }
}
           
  1. module的build.gradle中的添加依賴,自行修改為最新版本,同步後通常就可以用了:
dependencies {
	...
	implementation \'cn.wandersnail:easyble-x:latestVersion\'
	//額外三個依賴
	implementation \'cn.wandersnail:common-utils:latestVersion\'
	implementation \'cn.wandersnail:common-observer:latestVersion\'
	implementation \'cn.wandersnail:common-poster:latestVersion\'
	//也可以使用
	//implementation \'cn.wandersnail:common-full:latestVersion\'//此依賴包含上面三個
}
           
  1. 如果從jcenter下載下傳失敗。在project的build.gradle裡的repositories添加内容,最好兩個都加上,添加完再次同步即可。
allprojects {
	repositories {
		...
		mavenCentral()
		maven { url \'https://dl.bintray.com/wandersnail/androidx/\' }
	}
}
           

使用方法

初始化SDK

執行個體化有兩種方式:

  1. 使用預設方式自動建構執行個體,直接擷取執行個體即可
//執行個體化并初始化
EasyBLE.getInstance().initialize(this);
           
  1. 建構自定義執行個體,必須在EasyBLE.getInstance()之前!!
ScanConfiguration scanConfig = new ScanConfiguration()
		.setScanSettings(new ScanSettings.Builder()
				.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
				.build())
		.setScanPeriodMillis(15000)
		.setAcceptSysConnectedDevice(true)
		.setOnlyAcceptBleDevice(true);
EasyBLE ble = EasyBLE.getBuilder().setScanConfiguration(scanConfig)
		.setObserveAnnotationRequired(false)//不強制使用{@link Observe}注解才會收到被觀察者的消息,強制使用的話,性能會好一些
		.setMethodDefaultThreadMode(ThreadMode.MAIN)//指定回調方法和觀察者方法的預設線程
		.build();
ble.initialize(this);
           

銷毀SDK

//如果中途需要修改配置重新執行個體化,調用此方法後即可重新建構EasyBLE執行個體
EasyBLE.getInstance().destroy();
           

日志輸出控制

EasyBLE.getInstance().setLogEnabled(true);//開啟日志列印
           

藍牙搜尋

  1. 定義搜尋監聽器
private ScanListener scanListener = new ScanListener() {
	@Override
	public void onScanStart() {
		//搜尋開始
	}

	@Override
	public void onScanStop() {
		//搜尋停止
	}

	@Override
	public void onScanResult(@NotNull Device device) {
		//搜尋結果
	}

	@Override
	public void onScanError(int errorCode, @NotNull String errorMsg) {
		switch(errorCode) {
			case ScanListener.ERROR_LACK_LOCATION_PERMISSION://缺少定位權限		
				break;
			case ScanListener.ERROR_LOCATION_SERVICE_CLOSED://位置服務未開啟		
				break;
			case ScanListener.ERROR_SCAN_FAILED://搜尋失敗
				break;
		}
	}
};
           
  1. 添加監聽
EasyBLE.getInstance().addScanListener(scanListener);
           
  1. 開始搜尋
EasyBLE.getInstance().startScan();
           
  1. 停止搜尋
EasyBLE.getInstance().stopScan();
           
  1. 停止監聽
EasyBLE.getInstance().removeScanListener(scanListener);
           

觀察者模式資料及事件

  1. 定義觀察者。實作EventObserver接口即可:
public class MainActivity extends AppCompatActivity implements EventObserver {
    /**
     * 使用{@link Observe}确定要接收消息,并在主線程執行方法
     */
    @Observe(ThreadMode.MAIN)
    @Override
    public void onConnectionStateChanged(@NonNull Device device) {
        switch (device.getConnectionState()) {
            case SCANNING_FOR_RECONNECTION:
                break;
            case CONNECTING:
                break;
            case DISCONNECTED:
                break;
            case SERVICE_DISCOVERED:
                break;
        }
    }
	
    /**
     * 使用{@link Observe}确定要接收消息,方法在{@link EasyBLEBuilder#setMethodDefaultThreadMode(ThreadMode)}指定的線程執行
     */
    @Observe
    @Override
    public void onNotificationChanged(@NonNull Request request, boolean isEnabled) {
        if (request.getType() == RequestType.SET_NOTIFICATION) {
            if (isEnabled) {
                Log.d("EasyBLE", "通知開啟了");
            } else {
                Log.d("EasyBLE", "通知關閉了");
            }
        } else {
            if (isEnabled) {
                Log.d("EasyBLE", "Indication開啟了");
            } else {
                Log.d("EasyBLE", "Indication關閉了");
            }
        }
    }

    /**
     * 如果{@link EasyBLEBuilder#setObserveAnnotationRequired(boolean)}設定為false時,無論加不加{@link Observe}注解都會收到消息。
     * 設定為true時,必須加{@link Observe}才會收到消息。
     * 預設為false,方法預設執行線程在{@link EasyBLEBuilder#setMethodDefaultThreadMode(ThreadMode)}指定
     */
    @Override
    public void onCharacteristicWrite(@NonNull Request request, @NonNull byte[] value) {
        Log.d("EasyBLE", "成功寫入:" + StringUtils.toHex(value, " "));
    }
}
           
  1. 注冊觀察者
EasyBLE.getInstance().registerObserver(observer);
           
  1. 取消注冊觀察者
EasyBLE.getInstance().unregisterObserver(observer);
           

連接配接

  1. 連接配接配置
//連接配接配置,舉個例随意配置兩項
ConnectionConfiguration config = new ConnectionConfiguration();
config.setConnectTimeoutMillis(10000);
config.setRequestTimeoutMillis(1000);
           
  1. 建立連接配接
connection = EasyBLE.getInstance().connect(device, config);//觀察者監聽連接配接狀态
           
  1. 斷開連接配接,還可重連
EasyBLE.getInstance().disconnectConnection(device);//斷開指定連接配接
//EasyBLE.getInstance().disconnectAllConnections();//斷開所有連接配接
           
  1. 釋放連接配接,不可重連,需要重建立立連接配接
EasyBLE.getInstance().releaseConnection(device);//釋放指定連接配接
//EasyBLE.getInstance().releaseAllConnections();//釋放所有連接配接
           

讀寫特征值、開啟Notify

兩種方式:

  1. 接口回調方式
//開關通知
boolean isEnabled = connection.isNotificationOrIndicationEnabled(serviceUuid, characteristicUuid);
Request.Builder<NotificationChangeCallback> builder = Request.getSetNotificationBuilder(serviceUuid, characteristicUuid, !isEnabled);
//不設定回調,使用觀察者模式接收結果
builder.build().execute(connection);

//讀取特征值
Request.Builder<ReadCharacteristicCallback> builder = Request.getReadCharacteristicBuilder(serviceUuid, characteristicUuid);
builder.setTag(UUID.randomUUID().toString());
builder.setPriority(Integer.MAX_VALUE);//設定請求優先級
//設定了回調則觀察者不會收到此次請求的結果消息
builder.setCallback(new ReadCharacteristicCallback() {
	//注解可以指定回調線程
	@RunOn(ThreadMode.BACKGROUND)
	@Override
	public void onCharacteristicRead(@NonNull Request request, @NonNull byte[] value) {
		Log.d("EasyBLE", "主線程:" + (Looper.getMainLooper() == Looper.myLooper()));
		Log.d("EasyBLE", "讀取到特征值:" + StringUtils.toHex(value, " "));
	}

	//不使用注解指定線程的話,使用建構器設定的預設線程
	@Override
	public void onRequestFailed(@NonNull Request request, int failType, @Nullable Object value) {

	}
});
builder.build().execute(connection);

//寫特征值
Request.WriteCharacteristicBuilder builder = Request.getWriteCharacteristicBuilder(serviceUuid, characteristicUuid, "test write".getBytes());
//根據需要設定寫入配置
builder.setWriteOptions(new WriteOptions.Builder()
		.setPackageSize(20)
		.setPackageWriteDelayMillis(5)
		.setRequestWriteDelayMillis(10)
		.setWaitWriteResult(true)
		.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)
		.build());
//不設定回調,使用觀察者模式接收結果
connection.execute(builder.build());
           
  1. 使用觀察者模式接收結果。不在請求建構器中設定回調即可

釋放SDK,釋放後必須重新初始化後方可使用

EasyBLE.getInstance().release();
           

Demo效果預覽

Android Bluetooth Low Energy (BLE)簡單友善的藍牙開源庫——EasyBLE
Android Bluetooth Low Energy (BLE)簡單友善的藍牙開源庫——EasyBLE
Android Bluetooth Low Energy (BLE)簡單友善的藍牙開源庫——EasyBLE

基于此庫的BLE調試app

Android Bluetooth Low Energy (BLE)簡單友善的藍牙開源庫——EasyBLE
Android Bluetooth Low Energy (BLE)簡單友善的藍牙開源庫——EasyBLE
Android Bluetooth Low Energy (BLE)簡單友善的藍牙開源庫——EasyBLE