@microbit/capacitor-community-nordic-dfu 7.0.0-microbit.1

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.
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapacitorCommunityNordicDfu'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '14.0'
15
+ s.dependency 'Capacitor'
16
+ s.swift_version = '5.1'
17
+ s.dependency 'NordicDFU', '~> 4.16.0'
18
+ end
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) COPYRIGHT_YEAR COPYRIGHT_HOLDER
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,290 @@
1
+ <p align="center"><br><img src="https://user-images.githubusercontent.com/236501/85893648-1c92e880-b7a8-11ea-926d-95355b8175c7.png" width="128" height="128" /></p>
2
+ <h3 align="center">Nordic DFU</h3>
3
+ <p align="center"><strong><code>capacitor-community-nordic-dfu</code></strong></p>
4
+ <p align="center">
5
+ Capacitor plugin to interface with Nordic DFU's <a href="https://github.com/NordicSemiconductor/IOS-DFU-Library">IOS-DFU-Library</a> and <a href="https://github.com/NordicSemiconductor/Android-DFU-Library">Android-DFU-Library</a>.
6
+ </p>
7
+
8
+ <p align="center">
9
+ <img
10
+ alt="Maintenance status"
11
+ src="https://img.shields.io/maintenance/yes/2025?style=flat-square"/>
12
+ <a
13
+ href="https://github.com/robsonos/nordic-dfu/actions/workflows/ci.yml"
14
+ style="color: inherit; text-decoration: none;">
15
+ <img
16
+ alt="GitHub Workflow Status (with event)"
17
+ src="https://img.shields.io/github/actions/workflow/status/robsonos/nordic-dfu/ci.yml"/>
18
+ </a>
19
+ <a
20
+ href="https://www.npmjs.com/package/capacitor-community-nordic-dfu"
21
+ style="color: inherit; text-decoration: none;">
22
+ <img
23
+ alt="GitHub License"
24
+ src="https://img.shields.io/npm/l/capacitor-community-nordic-dfu?style=flat-square"/>
25
+ </a>
26
+ <br />
27
+ <a
28
+ href="https://www.npmjs.com/package/capacitor-community-nordic-dfu"
29
+ style="color: inherit; text-decoration: none;">
30
+ <img
31
+ alt="Version from npmjs"
32
+ src="https://img.shields.io/npm/v/capacitor-community-nordic-dfu?style=flat-square"/>
33
+ </a>
34
+ <a
35
+ href="https://www.npmjs.com/package/capacitor-community-nordic-dfu"
36
+ style="color: inherit; text-decoration: none;">
37
+ <img
38
+ alt="Downloads from npmjs"
39
+ src="https://img.shields.io/npm/dw/capacitor-community-nordic-dfu?style=flat-square"/>
40
+ </a>
41
+ <a href="#contributors"
42
+ style="color: inherit; text-decoration: none;">
43
+ <img
44
+ alt="GitHub contributors from allcontributors.org"
45
+ src="https://img.shields.io/github/all-contributors/robsonos/nordic-dfu">
46
+ </a>
47
+ </p>
48
+
49
+ ## Table of Contents
50
+
51
+ - [Maintainers](#maintainers)
52
+ - [Installation](#installation)
53
+ - [Permissions](#permissions)
54
+ - [API](#api)
55
+ - [Contributors](#contributors)
56
+
57
+ ## Maintainers
58
+
59
+ | Maintainer | GitHub | Active |
60
+ | ---------- | --------------------------------------- | ------ |
61
+ | robsonos | [robsonos](https://github.com/robsonos) | yes |
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ npm install capacitor-community-nordic-dfu
67
+ npx cap sync
68
+ ```
69
+
70
+ ## Permissions
71
+
72
+ Please check the sample permissions in [Android](./example/android/app/src/main/AndroidManifest.xml) and [iOS](./example/ios/App/App/Info.plist) folders.
73
+
74
+ ## API
75
+
76
+ <docgen-index>
77
+
78
+ - [`startDFU(...)`](#startdfu)
79
+ - [`checkPermissions()`](#checkpermissions)
80
+ - [`requestPermissions()`](#requestpermissions)
81
+ - [`addListener('DFUStateChanged', ...)`](#addlistenerdfustatechanged-)
82
+ - [`removeAllListeners()`](#removealllisteners)
83
+ - [Interfaces](#interfaces)
84
+ - [Type Aliases](#type-aliases)
85
+ - [Enums](#enums)
86
+
87
+ </docgen-index>
88
+
89
+ <docgen-api>
90
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
91
+
92
+ Defines the plugin for handling Nordic DFU processes.
93
+ Includes methods to start the DFU process, check permissions, and manage event listeners.
94
+
95
+ ### startDFU(...)
96
+
97
+ ```typescript
98
+ startDFU(dfuUpdateOptions: DfuUpdateOptions) => Promise<void | PluginResultError>
99
+ ```
100
+
101
+ Initiates the DFU process with the specified options.
102
+
103
+ | Param | Type | Description |
104
+ | ---------------------- | ------------------------------------------------------------- | ---------------------------- |
105
+ | **`dfuUpdateOptions`** | <code><a href="#dfuupdateoptions">DfuUpdateOptions</a></code> | Options for the DFU process. |
106
+
107
+ **Returns:** <code>Promise&lt;void | <a href="#pluginresulterror">PluginResultError</a>&gt;</code>
108
+
109
+ **Since:** 1.0.0
110
+
111
+ ---
112
+
113
+ ### checkPermissions()
114
+
115
+ ```typescript
116
+ checkPermissions() => Promise<PermissionStatus>
117
+ ```
118
+
119
+ Check status of permissions needed by the plugin
120
+
121
+ **Returns:** <code>Promise&lt;<a href="#permissionstatus">PermissionStatus</a>&gt;</code>
122
+
123
+ **Since:** 1.0.0
124
+
125
+ ---
126
+
127
+ ### requestPermissions()
128
+
129
+ ```typescript
130
+ requestPermissions() => Promise<PermissionStatus>
131
+ ```
132
+
133
+ Request permissions needed by the plugin
134
+
135
+ **Returns:** <code>Promise&lt;<a href="#permissionstatus">PermissionStatus</a>&gt;</code>
136
+
137
+ **Since:** 1.0.0
138
+
139
+ ---
140
+
141
+ ### addListener('DFUStateChanged', ...)
142
+
143
+ ```typescript
144
+ addListener(eventName: 'DFUStateChanged', handler: (update: DfuUpdate) => void) => Promise<PluginListenerHandle> & PluginListenerHandle
145
+ ```
146
+
147
+ Listen for when the DFU state changes
148
+
149
+ | Param | Type | Description |
150
+ | --------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------- |
151
+ | **`eventName`** | <code>'DFUStateChanged'</code> | The name of the event to listen for |
152
+ | **`handler`** | <code>(update: <a href="#dfuupdate">DfuUpdate</a>) =&gt; void</code> | The handler function that will be called when the event is fired |
153
+
154
+ **Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt; & <a href="#pluginlistenerhandle">PluginListenerHandle</a></code>
155
+
156
+ **Since:** 1.0.0
157
+
158
+ ---
159
+
160
+ ### removeAllListeners()
161
+
162
+ ```typescript
163
+ removeAllListeners() => Promise<void>
164
+ ```
165
+
166
+ Removes all listeners for the DFUStateChanged event
167
+
168
+ **Since:** 1.0.0
169
+
170
+ ---
171
+
172
+ ### Interfaces
173
+
174
+ #### PluginResultError
175
+
176
+ | Prop | Type |
177
+ | ------------- | ------------------- |
178
+ | **`message`** | <code>string</code> |
179
+
180
+ #### DfuUpdateOptions
181
+
182
+ Specifies the options required for initiating the DFU process.
183
+
184
+ | Prop | Type | Description | Since |
185
+ | ------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----- |
186
+ | **`deviceAddress`** | <code>string</code> | The target device address. On **Android** this is the BLE MAC address. On **iOS** and **web** it is a randomly generated UUID identifier. | 1.0.0 |
187
+ | **`deviceName`** | <code>string</code> | The name of the device | 1.0.0 |
188
+ | **`filePath`** | <code>string</code> | The path to the firmware file | 1.0.0 |
189
+ | **`dfuOptions`** | <code><a href="#dfuoptions">DfuOptions</a></code> | The additional options for the DFU process | 1.0.0 |
190
+
191
+ #### DfuOptions
192
+
193
+ Outlines additional options for configuring the DFU process.
194
+
195
+ | Prop | Type | Description | Default | Since |
196
+ | ----------------------------------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
197
+ | **`disableNotification`** | <code>boolean</code> | Sets whether the progress notification in the status bar should be disabled. | <code>false</code> | 1.0.0 |
198
+ | **`startAsForegroundService`** | <code>boolean</code> | Sets whether the progress notification in the status bar should be disabled. | <code>false</code> | 1.0.0 |
199
+ | **`keepBond`** | <code>boolean</code> | Sets whether the bond information should be preserver after flashing new application. | <code>false</code> | 1.0.0 |
200
+ | **`restoreBond`** | <code>boolean</code> | Sets whether a new bond should be created after the DFU is complete. The old bond information will be removed before. | <code>false</code> | 1.0.0 |
201
+ | **`dataObjectDelay`** | <code>number</code> | Sets the initial delay (in milliseconds) that the service will wait before sending each data object. | <code>0</code> | 1.0.0 |
202
+ | **`packetReceiptNotificationsEnabled`** | <code>boolean</code> | Enables or disables the Packet Receipt Notification (PRN) procedure. By default the PRNs are disabled on devices with Android Marshmallow or newer and enabled on older ones. | | 1.0.0 |
203
+ | **`packetsReceiptNotificationsValue`** | <code>number</code> | If Packet Receipt Notification procedure is enabled, this method sets the number of packets to be sent before receiving a PRN. | <code>12</code> | 1.0.0 |
204
+ | **`forceDfu`** | <code>boolean</code> | Setting force DFU to true will prevent from jumping to the DFU Bootloader mode in case there is no DFU Version characteristic (Legacy DFU only!). Use this if the DFU operation can be handled by your device running in the application mode. This method is ignored in Secure DFU. | <code>false</code> | 1.0.0 |
205
+ | **`rebootTime`** | <code>number</code> | Sets the time (in milliseconds) required by the device to reboot. The library will wait for this time before scanning for the device in bootloader mode. | <code>0</code> | 1.0.0 |
206
+ | **`scanTimeout`** | <code>number</code> | Sets the scan duration (in milliseconds) when scanning for DFU Bootloader. | <code>5000</code> | 1.0.0 |
207
+ | **`forceScanningForNewAddressInLegacyDfu`** | <code>boolean</code> | When this is set to true, the Legacy Buttonless Service will scan for the device advertising with an incremented MAC address, instead of trying to reconnect to the same device. | <code>false</code> | 1.0.0 |
208
+ | **`disableResume`** | <code>boolean</code> | This options allows to disable the resume feature in Secure DFU. When the extra value is set to true, the DFU will send Init Packet and Data again, despite the firmware might have been send partially before. By default, without setting this extra, or by setting it to false, the DFU will resume the previously cancelled upload if CRC values match. | <code>false</code> | 1.4.0 |
209
+ | **`numberOfRetries`** | <code>number</code> | Sets the number of retries that the DFU service will use to complete DFU. | <code>0</code> | 1.0.0 |
210
+ | **`mtu`** | <code>number</code> | Sets the Maximum Transfer Unit (MTU) value that the Secure DFU service will try to request before performing DFU. **Available for Android only.** By default, value 517 will be used, which is the highest supported y Android. However, as the highest supported MTU by the Secure DFU from SDK 15 (first which supports higher MTU) is 247, the sides will agree on using MTU = 247 instead if the phone supports it (Lollipop or newer device). | | 1.0.0 |
211
+ | **`currentMtu`** | <code>number</code> | Sets the current MTU value. This method should be used only if the device is already connected and MTU has been requested before DFU service is started. **Available for Android only.** | <code>23</code> | 1.0.0 |
212
+ | **`disableMtuRequest`** | <code>boolean</code> | Disables MTU request. **Available for Android only.** | <code>false</code> | 1.4.0 |
213
+ | **`scope`** | <code>number</code> | This method allows to narrow the update to selected parts from the ZIP, for example to allow only application update from a ZIP file that has SD+BL+App. System components scope include the Softdevice and/or the Bootloader (they can't be separated as they are packed in a single bin file and the library does not know whether it contains only the softdevice, the bootloader or both) Application scope includes the application only. | | 1.0.0 |
214
+ | **`mbrSize`** | <code>number</code> | This method sets the size of an MBR (Master Boot Record). It should be used only when updating a file from a HEX file. If you use BIN or ZIP, value set here will be ignored. | <code>4096</code> | 1.0.0 |
215
+ | **`unsafeExperimentalButtonlessServiceInSecureDfuEnabled`** | <code>boolean</code> | Set this flag to true to enable experimental buttonless feature in Secure DFU. When the experimental Buttonless DFU Service is found on a device, the service will use it to switch the device to the bootloader mode, connect to it in that mode and proceed with DFU. | <code>false</code> | 1.0.0 |
216
+
217
+ #### PermissionStatus
218
+
219
+ Represents the current status of permissions in the plugin.
220
+
221
+ | Prop | Type | Description | Since |
222
+ | ------------------- | ----------------------------------------------------------- | ------------------------------------------------ | ----- |
223
+ | **`notifications`** | <code><a href="#permissionstate">PermissionState</a></code> | Indicates the permission state of notifications. | 1.0.0 |
224
+
225
+ #### PluginListenerHandle
226
+
227
+ | Prop | Type |
228
+ | ------------ | ----------------------------------------- |
229
+ | **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |
230
+
231
+ #### DfuUpdate
232
+
233
+ The DFU update object that is passed to the DFUStateChanged event
234
+
235
+ | Prop | Type | Description | Since |
236
+ | ----------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------ | ----- |
237
+ | **`state`** | <code><a href="#dfustate">DfuState</a></code> | Defines the structure for the DFU update object passed to the DFUStateChanged event. | 1.0.0 |
238
+ | **`data`** | <code><a href="#dfuupdatedata">DfuUpdateData</a></code> | The DFU data that is passed to the <a href="#dfuupdate">DfuUpdate</a> object | 1.0.0 |
239
+
240
+ #### DfuUpdateData
241
+
242
+ Contains data related to the DFU update process, such as progress and speed.
243
+
244
+ | Prop | Type | Description | Since |
245
+ | ------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
246
+ | **`percent`** | <code>number</code> | The current status of upload (0-99). | 1.0.0 |
247
+ | **`speed`** | <code>number</code> | The current speed in bytes per millisecond. | 1.0.0 |
248
+ | **`avgSpeed`** | <code>number</code> | The average speed in bytes per millisecond. | 1.0.0 |
249
+ | **`currentPart`** | <code>number</code> | The number of parts being sent. In case the ZIP file contains a Soft Device and/or a Bootloader together with the application the SD+BL are sent as part 1, then the service starts again and send the application as part 2. | 1.0.0 |
250
+ | **`partsTotal`** | <code>number</code> | The total number of parts. | 1.0.0 |
251
+ | **`duration`** | <code>number</code> | The total time elapsed since the start of the DFU process in milliseconds | 1.1.0 |
252
+ | **`remainingTime`** | <code>number</code> | The estimated remaining time to the end of the DFU process in milliseconds | 1.1.0 |
253
+
254
+ ### Type Aliases
255
+
256
+ #### PermissionState
257
+
258
+ <code>'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'</code>
259
+
260
+ ### Enums
261
+
262
+ #### DfuState
263
+
264
+ | Members | Value | Description | Since |
265
+ | -------------------------- | ----------------------------------- | ---------------------------------------------------------------------- | ----- |
266
+ | **`DEVICE_CONNECTING`** | <code>'DEVICE_CONNECTING'</code> | The device is currently connecting. | 1.0.0 |
267
+ | **`DEVICE_CONNECTED`** | <code>'DEVICE_CONNECTED'</code> | The device has successfully connected. **Available for Android only.** | 1.0.0 |
268
+ | **`DFU_PROCESS_STARTING`** | <code>'DFU_PROCESS_STARTING'</code> | The DFU process is about to start. | 1.0.0 |
269
+ | **`DFU_PROCESS_STARTED`** | <code>'DFU_PROCESS_STARTED'</code> | The DFU process has started. **Available for Android only.** | 1.0.0 |
270
+ | **`ENABLING_DFU_MODE`** | <code>'ENABLING_DFU_MODE'</code> | The device is enabling DFU mode. | 1.0.0 |
271
+ | **`DFU_PROGRESS`** | <code>'DFU_PROGRESS'</code> | The DFU process is in progress. | 1.0.0 |
272
+ | **`VALIDATING_FIRMWARE`** | <code>'VALIDATING_FIRMWARE'</code> | The firmware is currently being validated. | 1.0.0 |
273
+ | **`DEVICE_DISCONNECTING`** | <code>'DEVICE_DISCONNECTING'</code> | The device is disconnecting. | 1.0.0 |
274
+ | **`DEVICE_DISCONNECTED`** | <code>'DEVICE_DISCONNECTED'</code> | The device has disconnected. **Available for Android only.** | 1.0.0 |
275
+ | **`DFU_COMPLETED`** | <code>'DFU_COMPLETED'</code> | The DFU process has completed successfully. | 1.0.0 |
276
+ | **`DFU_ABORTED`** | <code>'DFU_ABORTED'</code> | The DFU process has been aborted. | 1.0.0 |
277
+ | **`DFU_FAILED`** | <code>'DFU_FAILED'</code> | The DFU process has failed. | 1.0.0 |
278
+
279
+ </docgen-api>
280
+
281
+ ## Contributors
282
+
283
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
284
+ <!-- prettier-ignore-start -->
285
+ <!-- markdownlint-disable -->
286
+
287
+ <!-- markdownlint-restore -->
288
+ <!-- prettier-ignore-end -->
289
+
290
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
@@ -0,0 +1,69 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
4
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
5
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
6
+ }
7
+
8
+ buildscript {
9
+ ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.25'
10
+ ext.coreKtx = project.hasProperty('coreKtx') ? rootProject.ext.coreKtx : '1.12.0'
11
+
12
+ repositories {
13
+ google()
14
+ mavenCentral()
15
+ }
16
+ dependencies {
17
+ classpath 'com.android.tools.build:gradle:8.7.2'
18
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
19
+ }
20
+ }
21
+
22
+ apply plugin: 'com.android.library'
23
+ apply plugin: 'kotlin-android'
24
+
25
+ android {
26
+ namespace "com.example.plugin.nordicdfu"
27
+ compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
28
+ defaultConfig {
29
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
30
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
31
+ versionCode 1
32
+ versionName "1.0"
33
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
34
+ }
35
+ buildTypes {
36
+ release {
37
+ minifyEnabled false
38
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
39
+ }
40
+ }
41
+ lintOptions {
42
+ abortOnError false
43
+ }
44
+ compileOptions {
45
+ sourceCompatibility JavaVersion.VERSION_21
46
+ targetCompatibility JavaVersion.VERSION_21
47
+ }
48
+ kotlinOptions {
49
+ jvmTarget = 21
50
+ }
51
+ }
52
+
53
+ repositories {
54
+ google()
55
+ mavenCentral()
56
+ }
57
+
58
+
59
+ dependencies {
60
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
61
+ implementation project(':capacitor-android')
62
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
63
+ testImplementation "junit:junit:$junitVersion"
64
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
65
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
66
+ implementation "androidx.core:core-ktx:$coreKtx"
67
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
68
+ implementation "no.nordicsemi.android:dfu:2.9.0"
69
+ }
@@ -0,0 +1,13 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ xmlns:tools="http://schemas.android.com/tools">
3
+
4
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" />
5
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
6
+
7
+ <application>
8
+ <service
9
+ android:name=".DfuService"
10
+ android:foregroundServiceType="connectedDevice" />
11
+ <activity android:name=".NotificationActivity" />
12
+ </application>
13
+ </manifest>
@@ -0,0 +1,51 @@
1
+ package com.example.plugin.nordicdfu;
2
+
3
+ import android.app.Activity;
4
+ import androidx.annotation.NonNull;
5
+ import androidx.core.app.NotificationCompat;
6
+ import no.nordicsemi.android.dfu.BuildConfig;
7
+ import no.nordicsemi.android.dfu.DfuBaseService;
8
+
9
+ public class DfuService extends DfuBaseService {
10
+
11
+ @Override
12
+ protected Class<? extends Activity> getNotificationTarget() {
13
+ /*
14
+ * As a target activity the NotificationActivity is returned, not the
15
+ * MainActivity. This is because the notification must create a new task:
16
+ *
17
+ * intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
18
+ *
19
+ * when you press it. You can use NotificationActivity to check whether the new
20
+ * activity is a root activity (that means no other activity was open earlier)
21
+ * or that some other activity is already open. In the latter case the
22
+ * NotificationActivity will just be closed. The system will restore the
23
+ * previous activity. However, if the application has been closed during upload
24
+ * and you click the notification, a NotificationActivity will be launched as a
25
+ * root activity. It will create and start the main activity and terminate
26
+ * itself.
27
+ *
28
+ * This method may be used to restore the target activity in case the
29
+ * application was closed or is open. It may also be used to recreate an
30
+ * activity history using startActivities(...).
31
+ */
32
+ return NotificationActivity.class;
33
+ }
34
+
35
+ @Override
36
+ protected boolean isDebug() {
37
+ /*
38
+ * Here return true if you want the service to print more logs in LogCat.
39
+ * Library's BuildConfig in current version of Android Studio is always set to
40
+ * DEBUG=false, so make sure you return true or your.app.BuildConfig.DEBUG here.
41
+ */
42
+ return BuildConfig.DEBUG;
43
+ }
44
+
45
+ @Override
46
+ protected void updateForegroundNotification(@NonNull final NotificationCompat.Builder builder) {
47
+ /*
48
+ * Customize the foreground service notification here.
49
+ */
50
+ }
51
+ }
@@ -0,0 +1,179 @@
1
+ package com.example.plugin.nordicdfu;
2
+
3
+ import android.content.Context;
4
+ import android.os.Build;
5
+ import androidx.annotation.NonNull;
6
+ import androidx.annotation.Nullable;
7
+ import com.getcapacitor.JSObject;
8
+ import no.nordicsemi.android.dfu.DfuProgressListener;
9
+ import no.nordicsemi.android.dfu.DfuProgressListenerAdapter;
10
+ import no.nordicsemi.android.dfu.DfuServiceInitiator;
11
+ import no.nordicsemi.android.dfu.DfuServiceListenerHelper;
12
+
13
+ public class NordicDfu {
14
+
15
+ interface DfuEventListener {
16
+ void onDfuEvent(String state, @Nullable JSObject data);
17
+ }
18
+
19
+ @Nullable
20
+ public DfuEventListener getDFUEventListener() {
21
+ return dfuEventListener;
22
+ }
23
+
24
+ public void setDFUEventListener(@Nullable DfuEventListener dfuEventListener) {
25
+ this.dfuEventListener = dfuEventListener;
26
+ }
27
+
28
+ @Nullable
29
+ private DfuEventListener dfuEventListener;
30
+
31
+ private long startTime = 0;
32
+
33
+ public NordicDfu(Context context) {
34
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
35
+ DfuServiceInitiator.createDfuNotificationChannel(context);
36
+ }
37
+ }
38
+
39
+ final DfuProgressListener dfuProgressListener = new DfuProgressListenerAdapter() {
40
+ @Override
41
+ public void onDeviceConnecting(@NonNull final String deviceAddress) {
42
+ JSObject ret = new JSObject();
43
+ ret.put("deviceAddress", deviceAddress);
44
+ dfuEventListener.onDfuEvent("DEVICE_CONNECTING", ret);
45
+ }
46
+
47
+ @Override
48
+ public void onDeviceConnected(@NonNull final String deviceAddress) {
49
+ JSObject ret = new JSObject();
50
+ ret.put("deviceAddress", deviceAddress);
51
+ dfuEventListener.onDfuEvent("DEVICE_CONNECTED", ret);
52
+ }
53
+
54
+ @Override
55
+ public void onDfuProcessStarting(@NonNull final String deviceAddress) {
56
+ JSObject ret = new JSObject();
57
+ ret.put("deviceAddress", deviceAddress);
58
+ dfuEventListener.onDfuEvent("DFU_PROCESS_STARTING", ret);
59
+ }
60
+
61
+ @Override
62
+ public void onDfuProcessStarted(@NonNull final String deviceAddress) {
63
+ startTime = System.currentTimeMillis();
64
+
65
+ JSObject ret = new JSObject();
66
+ ret.put("deviceAddress", deviceAddress);
67
+ dfuEventListener.onDfuEvent("DFU_PROCESS_STARTED", ret);
68
+ }
69
+
70
+ @Override
71
+ public void onEnablingDfuMode(@NonNull final String deviceAddress) {
72
+ JSObject ret = new JSObject();
73
+ ret.put("deviceAddress", deviceAddress);
74
+ dfuEventListener.onDfuEvent("ENABLING_DFU_MODE", ret);
75
+ }
76
+
77
+ @Override
78
+ public void onProgressChanged(
79
+ @NonNull final String deviceAddress,
80
+ final int percent,
81
+ final float speed,
82
+ final float avgSpeed,
83
+ final int currentPart,
84
+ final int partsTotal
85
+ ) {
86
+ long currentTime = System.currentTimeMillis();
87
+ long duration = currentTime - startTime;
88
+ long remainingTime = 0;
89
+
90
+ if (percent > 0) {
91
+ long estimatedTotalTime = (duration * 100) / percent;
92
+ remainingTime = estimatedTotalTime - duration;
93
+ }
94
+
95
+ JSObject ret = new JSObject();
96
+ ret.put("deviceAddress", deviceAddress);
97
+ ret.put("percent", percent);
98
+ ret.put("speed", speed);
99
+ ret.put("avgSpeed", avgSpeed);
100
+ ret.put("currentPart", currentPart);
101
+ ret.put("partsTotal", partsTotal);
102
+ ret.put("duration", duration);
103
+ ret.put("remainingTime", remainingTime);
104
+ dfuEventListener.onDfuEvent("DFU_PROGRESS", ret);
105
+ }
106
+
107
+ @Override
108
+ public void onFirmwareValidating(@NonNull final String deviceAddress) {
109
+ JSObject ret = new JSObject();
110
+ ret.put("deviceAddress", deviceAddress);
111
+ dfuEventListener.onDfuEvent("VALIDATING_FIRMWARE", ret);
112
+ }
113
+
114
+ @Override
115
+ public void onDeviceDisconnecting(final String deviceAddress) {
116
+ JSObject ret = new JSObject();
117
+ ret.put("deviceAddress", deviceAddress);
118
+ dfuEventListener.onDfuEvent("DEVICE_DISCONNECTING", ret);
119
+ }
120
+
121
+ @Override
122
+ public void onDeviceDisconnected(@NonNull final String deviceAddress) {
123
+ JSObject ret = new JSObject();
124
+ ret.put("deviceAddress", deviceAddress);
125
+ dfuEventListener.onDfuEvent("DEVICE_DISCONNECTED", ret);
126
+ }
127
+
128
+ @Override
129
+ public void onDfuCompleted(@NonNull final String deviceAddress) {
130
+ JSObject ret = new JSObject();
131
+ ret.put("deviceAddress", deviceAddress);
132
+ dfuEventListener.onDfuEvent("DFU_COMPLETED", ret);
133
+ // TODO: end activity
134
+ // new Handler()
135
+ // .postDelayed(
136
+ // new Runnable() {
137
+ // @Override
138
+ // public void run() {
139
+ // // if this activity is still open and upload process was completed, cancel
140
+ // the notification
141
+ // final NotificationManager manager = (NotificationManager)
142
+ // reactContext.getSystemService(
143
+ // Context.NOTIFICATION_SERVICE
144
+ // );
145
+ // manager.cancel(DfuService.NOTIFICATION_ID);
146
+ // }
147
+ // },
148
+ // 200
149
+ // );
150
+ }
151
+
152
+ @Override
153
+ public void onDfuAborted(@NonNull final String deviceAddress) {
154
+ JSObject ret = new JSObject();
155
+ ret.put("deviceAddress", deviceAddress);
156
+ dfuEventListener.onDfuEvent("DFU_ABORTED", ret);
157
+ }
158
+
159
+ @Override
160
+ public void onError(@NonNull final String deviceAddress, final int error, final int errorType, final String message) {
161
+ JSObject ret = new JSObject();
162
+ ret.put("deviceAddress", deviceAddress);
163
+ ret.put("error", error);
164
+ ret.put("errorType", errorType);
165
+ ret.put("message", message);
166
+ dfuEventListener.onDfuEvent("DFU_FAILED", ret);
167
+ }
168
+ };
169
+
170
+ public void onResume(Context context) {
171
+ DfuServiceListenerHelper.registerProgressListener(context, dfuProgressListener);
172
+ }
173
+
174
+ public void onPause(Context context) {}
175
+
176
+ public void onDestroy(Context context) {
177
+ DfuServiceListenerHelper.unregisterProgressListener(context, dfuProgressListener);
178
+ }
179
+ }