跳转到内容
Skip 中文站
3.2k

SkipBluetooth

这是一个 Skip Lite Swift/Kotlin 库项目, 在 Android 上提供与 CoreBluetooth 对等的 API。

要在项目中引入此框架,请将以下依赖项 添加到 Package.swift 文件中:

let package = Package(
name: "my-package",
products: [
.library(name: "MyProduct", targets: ["MyTarget"]),
],
dependencies: [
.package(url: "https://source.skip.dev/skip-bluetooth.git", "0.0.0"..<"2.0.0"),
],
targets: [
.target(name: "MyTarget", dependencies: [
.product(name: "SkipBluetooth", package: "skip-bluetooth")
])
]
)

SkipBluetooth 旨在提供与 CoreBluetooth 对等的 API,但在少数情况下,你需要在实现中使用 // SKIP DECLARE:。

CoreBluetooth 中有一些委托方法虽然参数名称不同,却拥有相同的参数类型签名。由于 Kotlin 不会根据参数名称区分函数调用,Gradle 会将它们识别为同一个函数。以下就是一个发生冲突的示例:

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)
func centralManager(central: CBCentralManager, DidUpdateANCSAuthorizationFor peripheral: CBPeripheral)

要在 CBCentralManagerDelegate 实现中实现这些函数,请按照 Swift 的方式编写函数调用,同时在函数上方加入对应的 // SKIP DECLARE: ... 行,用来声明符合 Kotlin 规则的 API 调用。

示例如下:

/* 假设此函数位于遵循 `CBCentralManagerDelegate` 的类中 */
// SKIP DECLARE: override fun centralManagerDidConnect(central: CBCentralManager, didConnect: CBPeripheral)
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
/* 在此处编写你的实现 */
}

以下列出了目前所有此类可用函数及其对应调用:

CBCentralManagerDelegate

CoreBluetoothSkipBluetooth
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)// SKIP DECLARE: override fun centralManagerDidConnect(central: CBCentralManager, didConnect: CBPeripheral)
func centralManager(_ central: CBCentralManager, didUpdateANCSAuthorizationFor peripheral: CBPeripheral)// SKIP DECLARE: override fun centralManagerDidUpdateANCSAuthorizationFor(central: CBCentralManager, didUpdateANCSAuthorizationFor: CBPeripheral)
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: (any Error)?)// SKIP DECLARE: override fun centralManagerDidDisconnectPeripheral(central: CBCentralManager, peripheral: CBPeripheral, error: (any Error)?)

CBPeripheralManagerDelegate

CoreBluetoothSkipBluetooth
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo characteristic: CBCharacteristic)// SKIP DECLARE: override fun peripheralManagerDidSubscribeTo(peripheral: CBPeripheralManager, central: CBCentral, didSubscribeTo: CBCharacteristic)
func peripheralManager(_ peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom characteristic: CBCharacteristic)// SKIP DECLARE: override fun peripheralManagerDidUnsubscribeFrom(peripheral: CBPeripheralManager, central: CBCentral, didUnsubscribeFrom: CBCharacteristic)

CBPeripheralDelegate

CoreBluetoothSkipBluetooth
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: (any Error)?)// SKIP DECLARE: override fun peripheralDidUpdateValueFor(peripheral: CBPeripheral, didUpdateValueFor: CBCharacteristic, error: Error?)
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: (any Error)?)// SKIP DECLARE: override fun peripheralDidWriteValueFor(peripheral: CBPeripheral, didWriteValueFor: CBCharacteristic, error: Error?)
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: (any Error)?)// SKIP DECLARE: override fun peripheralDidUpdateNotificationStateFor(peripheral: CBPeripheral, didUpdateNotificationStateFor: CBCharacteristic, error: Error?)
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: (any Error)?)// SKIP DECLARE: override fun peripheralDidDiscoverCharacteristicsFor(peripheral: CBPeripheral, didDiscoverCharacteristicsFor: CBService, error: Error?)

蓝牙在 iOS 和 Kotlin 两端都需要相应权限,因此你必须在 Info.plist 文件中添加以下内容:

并在 AndroidManifest.xml 中添加以下内容:

<manifest>
<!-- 通常需要的权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 允许执行需要更高权限的操作(例如在 Android 上开启和关闭蓝牙) -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 如果需要中心设备权限
由于蓝牙可用于推断用户的精确位置,你可以使用此属性表明应用不会利用蓝牙获取其位置
(也可以移除此属性,以表明应用确实会将蓝牙用于定位)
-->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<!-- 如果需要外设权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<!-- 无论作为哪种角色,只要需要连接就添加此权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- 其他属性 -->
</manifest>

使用任何蓝牙 API 之前,都必须向用户请求权限。 一种方式是使用 SkipKit 中的 PermissionManager API:

import SkipKit
func performBluetoothOperation() async {
if await PermissionManager.requestPermission("android.permission.BLUETOOTH_SCAN") == true {
if await PermissionManager.requestPermission("android.permission.BLUETOOTH_CONNECT") == true {
// 执行蓝牙操作……
}
}
}

以下是不使用 SkipKit、手动请求权限的示例。 在这种情况下,请注意必须在将要使用蓝牙的视图或函数体中 请求用户权限。

import SwiftUI
#if SKIP
import SkipBluetooth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
#endif
struct ContentView: View {
var body: some View {
#if SKIP
askForBluetoothPermissions()
#endif
}
}
/// 提示用户授予蓝牙权限
@Composable
public func askForBluetoothPermissions() {
let requestPermissionLauncher = rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestMultiplePermissions()) { perms in
// 如有需要,可在此处处理权限
}
let permissions: kotlin.Array<String> = kotlin.arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT
)
// Skip 无法在 kotlin.Array<string> 与
// skip.lib.Array<String> 之间隐式转换,因此需要进行类型转换
SideEffect {
requestPermissionLauncher.launch(permissions)
}
}
#endif

视图一出现,这段代码就会请求蓝牙权限。此后再次加载该视图时, 系统不会再次显示提示;如果用户之前拒绝了权限,你需要提示他们前往设置中启用蓝牙。

本项目是一个 Swift Package Manager 模块,它使用 Skip 插件为 iOS 和 Android 构建软件包。

可以使用标准的 swift test 命令测试此模块, 也可以在 Xcode 中运行面向 macOS 的测试目标; 后者既会运行 Swift 测试,也会在 Robolectric Android 模拟环境中 运行转译后的 Kotlin JUnit 测试。

可以使用 skip test 执行一致性测试, 该命令会以表格形式输出两个平台的测试结果。

欢迎通过功能增强和错误修复为此软件包作出贡献。

为此软件包及其他 Skip 软件包贡献代码的一般流程如下:

  1. 派生(Fork)此仓库,并在 “Actions” 标签页中启用 Actions
  2. 将你的 Fork 检出到本地
  3. 与 Skip 应用一同开发时,将软件包添加到共享工作区,以便在应用中看到所做的更改
  4. 将更改推送到你的 Fork,并确保 “Actions” 标签页中的所有 CI 检查均通过
  5. 将你的名字添加到 Skip 贡献者协议 ↗中
  6. 从你的 Fork 发起拉取请求(Pull Request),并说明所做的更改

skiptools/skip-bluetooth ↗ 最近发布的 4 个版本:

完整历史记录:github.com/skiptools/skip-bluetooth/releases ↗ — .atom 订阅源 ↗