@magicred-1/ble-mesh 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +394 -0
- package/android/build.gradle +94 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +18 -0
- package/android/src/main/AndroidManifestNew.xml +17 -0
- package/android/src/main/java/com/blemesh/BleMeshModule.kt +1994 -0
- package/android/src/main/java/com/blemesh/BleMeshPackage.kt +16 -0
- package/ios/BleMesh.m +49 -0
- package/ios/BleMesh.swift +1838 -0
- package/kard-network-ble-mesh.podspec +27 -0
- package/lib/commonjs/index.js +275 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/index.js +270 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/index.d.ts +178 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/package.json +99 -0
- package/src/index.ts +448 -0
package/README.md
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# kard-network-ble-mesh
|
|
2
|
+
|
|
3
|
+
A React Native library for BLE (Bluetooth Low Energy) mesh networking. Build decentralized, peer-to-peer messaging apps that work without internet connectivity.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Cross-platform**: Works on both iOS and Android
|
|
8
|
+
- **Mesh networking**: Messages automatically relay through peers
|
|
9
|
+
- **End-to-end encryption**: Noise protocol for secure private messages
|
|
10
|
+
- **File transfer**: Send files over BLE mesh (chunked for reliability)
|
|
11
|
+
- **Solana transactions**: Multi-signature transaction signing over BLE
|
|
12
|
+
- **Seamless permissions**: Handles permission requests automatically
|
|
13
|
+
- **Message deduplication**: Built-in deduplication prevents duplicate messages
|
|
14
|
+
- **Peer discovery**: Automatic discovery of nearby devices
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install kard-network-ble-mesh
|
|
20
|
+
# or
|
|
21
|
+
yarn add kard-network-ble-mesh
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### iOS
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cd ios && pod install
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Add the following to your `Info.plist`:
|
|
31
|
+
|
|
32
|
+
```xml
|
|
33
|
+
<key>NSBluetoothAlwaysUsageDescription</key>
|
|
34
|
+
<string>This app uses Bluetooth to communicate with nearby devices</string>
|
|
35
|
+
<key>NSBluetoothPeripheralUsageDescription</key>
|
|
36
|
+
<string>This app uses Bluetooth to communicate with nearby devices</string>
|
|
37
|
+
<key>UIBackgroundModes</key>
|
|
38
|
+
<array>
|
|
39
|
+
<string>bluetooth-central</string>
|
|
40
|
+
<string>bluetooth-peripheral</string>
|
|
41
|
+
</array>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Android
|
|
45
|
+
|
|
46
|
+
Add the following permissions to your `AndroidManifest.xml` (they are already included in the library manifest):
|
|
47
|
+
|
|
48
|
+
```xml
|
|
49
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
50
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
51
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
|
52
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
53
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
54
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
55
|
+
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import { BleMesh } from 'kard-network-ble-mesh';
|
|
62
|
+
|
|
63
|
+
// Start the mesh service (automatically requests permissions)
|
|
64
|
+
await BleMesh.start({ nickname: 'Alice' });
|
|
65
|
+
|
|
66
|
+
// Listen for events
|
|
67
|
+
BleMesh.onPeerListUpdated(({ peers }) => {
|
|
68
|
+
console.log('Connected peers:', peers);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
BleMesh.onMessageReceived(({ message }) => {
|
|
72
|
+
console.log('Received message:', message);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Send a public broadcast message
|
|
76
|
+
await BleMesh.sendMessage('Hello everyone!');
|
|
77
|
+
|
|
78
|
+
// Send a private encrypted message
|
|
79
|
+
await BleMesh.sendPrivateMessage('Secret message', recipientPeerId);
|
|
80
|
+
|
|
81
|
+
// Get current peers
|
|
82
|
+
const peers = await BleMesh.getPeers();
|
|
83
|
+
|
|
84
|
+
// Stop the service
|
|
85
|
+
await BleMesh.stop();
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## API Reference
|
|
89
|
+
|
|
90
|
+
### BleMesh
|
|
91
|
+
|
|
92
|
+
The main singleton instance for interacting with the BLE mesh.
|
|
93
|
+
|
|
94
|
+
#### Methods
|
|
95
|
+
|
|
96
|
+
##### `start(config?: MeshServiceConfig): Promise<void>`
|
|
97
|
+
|
|
98
|
+
Starts the mesh service. Automatically requests required permissions.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
interface MeshServiceConfig {
|
|
102
|
+
nickname?: string; // Default: 'anon'
|
|
103
|
+
autoRequestPermissions?: boolean; // Default: true
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
##### `stop(): Promise<void>`
|
|
108
|
+
|
|
109
|
+
Stops the mesh service and disconnects from all peers.
|
|
110
|
+
|
|
111
|
+
##### `setNickname(nickname: string): Promise<void>`
|
|
112
|
+
|
|
113
|
+
Updates your nickname and broadcasts the change to peers.
|
|
114
|
+
|
|
115
|
+
##### `getMyPeerId(): Promise<string>`
|
|
116
|
+
|
|
117
|
+
Returns your unique peer ID (derived from your public key fingerprint).
|
|
118
|
+
|
|
119
|
+
##### `getMyNickname(): Promise<string>`
|
|
120
|
+
|
|
121
|
+
Returns your current nickname.
|
|
122
|
+
|
|
123
|
+
##### `getPeers(): Promise<Peer[]>`
|
|
124
|
+
|
|
125
|
+
Returns an array of all discovered peers.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface Peer {
|
|
129
|
+
peerId: string;
|
|
130
|
+
nickname: string;
|
|
131
|
+
isConnected: boolean;
|
|
132
|
+
rssi?: number;
|
|
133
|
+
lastSeen: number;
|
|
134
|
+
isVerified: boolean;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
##### `sendMessage(content: string, channel?: string): Promise<string>`
|
|
139
|
+
|
|
140
|
+
Sends a public broadcast message. Returns the message ID.
|
|
141
|
+
|
|
142
|
+
##### `sendPrivateMessage(content: string, recipientPeerId: string): Promise<string>`
|
|
143
|
+
|
|
144
|
+
Sends an encrypted private message to a specific peer. Returns the message ID.
|
|
145
|
+
|
|
146
|
+
##### `sendReadReceipt(messageId: string, recipientPeerId: string): Promise<void>`
|
|
147
|
+
|
|
148
|
+
Sends a read receipt for a received message.
|
|
149
|
+
|
|
150
|
+
##### `sendFile(filePath: string, options?: { recipientPeerId?: string; channel?: string }): Promise<string>`
|
|
151
|
+
|
|
152
|
+
Sends a file over the mesh network. Files are automatically chunked for reliable transmission.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// Send to all peers (broadcast)
|
|
156
|
+
await BleMesh.sendFile('/path/to/photo.jpg');
|
|
157
|
+
|
|
158
|
+
// Send to specific peer
|
|
159
|
+
await BleMesh.sendFile('/path/to/document.pdf', { recipientPeerId: 'abc123' });
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
##### `sendTransaction(serializedTransaction: string, options): Promise<string>`
|
|
163
|
+
|
|
164
|
+
Sends a Solana transaction for any peer to sign as the second signer. Perfect for multi-signature transactions.
|
|
165
|
+
|
|
166
|
+
**Targeted (specific peer):**
|
|
167
|
+
```typescript
|
|
168
|
+
await BleMesh.sendTransaction(base64SerializedTx, {
|
|
169
|
+
recipientPeerId: 'abc123', // Send to specific peer (optional)
|
|
170
|
+
firstSignerPublicKey: senderPubKey,
|
|
171
|
+
secondSignerPublicKey: recipientPubKey, // Preferred signer (optional)
|
|
172
|
+
description: 'Payment for services'
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Broadcast (any peer can sign):**
|
|
177
|
+
```typescript
|
|
178
|
+
// Broadcast to all peers - any peer can sign
|
|
179
|
+
await BleMesh.sendTransaction(base64SerializedTx, {
|
|
180
|
+
firstSignerPublicKey: senderPubKey,
|
|
181
|
+
// No recipientPeerId - broadcasts to all
|
|
182
|
+
// No secondSignerPublicKey - open for any signer
|
|
183
|
+
description: 'Open offer - anyone can complete'
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
##### `respondToTransaction(transactionId: string, recipientPeerId: string, response): Promise<void>`
|
|
188
|
+
|
|
189
|
+
Responds to a received transaction with the signed transaction or an error.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
// Approve and sign
|
|
193
|
+
await BleMesh.respondToTransaction(txId, senderPeerId, {
|
|
194
|
+
signedTransaction: fullySignedBase64Tx
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Reject
|
|
198
|
+
await BleMesh.respondToTransaction(txId, senderPeerId, {
|
|
199
|
+
error: 'User rejected transaction'
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
##### `hasEncryptedSession(peerId: string): Promise<boolean>`
|
|
204
|
+
|
|
205
|
+
Checks if an encrypted session exists with the specified peer.
|
|
206
|
+
|
|
207
|
+
##### `initiateHandshake(peerId: string): Promise<void>`
|
|
208
|
+
|
|
209
|
+
Initiates a Noise handshake with a peer for encrypted communication.
|
|
210
|
+
|
|
211
|
+
##### `getIdentityFingerprint(): Promise<string>`
|
|
212
|
+
|
|
213
|
+
Returns your identity fingerprint for verification.
|
|
214
|
+
|
|
215
|
+
##### `getPeerFingerprint(peerId: string): Promise<string | null>`
|
|
216
|
+
|
|
217
|
+
Returns a peer's identity fingerprint for verification.
|
|
218
|
+
|
|
219
|
+
##### `broadcastAnnounce(): Promise<void>`
|
|
220
|
+
|
|
221
|
+
Forces a broadcast announce to refresh your presence on the mesh.
|
|
222
|
+
|
|
223
|
+
#### Events
|
|
224
|
+
|
|
225
|
+
##### `onPeerListUpdated(callback): () => void`
|
|
226
|
+
|
|
227
|
+
Called when the peer list changes.
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
BleMesh.onPeerListUpdated(({ peers }) => {
|
|
231
|
+
console.log('Peers updated:', peers);
|
|
232
|
+
});
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
##### `onMessageReceived(callback): () => void`
|
|
236
|
+
|
|
237
|
+
Called when a message is received.
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
BleMesh.onMessageReceived(({ message }) => {
|
|
241
|
+
console.log('Message from', message.senderNickname, ':', message.content);
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
##### `onConnectionStateChanged(callback): () => void`
|
|
246
|
+
|
|
247
|
+
Called when the connection state changes.
|
|
248
|
+
|
|
249
|
+
##### `onReadReceipt(callback): () => void`
|
|
250
|
+
|
|
251
|
+
Called when a read receipt is received.
|
|
252
|
+
|
|
253
|
+
##### `onDeliveryAck(callback): () => void`
|
|
254
|
+
|
|
255
|
+
Called when a delivery acknowledgment is received.
|
|
256
|
+
|
|
257
|
+
##### `onFileReceived(callback): () => void`
|
|
258
|
+
|
|
259
|
+
Called when a file is received.
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
BleMesh.onFileReceived(({ file }) => {
|
|
263
|
+
console.log('Received file:', file.fileName);
|
|
264
|
+
console.log('Size:', file.fileSize);
|
|
265
|
+
console.log('Data (base64):', file.data);
|
|
266
|
+
// Save or display the file...
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
##### `onTransactionReceived(callback): () => void`
|
|
271
|
+
|
|
272
|
+
Called when a Solana transaction is received for signing.
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
BleMesh.onTransactionReceived(({ transaction }) => {
|
|
276
|
+
console.log('Transaction to sign:', transaction.id);
|
|
277
|
+
console.log('Serialized:', transaction.serializedTransaction);
|
|
278
|
+
console.log('First signer:', transaction.firstSignerPublicKey);
|
|
279
|
+
|
|
280
|
+
// Check if a specific second signer is required
|
|
281
|
+
if (transaction.secondSignerPublicKey) {
|
|
282
|
+
console.log('Required second signer:', transaction.secondSignerPublicKey);
|
|
283
|
+
// Verify this is your public key before signing
|
|
284
|
+
} else if (transaction.openForAnySigner) {
|
|
285
|
+
console.log('Any peer can sign this transaction');
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Sign with your wallet...
|
|
289
|
+
const signedTx = await yourWallet.signTransaction(transaction.serializedTransaction);
|
|
290
|
+
|
|
291
|
+
// Respond
|
|
292
|
+
await BleMesh.respondToTransaction(transaction.id, transaction.senderPeerId, {
|
|
293
|
+
signedTransaction: signedTx
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
##### `onTransactionResponse(callback): () => void`
|
|
299
|
+
|
|
300
|
+
Called when a transaction response is received (signed or rejected).
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
BleMesh.onTransactionResponse(({ response }) => {
|
|
304
|
+
if (response.signedTransaction) {
|
|
305
|
+
console.log('Transaction fully signed!');
|
|
306
|
+
// Broadcast to Solana network...
|
|
307
|
+
} else if (response.error) {
|
|
308
|
+
console.log('Transaction rejected:', response.error);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
##### `onError(callback): () => void`
|
|
314
|
+
|
|
315
|
+
Called when an error occurs.
|
|
316
|
+
|
|
317
|
+
## Solana Multi-Signature Transaction Flow
|
|
318
|
+
|
|
319
|
+
### Targeted Transaction (Specific Peer)
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
Alice (First Signer) Bob (Second Signer)
|
|
323
|
+
| |
|
|
324
|
+
| 1. Create transaction |
|
|
325
|
+
| 2. Sign with Alice's key |
|
|
326
|
+
| 3. Send via BleMesh.sendTransaction() |
|
|
327
|
+
| with recipientPeerId |
|
|
328
|
+
|--------------------------------------->|
|
|
329
|
+
| |
|
|
330
|
+
| 4. onTransactionReceived event |
|
|
331
|
+
|<---------------------------------------|
|
|
332
|
+
| |
|
|
333
|
+
| 5. Review & sign with Bob's key |
|
|
334
|
+
|<---------------------------------------|
|
|
335
|
+
| |
|
|
336
|
+
| 6. respondToTransaction() |
|
|
337
|
+
|--------------------------------------->|
|
|
338
|
+
| |
|
|
339
|
+
| 7. Broadcast fully signed tx |
|
|
340
|
+
v to Solana network v
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Broadcast Transaction (Any Peer Can Sign)
|
|
344
|
+
|
|
345
|
+
```
|
|
346
|
+
Alice (First Signer) Bob Carol Dave
|
|
347
|
+
| | | |
|
|
348
|
+
| 1. Create tx | | |
|
|
349
|
+
| 2. Sign | | |
|
|
350
|
+
| 3. Broadcast | | |
|
|
351
|
+
|---------------------->|------------>|------------>|
|
|
352
|
+
| | | |
|
|
353
|
+
| | 4. All receive |
|
|
354
|
+
| | onTransactionReceived |
|
|
355
|
+
| | | |
|
|
356
|
+
| | 5. Carol decides to sign |
|
|
357
|
+
| | | |
|
|
358
|
+
| |<------------|------------>|
|
|
359
|
+
| | 6. Carol responds |
|
|
360
|
+
|<----------------------|-------------|-------------|
|
|
361
|
+
| | | |
|
|
362
|
+
| 7. Alice receives | | |
|
|
363
|
+
| signed tx | | |
|
|
364
|
+
v v v v
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### MTU and Transaction Size Limits
|
|
368
|
+
|
|
369
|
+
The library automatically handles BLE MTU limitations:
|
|
370
|
+
|
|
371
|
+
| Feature | Max Size | Handling |
|
|
372
|
+
|---------|----------|----------|
|
|
373
|
+
| Simple messages | ~450 bytes | Single packet |
|
|
374
|
+
| Small transactions | ~450 bytes | Single packet |
|
|
375
|
+
| Large transactions | Unlimited | Automatic chunking (400 byte chunks) |
|
|
376
|
+
| Files | Unlimited | Chunked (180 byte chunks) |
|
|
377
|
+
|
|
378
|
+
**For Solana transactions:**
|
|
379
|
+
- Most transactions (simple transfers) fit in a single packet
|
|
380
|
+
- Complex transactions (multi-instruction, large memos) are automatically chunked
|
|
381
|
+
- Chunking is transparent to the application layer
|
|
382
|
+
- The receiver automatically reassembles chunks before decrypting
|
|
383
|
+
|
|
384
|
+
## Protocol Compatibility
|
|
385
|
+
|
|
386
|
+
This library uses the same binary protocol as:
|
|
387
|
+
- [bitchat (iOS)](https://github.com/permissionlesstech/bitchat)
|
|
388
|
+
- [bitchat-android](https://github.com/permissionlesstech/bitchat-android)
|
|
389
|
+
|
|
390
|
+
Messages can be exchanged between all three platforms.
|
|
391
|
+
|
|
392
|
+
## License
|
|
393
|
+
|
|
394
|
+
MIT
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath "com.android.tools.build:gradle:8.1.0"
|
|
9
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.0"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
def isNewArchitectureEnabled() {
|
|
14
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
apply plugin: "com.android.library"
|
|
18
|
+
apply plugin: "kotlin-android"
|
|
19
|
+
|
|
20
|
+
def getExtOrDefault(name) {
|
|
21
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["BleMesh_" + name]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def getExtOrIntegerDefault(name) {
|
|
25
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["BleMesh_" + name]).toInteger()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def supportsNamespace() {
|
|
29
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
30
|
+
def major = parsed[0].toInteger()
|
|
31
|
+
def minor = parsed[1].toInteger()
|
|
32
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
android {
|
|
36
|
+
if (supportsNamespace()) {
|
|
37
|
+
namespace "com.blemesh"
|
|
38
|
+
|
|
39
|
+
sourceSets {
|
|
40
|
+
main {
|
|
41
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
47
|
+
|
|
48
|
+
defaultConfig {
|
|
49
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
50
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
51
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
buildFeatures {
|
|
55
|
+
buildConfig true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
buildTypes {
|
|
59
|
+
release {
|
|
60
|
+
minifyEnabled false
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
lintOptions {
|
|
65
|
+
disable "GradleCompatible"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
compileOptions {
|
|
69
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
70
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
kotlinOptions {
|
|
74
|
+
jvmTarget = "17"
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
sourceSets {
|
|
78
|
+
main {
|
|
79
|
+
java.srcDirs = ['src/main/java']
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
repositories {
|
|
85
|
+
mavenCentral()
|
|
86
|
+
google()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
dependencies {
|
|
90
|
+
implementation "com.facebook.react:react-android"
|
|
91
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.0"
|
|
92
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
|
|
93
|
+
implementation "androidx.core:core-ktx:1.12.0"
|
|
94
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
package="com.blemesh">
|
|
3
|
+
|
|
4
|
+
<!-- BLE Permissions -->
|
|
5
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
6
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
7
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
|
8
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
9
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
10
|
+
|
|
11
|
+
<!-- Location Permissions (required for BLE scanning) -->
|
|
12
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
13
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
14
|
+
|
|
15
|
+
<!-- Declare BLE feature -->
|
|
16
|
+
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
17
|
+
|
|
18
|
+
</manifest>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
|
|
3
|
+
<!-- BLE Permissions -->
|
|
4
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
5
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
6
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
|
7
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
8
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
9
|
+
|
|
10
|
+
<!-- Location Permissions (required for BLE scanning) -->
|
|
11
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
12
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
13
|
+
|
|
14
|
+
<!-- Declare BLE feature -->
|
|
15
|
+
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
16
|
+
|
|
17
|
+
</manifest>
|