Skip to content

Commit 32f3d39

Browse files
fix: gitignore (#2)
1 parent d44e2e6 commit 32f3d39

File tree

6 files changed

+279
-11
lines changed

6 files changed

+279
-11
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ android/keystores/debug.keystore
7676
.turbo/
7777

7878
# generated by bob
79-
lib/
79+
dist/
8080

8181
# React Native Codegen
8282
ios/generated
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
package so.onekey.lib.ble.utils
2+
3+
import android.annotation.SuppressLint
4+
import android.bluetooth.BluetoothAdapter
5+
import android.bluetooth.BluetoothDevice
6+
import android.bluetooth.BluetoothManager
7+
import android.bluetooth.BluetoothProfile.GATT
8+
import android.content.BroadcastReceiver
9+
import android.content.Context
10+
import android.content.Intent
11+
import android.content.IntentFilter
12+
import android.content.pm.PackageManager
13+
import android.os.Build
14+
import android.os.Handler
15+
import android.os.Looper
16+
import android.util.Log
17+
import com.facebook.react.bridge.*
18+
import com.facebook.react.modules.core.DeviceEventManagerModule
19+
import so.onekey.lib.ble.utils.data.Peripheral
20+
21+
22+
class BleUtilsModule(private val reactContext: ReactApplicationContext) :
23+
ReactContextBaseJavaModule(reactContext) {
24+
25+
private var bluetoothManager: BluetoothManager? = null
26+
private val mBleBroadcastReceiver = lazy {
27+
MyBroadcastReceiver(this)
28+
}
29+
30+
override fun getName() = NAME
31+
32+
private fun getBluetoothManager(): BluetoothManager? {
33+
if (bluetoothManager == null) {
34+
bluetoothManager =
35+
reactContext.getSystemService(Context.BLUETOOTH_SERVICE)
36+
}
37+
return bluetoothManager
38+
}
39+
40+
private fun getBluetoothAdapter(): BluetoothAdapter? {
41+
return getBluetoothManager()?.adapter
42+
}
43+
44+
init {
45+
registerBluetoothReceiver()
46+
}
47+
48+
private fun registerBluetoothReceiver() {
49+
if (getBluetoothAdapter() == null) {
50+
Log.d(LOG_TAG, "No bluetooth support")
51+
return
52+
}
53+
54+
val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
55+
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
56+
val intentFilter = IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST)
57+
intentFilter.priority = IntentFilter.SYSTEM_HIGH_PRIORITY
58+
if (Build.VERSION.SDK_INT >= 34) {
59+
// Google in 2023 decides that flag RECEIVER_NOT_EXPORTED or RECEIVER_EXPORTED should be explicit set SDK 34(UPSIDE_DOWN_CAKE) on registering receivers.
60+
// Also the export flags are available on Android 8 and higher, should be used with caution so that don't break compability with that devices.
61+
reactContext.registerReceiver(mBleBroadcastReceiver.value, filter, Context.RECEIVER_EXPORTED)
62+
reactContext.registerReceiver(
63+
mBleBroadcastReceiver.value,
64+
intentFilter,
65+
Context.RECEIVER_EXPORTED
66+
)
67+
} else {
68+
reactContext.registerReceiver(mBleBroadcastReceiver.value, filter)
69+
reactContext.registerReceiver(mBleBroadcastReceiver.value, intentFilter)
70+
}
71+
Log.d(LOG_TAG, "BleManager initialized")
72+
}
73+
74+
// 向JS端发送设备绑定状态变化事件
75+
fun emitOnDeviceBondState(params: WritableMap) {
76+
reactContext
77+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
78+
.emit("onDeviceBondState", params)
79+
}
80+
81+
// 事件监听管理
82+
@ReactMethod
83+
fun addListener(eventName: String) {
84+
// 实现为空,仅用于满足RN事件监听器注册需求
85+
Log.d(LOG_TAG, "addListener $eventName")
86+
}
87+
88+
@ReactMethod
89+
fun removeListeners(count: Int) {
90+
// 实现为空,仅用于满足RN事件监听器注册需求
91+
Log.d(LOG_TAG, "removeListeners $count")
92+
}
93+
94+
@ReactMethod
95+
fun checkState(callback: Callback) {
96+
Log.d(LOG_TAG, "checkState")
97+
98+
val adapter = getBluetoothAdapter()
99+
var state = "off"
100+
if (!reactContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
101+
state = "unsupported"
102+
} else if (adapter != null) {
103+
when (adapter.state) {
104+
BluetoothAdapter.STATE_ON -> state = "on"
105+
BluetoothAdapter.STATE_TURNING_ON -> state = "turning_on"
106+
BluetoothAdapter.STATE_TURNING_OFF -> {
107+
state = "turning_off"
108+
}
109+
110+
BluetoothAdapter.STATE_OFF -> {
111+
// should not happen as per https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#getState()
112+
state = "off"
113+
}
114+
115+
else -> {
116+
state = "off"
117+
}
118+
}
119+
}
120+
121+
val map: WritableMap = Arguments.createMap()
122+
map.putString("state", state)
123+
Log.d(LOG_TAG, "state:$state")
124+
callback.invoke(state)
125+
}
126+
127+
@SuppressLint("MissingPermission")
128+
@ReactMethod
129+
fun getBondedPeripherals(callback: Callback) {
130+
val map: WritableArray = Arguments.createArray()
131+
val deviceSet: Set<BluetoothDevice> = getBluetoothAdapter()?.getBondedDevices() ?: emptySet()
132+
for (device in deviceSet) {
133+
val peripheral = Peripheral(device)
134+
val jsonBundle: WritableMap = peripheral.asWritableMap()
135+
map.pushMap(jsonBundle)
136+
}
137+
callback.invoke(null, map)
138+
}
139+
140+
@SuppressLint("MissingPermission")
141+
@ReactMethod
142+
fun getConnectedPeripherals(serviceUUIDs: ReadableArray?, callback: Callback) {
143+
Log.d(LOG_TAG, "Get connected peripherals")
144+
val map: WritableArray = Arguments.createArray()
145+
146+
if (getBluetoothAdapter() == null) {
147+
Log.d(LOG_TAG, "No bluetooth support")
148+
callback.invoke("No bluetooth support")
149+
return
150+
}
151+
152+
val peripherals: List<BluetoothDevice> =
153+
getBluetoothManager()?.getConnectedDevices(GATT) ?: emptyList()
154+
for (entry in peripherals) {
155+
val peripheral = Peripheral(entry)
156+
val jsonBundle: WritableMap = peripheral.asWritableMap()
157+
map.pushMap(jsonBundle)
158+
}
159+
callback.invoke(null, map)
160+
}
161+
162+
private class MyBroadcastReceiver(private val module: BleUtilsModule) : BroadcastReceiver() {
163+
@SuppressLint("MissingPermission")
164+
override fun onReceive(context: Context, intent: Intent) {
165+
Log.d(LOG_TAG, "onReceive")
166+
val action = intent.action
167+
168+
if (action == BluetoothDevice.ACTION_BOND_STATE_CHANGED) {
169+
val bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR)
170+
val prevState = intent.getIntExtra(
171+
BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR
172+
)
173+
val device = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
174+
intent.getParcelableExtra(
175+
BluetoothDevice.EXTRA_DEVICE, BluetoothDevice::class.java
176+
)
177+
} else {
178+
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
179+
}
180+
181+
var bondStateStr = "UNKNOWN"
182+
when (bondState) {
183+
BluetoothDevice.BOND_BONDED -> bondStateStr = "BOND_BONDED"
184+
BluetoothDevice.BOND_BONDING -> bondStateStr = "BOND_BONDING"
185+
BluetoothDevice.BOND_NONE -> bondStateStr = "BOND_NONE"
186+
BluetoothDevice.ERROR -> bondStateStr = "BOND_ERROR"
187+
}
188+
189+
var prevBondStateStr = "UNKNOWN"
190+
when (prevState) {
191+
BluetoothDevice.BOND_BONDED -> prevBondStateStr = "BOND_BONDED"
192+
BluetoothDevice.BOND_BONDING -> prevBondStateStr = "BOND_BONDING"
193+
BluetoothDevice.BOND_NONE -> prevBondStateStr = "BOND_NONE"
194+
BluetoothDevice.ERROR -> bondStateStr = "BOND_ERROR"
195+
}
196+
Log.d(LOG_TAG, "bond state: $bondStateStr")
197+
Log.d(LOG_TAG, "bond state: $prevBondStateStr")
198+
199+
val bond = Arguments.createMap()
200+
bond.putString("state", bondStateStr)
201+
bond.putString("preState", prevBondStateStr)
202+
203+
val peripheral = Peripheral(device!!)
204+
val map = peripheral.asWritableMap()
205+
map.putMap("bondState", bond)
206+
Log.d(LOG_TAG, "onReceive BluetoothDevice BondState Change ${map}")
207+
module.emitOnDeviceBondState(map)
208+
}
209+
}
210+
}
211+
212+
companion object {
213+
const val NAME = "BleUtilsModule"
214+
const val LOG_TAG: String = "RNBleUtils"
215+
}
216+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package so.onekey.lib.ble.utils
2+
3+
import com.facebook.react.ReactPackage
4+
import com.facebook.react.bridge.NativeModule
5+
import com.facebook.react.bridge.ReactApplicationContext
6+
import com.facebook.react.uimanager.ViewManager
7+
8+
9+
class BleUtilsPackage : ReactPackage {
10+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11+
return listOf(BleUtilsModule(reactContext))
12+
}
13+
14+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15+
return emptyList()
16+
}
17+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package so.onekey.lib.ble.utils.data
2+
3+
import android.annotation.SuppressLint
4+
import android.bluetooth.BluetoothDevice
5+
import android.util.Log
6+
import com.facebook.react.bridge.Arguments
7+
import com.facebook.react.bridge.WritableMap
8+
9+
10+
class Peripheral(
11+
private val device: BluetoothDevice
12+
) {
13+
@SuppressLint("MissingPermission")
14+
fun asWritableMap(): WritableMap {
15+
val map: WritableMap = Arguments.createMap()
16+
val advertising: WritableMap = Arguments.createMap()
17+
18+
try {
19+
map.putString("name", device.getName())
20+
map.putString("id", device.getAddress()) // mac address
21+
22+
val name: String = device.getName()
23+
if (name != null) advertising.putString("localName", name)
24+
25+
// No scanResult to access so we can't check if peripheral is connectable
26+
advertising.putBoolean("isConnectable", true)
27+
28+
map.putMap("advertising", advertising)
29+
} catch (e: Exception) { // this shouldn't happen
30+
Log.e("BleUtils", "Unexpected error on asWritableMap", e)
31+
}
32+
33+
return map
34+
}
35+
}

package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"name": "@onekeyfe/react-native-ble-utils",
3-
"version": "0.1.0",
3+
"version": "0.1.1",
44
"description": "ble uilts",
55
"source": "./src/index.tsx",
6-
"main": "./lib/commonjs/index.js",
7-
"module": "./lib/module/index.js",
6+
"main": "./dist/commonjs/index.js",
7+
"module": "./dist/module/index.js",
88
"react-native": "src/index.ts",
9-
"types": "./lib/typescript/module/src/index.d.ts",
9+
"types": "./dist/typescript/module/src/index.d.ts",
1010
"files": [
1111
"src",
12-
"lib",
12+
"dist",
1313
"android",
1414
"ios",
1515
"cpp",
@@ -31,7 +31,7 @@
3131
"test": "jest",
3232
"typecheck": "tsc",
3333
"lint": "eslint \"**/*.{js,ts,tsx}\"",
34-
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
34+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build dist",
3535
"prepare": "bob build",
3636
"release": "release-it"
3737
},
@@ -90,7 +90,7 @@
9090
"preset": "react-native",
9191
"modulePathIgnorePatterns": [
9292
"<rootDir>/example/node_modules",
93-
"<rootDir>/lib/"
93+
"<rootDir>/dist/"
9494
]
9595
},
9696
"commitlint": {
@@ -137,7 +137,7 @@
137137
},
138138
"eslintIgnore": [
139139
"node_modules/",
140-
"lib/"
140+
"dist/"
141141
],
142142
"prettier": {
143143
"quoteProps": "consistent",
@@ -148,7 +148,7 @@
148148
},
149149
"react-native-builder-bob": {
150150
"source": "src",
151-
"output": "lib",
151+
"output": "dist",
152152
"targets": [
153153
[
154154
"commonjs",

tsconfig.build.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"extends": "./tsconfig",
3-
"exclude": ["example", "lib"]
3+
"exclude": ["example", "dist"]
44
}

0 commit comments

Comments
 (0)