├── example
├── .watchmanconfig
├── .gitattributes
├── .babelrc
├── app.json
├── android
│ ├── app
│ │ ├── src
│ │ │ └── main
│ │ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ └── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── nordicdfuexample
│ │ │ │ │ ├── MainActivity.java
│ │ │ │ │ └── MainApplication.java
│ │ │ │ └── AndroidManifest.xml
│ │ ├── BUCK
│ │ ├── proguard-rules.pro
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── keystores
│ │ ├── debug.keystore.properties
│ │ └── BUCK
│ ├── settings.gradle
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradlew.bat
│ └── gradlew
├── .buckconfig
├── ios
│ ├── NordicDFUExample.xcworkspace
│ │ ├── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── contents.xcworkspacedata
│ ├── NordicDFUExample
│ │ ├── AppDelegate.h
│ │ ├── main.m
│ │ ├── Images.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── AppDelegate.m
│ │ └── Base.lproj
│ │ │ └── LaunchScreen.xib
│ ├── Podfile
│ ├── Podfile.lock
│ └── NordicDFUExample.xcodeproj
│ │ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── NordicDFUExample.xcscheme
│ │ └── project.pbxproj
├── __tests__
│ ├── index.ios.js
│ └── index.android.js
├── index.ios.js
├── index.android.js
├── package.json
├── .gitignore
├── .flowconfig
└── app.js
├── .gitattributes
├── android
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── pilloxa
│ │ └── dfu
│ │ ├── RNNordicDfuPackage.java
│ │ ├── DfuService.java
│ │ ├── NotificationActivity.java
│ │ └── RNNordicDfuModule.java
└── build.gradle
├── .gitignore
├── ios
├── RNNordicDfu.h
├── RNNordicDfu.xcodeproj
│ └── project.pbxproj
└── RNNordicDfu.m
├── .npmignore
├── react-native-nordic-dfu.podspec
├── index.d.ts
├── circle.yml
├── LICENSE
├── package.json
├── index.js
└── README.md
/example/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
--------------------------------------------------------------------------------
/example/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/example/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["module:metro-react-native-babel-preset"]
3 | }
4 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "NordicDFUExample",
3 | "displayName": "NordicDFUExample"
4 | }
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | NordicDFUExample
3 |
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pilloxa/react-native-nordic-dfu/HEAD/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pilloxa/react-native-nordic-dfu/HEAD/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/keystores/debug.keystore.properties:
--------------------------------------------------------------------------------
1 | key.store=debug.keystore
2 | key.alias=androiddebugkey
3 | key.store.password=android
4 | key.alias.password=android
5 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pilloxa/react-native-nordic-dfu/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pilloxa/react-native-nordic-dfu/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pilloxa/react-native-nordic-dfu/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pilloxa/react-native-nordic-dfu/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/keystores/BUCK:
--------------------------------------------------------------------------------
1 | keystore(
2 | name = "debug",
3 | properties = "debug.keystore.properties",
4 | store = "debug.keystore",
5 | visibility = [
6 | "PUBLIC",
7 | ],
8 | )
9 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Nov 28 15:32:55 CET 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
8 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Jun 26 16:03:16 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/__tests__/index.ios.js:
--------------------------------------------------------------------------------
1 | import 'react-native';
2 | import React from 'react';
3 | import Index from '../index.ios.js';
4 |
5 | // Note: test renderer must be required after react-native.
6 | import renderer from 'react-test-renderer';
7 |
8 | it('renders correctly', () => {
9 | const tree = renderer.create(
10 |
11 | );
12 | });
13 |
--------------------------------------------------------------------------------
/example/index.ios.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from "react";
8 | import { AppRegistry } from "react-native";
9 |
10 | import NordicDFUExample from "./app";
11 |
12 | AppRegistry.registerComponent("NordicDFUExample", () => NordicDFUExample);
13 |
--------------------------------------------------------------------------------
/example/index.android.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from "react";
8 | import { AppRegistry } from "react-native";
9 |
10 | import NordicDFUExample from "./app";
11 |
12 | AppRegistry.registerComponent("NordicDFUExample", () => NordicDFUExample);
13 |
--------------------------------------------------------------------------------
/example/__tests__/index.android.js:
--------------------------------------------------------------------------------
1 | import 'react-native';
2 | import React from 'react';
3 | import Index from '../index.android.js';
4 |
5 | // Note: test renderer must be required after react-native.
6 | import renderer from 'react-test-renderer';
7 |
8 | it('renders correctly', () => {
9 | const tree = renderer.create(
10 |
11 | );
12 | });
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/nordicdfuexample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.nordicdfuexample;
2 |
3 | import com.facebook.react.ReactActivity;
4 |
5 | public class MainActivity extends ReactActivity {
6 |
7 | /**
8 | * Returns the name of the main component registered from JavaScript.
9 | * This is used to schedule rendering of the component.
10 | */
11 | @Override
12 | protected String getMainComponentName() {
13 | return "NordicDFUExample";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | @interface AppDelegate : UIResponder
13 |
14 | @property (nonatomic, strong) UIWindow *window;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "NordicDFUExample",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "postinstall": "(cd ios && pod install)",
7 | "start": "node node_modules/react-native/local-cli/cli.js start",
8 | "test": "jest"
9 | },
10 | "dependencies": {
11 | "react": "16.8.3",
12 | "react-native": "0.59.4",
13 | "react-native-ble-manager": "6.6.2",
14 | "react-native-nordic-dfu": "file:../",
15 | "rn-fetch-blob": "^0.10.12"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'NordicDFUExample'
2 | include ':react-native-fetch-blob'
3 | project(':react-native-fetch-blob').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fetch-blob/android')
4 | include ':react-native-nordic-dfu'
5 | project(':react-native-nordic-dfu').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-nordic-dfu/android')
6 | include ':react-native-ble-manager'
7 | project(':react-native-ble-manager').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-ble-manager/android')
8 |
9 | include ':app'
10 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample/main.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | #import "AppDelegate.h"
13 |
14 | int main(int argc, char * argv[]) {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 | # node.js
7 | #
8 | node_modules/
9 | npm-debug.log
10 | yarn-error.log
11 |
12 |
13 | # Xcode
14 | #
15 | build/
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 | xcuserdata
25 | *.xccheckout
26 | *.moved-aside
27 | DerivedData
28 | *.hmap
29 | *.ipa
30 | *.xcuserstate
31 | project.xcworkspace
32 |
33 |
34 | # Android/IntelliJ
35 | #
36 | build/
37 | .idea
38 | .gradle
39 | local.properties
40 | *.iml
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 |
47 | # CocoaPods
48 | Pods/
--------------------------------------------------------------------------------
/ios/RNNordicDfu.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 | @import iOSDFULibrary;
5 |
6 | @interface RNNordicDfu : RCTEventEmitter
7 |
8 | @property (strong, nonatomic) NSString * deviceAddress;
9 | @property (strong, nonatomic) RCTPromiseResolveBlock resolve;
10 | @property (strong, nonatomic) RCTPromiseRejectBlock reject;
11 |
12 | + (void)setCentralManagerGetter:(CBCentralManager * (^)())getter;
13 | + (void)setOnDFUComplete:(void (^)())onComplete;
14 | + (void)setOnDFUError:(void (^)())onError;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 | # node.js
7 | #
8 | node_modules/
9 | npm-debug.log
10 | yarn-error.log
11 |
12 |
13 | # Xcode
14 | #
15 | build/
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 | xcuserdata
25 | *.xccheckout
26 | *.moved-aside
27 | DerivedData
28 | *.hmap
29 | *.ipa
30 | *.xcuserstate
31 | project.xcworkspace
32 |
33 |
34 | # Android/IntelliJ
35 | #
36 | build/
37 | .idea
38 | .gradle
39 | local.properties
40 | *.iml
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 |
47 |
48 | # Example dir
49 | example
50 |
--------------------------------------------------------------------------------
/react-native-nordic-dfu.podspec:
--------------------------------------------------------------------------------
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 = "react-native-nordic-dfu"
7 | s.version = package['version']
8 | s.summary = package['description']
9 |
10 | s.authors = { "Pilloxa" => "recruitment@pilloxa.com" }
11 | s.homepage = "https://github.com/Pilloxa/react-native-nordic-dfu"
12 | s.license = "Apache License 2.0"
13 | s.platform = :ios, "8.0"
14 |
15 | s.source = { :git => "https://github.com/Pilloxa/react-native-nordic-dfu.git" }
16 | s.source_files = "ios/**/*.{h,m}"
17 |
18 | s.dependency 'React'
19 | s.dependency 'iOSDFULibrary', '~> 4.11.1'
20 | end
21 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.3'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | mavenLocal()
18 | jcenter()
19 | maven {
20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
21 | url "$rootDir/../node_modules/react-native/android"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'react-native-nordic-dfu' {
2 | export class NordicDFU {
3 | static startDFU({
4 | deviceAddress,
5 | deviceName,
6 | filePath,
7 | alternativeAdvertisingNameEnabled
8 | }: {
9 | deviceAddress: string;
10 | deviceName?: string;
11 | filePath: string | null;
12 | alternativeAdvertisingNameEnabled?: boolean;
13 | }): Promise;
14 | }
15 |
16 | export interface IDfuUpdate {
17 | percent?: number;
18 | currentPart?: number;
19 | partsTotal?: number;
20 | avgSpeed?: number;
21 | speed?: number;
22 | state?: string;
23 | }
24 |
25 | export class DFUEmitter {
26 | static addListener(
27 | name: 'DFUProgress' | 'DFUStateChanged',
28 | handler: (update: IDfuUpdate) => void
29 | ): void;
30 |
31 | static removeAllListeners(name: 'DFUProgress' | 'DFUStateChanged'): void;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | android.useDeprecatedNdk=true
21 |
--------------------------------------------------------------------------------
/android/src/main/java/com/pilloxa/dfu/RNNordicDfuPackage.java:
--------------------------------------------------------------------------------
1 |
2 | package com.pilloxa.dfu;
3 |
4 | import java.util.Arrays;
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.ViewManager;
12 | import com.facebook.react.bridge.JavaScriptModule;
13 | public class RNNordicDfuPackage implements ReactPackage {
14 | @Override
15 | public List createNativeModules(ReactApplicationContext reactContext) {
16 | return Arrays.asList(new RNNordicDfuModule(reactContext));
17 | }
18 |
19 | public List> createJSModules() {
20 | return Collections.emptyList();
21 | }
22 |
23 | @Override
24 | public List createViewManagers(ReactApplicationContext reactContext) {
25 | return Collections.emptyList();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | }
43 | ],
44 | "info" : {
45 | "version" : 1,
46 | "author" : "xcode"
47 | }
48 | }
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IntelliJ
26 | #
27 | build/
28 | .idea
29 | .gradle
30 | local.properties
31 | *.iml
32 |
33 | # node.js
34 | #
35 | node_modules/
36 | npm-debug.log
37 | yarn-error.log
38 |
39 | # BUCK
40 | buck-out/
41 | \.buckd/
42 | *.keystore
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
50 |
51 | fastlane/report.xml
52 | fastlane/Preview.html
53 | fastlane/screenshots
54 | jsconfig.json
55 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | machine:
2 | node:
3 | version: 7
4 | environment:
5 | PATH: "${PATH}:${HOME}/${CIRCLE_PROJECT_REPONAME}/example/node_modules/.bin"
6 | JAVA_OPTS: "-Xms518m -Xmx2048m"
7 | GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'
8 |
9 | dependencies:
10 | pre:
11 | - echo y | android update sdk --no-ui --all --filter "android-23"
12 | - echo y | android update sdk --no-ui --all --filter "build-tools-23.0.1"
13 | override:
14 | - cd example && yarn
15 | - cd example/android && ./gradlew --stacktrace app:dependencies
16 | cache_directories:
17 | - ~/.android
18 | - ~/.gradle
19 |
20 | test:
21 | override:
22 | # start the emulator
23 | - emulator -avd circleci-android22 -no-window:
24 | background: true
25 | parallel: true
26 | # wait for it to have booted
27 | - circle-android wait-for-boot
28 | - adb shell pm grant com.backtest android.permission.SYSTEM_ALERT_WINDOW
29 | # make sure that the project can be built
30 | - cd example/android && ./gradlew installDebug
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Pilloxa
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.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-nordic-dfu",
3 | "version": "3.2.1",
4 | "description": "Nordic Device Firmware Update for React Native",
5 | "main": "index.js",
6 | "url": "https://github.com/Pilloxa/react-native-nordic-dfu",
7 | "repository": "Pilloxa/react-native-nordic-dfu",
8 | "scripts": {
9 | "test": "echo \"No test specified\"",
10 | "precommit": "lint-staged",
11 | "document": "documentation readme --readme-file README.md -s \"API\" -g"
12 | },
13 | "keywords": [
14 | "react-native",
15 | "dfu",
16 | "nordic"
17 | ],
18 | "author": "Pilloxa ",
19 | "license": "MIT",
20 | "peerDependencies": {
21 | "react-native": ">= 0.45.1"
22 | },
23 | "devDependencies": {
24 | "documentation": "^4.0.0-rc.1",
25 | "husky": "^0.13.3",
26 | "lint-staged": "^3.4.0",
27 | "prettier": "^1.2.2"
28 | },
29 | "lint-staged": {
30 | "*.js": [
31 | "prettier --write",
32 | "git add"
33 | ],
34 | "index.js": [
35 | "npm run document",
36 | "git add README.md"
37 | ]
38 | },
39 | "types": "./index.d.ts"
40 | }
41 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, "9.0"
2 |
3 | # External dependencies contain Swift, important to add this line
4 | use_frameworks!
5 |
6 | target "NordicDFUExample" do
7 | # Standard React Native dependencies when using CocoaPods
8 | pod "yoga", path: "../node_modules/react-native/ReactCommon/yoga"
9 | pod "DoubleConversion", podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
10 | pod "glog", podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
11 | pod "Folly", podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
12 | pod "React", path: "../node_modules/react-native", subspecs: [
13 | "Core",
14 | "CxxBridge",
15 | "DevSupport",
16 | "RCTBlob",
17 | "RCTImage",
18 | "RCTLinkingIOS",
19 | "RCTText",
20 | ]
21 |
22 | pod "react-native-ble-manager", path: "../node_modules/react-native-ble-manager"
23 | pod "rn-fetch-blob", path: "../node_modules/rn-fetch-blob"
24 |
25 | # replace this path with "../node_modules/react-native-nordic-dfu" or wherever
26 | # it's installed in your project
27 | pod "react-native-nordic-dfu", path: "../../"
28 | end
29 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | google()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.1.4'
10 | }
11 | }
12 |
13 | apply plugin: 'com.android.library'
14 |
15 | def DEFAULT_COMPILE_SDK_VERSION = 28
16 | def DEFAULT_BUILD_TOOLS_VERSION = '28.0.3'
17 | def DEFAULT_TARGET_SDK_VERSION = 26
18 |
19 | android {
20 | compileSdkVersion project.hasProperty('compileSdkVersion') ? project.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION
21 | buildToolsVersion project.hasProperty('buildToolsVersion') ? project.buildToolsVersion : DEFAULT_BUILD_TOOLS_VERSION
22 |
23 | defaultConfig {
24 | minSdkVersion 18
25 | targetSdkVersion project.hasProperty('targetSdkVersion') ? project.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION
26 | versionCode 1
27 | versionName "1.0"
28 | }
29 | lintOptions {
30 | abortOnError false
31 | }
32 | }
33 |
34 | repositories {
35 | mavenCentral()
36 | google()
37 | }
38 |
39 | dependencies {
40 | implementation 'com.facebook.react:react-native:+'
41 | implementation 'no.nordicsemi.android:dfu:1.8.0'
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/nordicdfuexample/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.nordicdfuexample;
2 |
3 | import android.app.Application;
4 |
5 | import com.facebook.react.ReactApplication;
6 | import com.RNFetchBlob.RNFetchBlobPackage;
7 | import com.pilloxa.dfu.RNNordicDfuPackage;
8 | import it.innove.BleManagerPackage;
9 | import com.facebook.react.ReactNativeHost;
10 | import com.facebook.react.ReactPackage;
11 | import com.facebook.react.shell.MainReactPackage;
12 | import com.facebook.soloader.SoLoader;
13 |
14 | import java.util.Arrays;
15 | import java.util.List;
16 |
17 | public class MainApplication extends Application implements ReactApplication {
18 |
19 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
20 | @Override
21 | public boolean getUseDeveloperSupport() {
22 | return BuildConfig.DEBUG;
23 | }
24 |
25 | @Override
26 | protected List getPackages() {
27 | return Arrays.asList(
28 | new MainReactPackage(),
29 | new RNFetchBlobPackage(),
30 | new RNNordicDfuPackage(),
31 | new BleManagerPackage()
32 | );
33 | }
34 | };
35 |
36 | @Override
37 | public ReactNativeHost getReactNativeHost() {
38 | return mReactNativeHost;
39 | }
40 |
41 | @Override
42 | public void onCreate() {
43 | super.onCreate();
44 | SoLoader.init(this, /* native exopackage */ false);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/example/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | ; We fork some components by platform
3 | .*/*[.]android.js
4 |
5 | ; Ignore "BUCK" generated dirs
6 | /\.buckd/
7 |
8 | ; Ignore unexpected extra "@providesModule"
9 | .*/node_modules/.*/node_modules/fbjs/.*
10 |
11 | ; Ignore duplicate module providers
12 | ; For RN Apps installed via npm, "Libraries" folder is inside
13 | ; "node_modules/react-native" but in the source repo it is in the root
14 | .*/Libraries/react-native/React.js
15 | .*/Libraries/react-native/ReactNative.js
16 |
17 | [include]
18 |
19 | [libs]
20 | node_modules/react-native/Libraries/react-native/react-native-interface.js
21 | node_modules/react-native/flow
22 | flow/
23 |
24 | [options]
25 | emoji=true
26 |
27 | module.system=haste
28 |
29 | experimental.strict_type_args=true
30 |
31 | munge_underscores=true
32 |
33 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
34 |
35 | suppress_type=$FlowIssue
36 | suppress_type=$FlowFixMe
37 | suppress_type=$FixMe
38 |
39 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-5]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
40 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-5]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
41 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
42 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
43 |
44 | unsafe.enable_getters_and_setters=true
45 |
46 | [version]
47 | ^0.45.0
48 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | NordicDFUExample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSExceptionDomains
30 |
31 | localhost
32 |
33 | NSExceptionAllowsInsecureHTTPLoads
34 |
35 |
36 |
37 |
38 | NSLocationWhenInUseUsageDescription
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UIViewControllerBasedStatusBarAppearance
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/example/android/app/BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | lib_deps = []
12 |
13 | for jarfile in glob(['libs/*.jar']):
14 | name = 'jars__' + jarfile[jarfile.rindex('/') + 1: jarfile.rindex('.jar')]
15 | lib_deps.append(':' + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
21 | for aarfile in glob(['libs/*.aar']):
22 | name = 'aars__' + aarfile[aarfile.rindex('/') + 1: aarfile.rindex('.aar')]
23 | lib_deps.append(':' + name)
24 | android_prebuilt_aar(
25 | name = name,
26 | aar = aarfile,
27 | )
28 |
29 | android_library(
30 | name = "all-libs",
31 | exported_deps = lib_deps,
32 | )
33 |
34 | android_library(
35 | name = "app-code",
36 | srcs = glob([
37 | "src/main/java/**/*.java",
38 | ]),
39 | deps = [
40 | ":all-libs",
41 | ":build_config",
42 | ":res",
43 | ],
44 | )
45 |
46 | android_build_config(
47 | name = "build_config",
48 | package = "com.nordicdfuexample",
49 | )
50 |
51 | android_resource(
52 | name = "res",
53 | package = "com.nordicdfuexample",
54 | res = "src/main/res",
55 | )
56 |
57 | android_binary(
58 | name = "app",
59 | keystore = "//android/keystores:debug",
60 | manifest = "src/main/AndroidManifest.xml",
61 | package_type = "debug",
62 | deps = [
63 | ":app-code",
64 | ],
65 | )
66 |
--------------------------------------------------------------------------------
/android/src/main/java/com/pilloxa/dfu/DfuService.java:
--------------------------------------------------------------------------------
1 | package com.pilloxa.dfu;
2 |
3 | import no.nordicsemi.android.dfu.DfuBaseService;
4 | import android.app.Activity;
5 |
6 | public class DfuService extends DfuBaseService {
7 |
8 | @Override
9 | protected Class extends Activity> getNotificationTarget() {
10 | /*
11 | * As a target activity the NotificationActivity is returned, not the MainActivity. This is because
12 | * the notification must create a new task:
13 | *
14 | * intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
15 | *
16 | * when you press it. You can use NotificationActivity to check whether the new activity
17 | * is a root activity (that means no other activity was open earlier) or that some
18 | * other activity is already open. In the latter case the NotificationActivity will just be
19 | * closed. The system will restore the previous activity. However, if the application has been
20 | * closed during upload and you click the notification, a NotificationActivity will
21 | * be launched as a root activity. It will create and start the main activity and
22 | * terminate itself.
23 | *
24 | * This method may be used to restore the target activity in case the application
25 | * was closed or is open. It may also be used to recreate an activity history using
26 | * startActivities(...).
27 | */
28 | return NotificationActivity.class;
29 | }
30 |
31 | @Override
32 | protected boolean isDebug() {
33 | // Here return true if you want the service to print more logs in LogCat.
34 | // Library's BuildConfig in current version of Android Studio is always set to DEBUG=false, so
35 | // make sure you return true or your.app.BuildConfig.DEBUG here.
36 | return true;
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import "AppDelegate.h"
11 |
12 | #import
13 | #import
14 | #import "RNNordicDfu.h"
15 | #import "BleManager.h"
16 |
17 | @implementation AppDelegate
18 |
19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
20 | {
21 | NSURL *jsCodeLocation;
22 |
23 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
24 |
25 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
26 | moduleName:@"NordicDFUExample"
27 | initialProperties:nil
28 | launchOptions:launchOptions];
29 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
30 |
31 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
32 | UIViewController *rootViewController = [UIViewController new];
33 | rootViewController.view = rootView;
34 | self.window.rootViewController = rootViewController;
35 | [self.window makeKeyAndVisible];
36 |
37 | [RNNordicDfu setCentralManagerGetter:^() {
38 | return [BleManager getCentralManager];
39 | }];
40 |
41 | // Reset manager delegate since the Nordic DFU lib "steals" control over it
42 | [RNNordicDfu setOnDFUComplete:^() {
43 | NSLog(@"onDFUComplete");
44 | CBCentralManager * manager = [BleManager getCentralManager];
45 | manager.delegate = [BleManager getInstance];
46 | }];
47 | [RNNordicDfu setOnDFUError:^() {
48 | NSLog(@"onDFUError");
49 | CBCentralManager * manager = [BleManager getCentralManager];
50 | manager.delegate = [BleManager getInstance];
51 | }];
52 |
53 | return YES;
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/android/src/main/java/com/pilloxa/dfu/NotificationActivity.java:
--------------------------------------------------------------------------------
1 | package com.pilloxa.dfu;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import androidx.annotation.Nullable;
7 | import com.facebook.react.ReactApplication;
8 | import com.facebook.react.ReactInstanceManager;
9 | import com.facebook.react.bridge.ReactContext;
10 |
11 | /**
12 | * Created by viktor on 2017-06-26.
13 | */
14 |
15 | public class NotificationActivity extends Activity {
16 |
17 | private ReactInstanceManager reactInstanceManager;
18 |
19 | private ReactContext getReactContext() {
20 | reactInstanceManager = ((ReactApplication) getApplication())
21 | .getReactNativeHost()
22 | .getReactInstanceManager();
23 | return reactInstanceManager.getCurrentReactContext();
24 | }
25 |
26 | public Class getMainActivityClass(ReactContext reactContext) {
27 | String packageName = reactContext.getPackageName();
28 | Intent launchIntent = reactContext.getPackageManager().getLaunchIntentForPackage(packageName);
29 | String className = launchIntent.getComponent().getClassName();
30 | try {
31 | return Class.forName(className);
32 | } catch (ClassNotFoundException e) {
33 | e.printStackTrace();
34 | return null;
35 | }
36 | }
37 |
38 | @Override
39 | protected void onCreate(@Nullable Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | // If this activity is the root activity of the task, the app is not running
42 | if (isTaskRoot()) {
43 | ReactContext reactContext = getReactContext();
44 | Class HostActivity = getMainActivityClass(reactContext);
45 | // Start the app before finishing
46 | final Intent intent = new Intent(this, HostActivity);
47 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
48 | intent.putExtras(getIntent().getExtras()); // copy all extras
49 | startActivity(intent);
50 | }
51 |
52 | // Now finish, which will drop you to the activity at which you were at the top of the task stack
53 | finish();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Disabling obfuscation is useful if you collect stack traces from production crashes
20 | # (unless you are using a system that supports de-obfuscate the stack traces).
21 | -dontobfuscate
22 |
23 | # React Native
24 |
25 | # Keep our interfaces so they can be used by other ProGuard rules.
26 | # See http://sourceforge.net/p/proguard/bugs/466/
27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
30 |
31 | # Do not strip any method/class that is annotated with @DoNotStrip
32 | -keep @com.facebook.proguard.annotations.DoNotStrip class *
33 | -keep @com.facebook.common.internal.DoNotStrip class *
34 | -keepclassmembers class * {
35 | @com.facebook.proguard.annotations.DoNotStrip *;
36 | @com.facebook.common.internal.DoNotStrip *;
37 | }
38 |
39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
40 | void set*(***);
41 | *** get*();
42 | }
43 |
44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; }
46 | -keepclassmembers,includedescriptorclasses class * { native ; }
47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; }
48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; }
49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; }
50 |
51 | -dontwarn com.facebook.react.**
52 |
53 | # TextLayoutBuilder uses a non-public Android constructor within StaticLayout.
54 | # See libs/proxy/src/main/java/com/facebook/fbui/textlayoutbuilder/proxy for details.
55 | -dontwarn android.text.StaticLayout
56 |
57 | # okhttp
58 |
59 | -keepattributes Signature
60 | -keepattributes *Annotation*
61 | -keep class okhttp3.** { *; }
62 | -keep interface okhttp3.** { *; }
63 | -dontwarn okhttp3.**
64 |
65 | # okio
66 |
67 | -keep class sun.misc.Unsafe { *; }
68 | -dontwarn java.nio.file.*
69 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
70 | -dontwarn okio.**
71 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import { NativeModules, NativeEventEmitter, Platform } from "react-native";
2 | const { RNNordicDfu } = NativeModules;
3 | const NordicDFU = { startDFU };
4 |
5 | function rejectPromise(message) {
6 | return new Promise((resolve, reject) => {
7 | reject(new Error("NordicDFU.startDFU: " + message));
8 | });
9 | }
10 |
11 | /**
12 | *
13 | * Starts the DFU process
14 | *
15 | * Observe: The peripheral must have been discovered by the native BLE side so that the
16 | * bluetooth stack knows about it. This library will not do a scan but only
17 | * the actual connect and then the transfer. See the example project to see how it can be
18 | * done in React Native.
19 | *
20 | * For `alternativeAdvertisingNameEnabled` option below, see:
21 | * https://github.com/NordicSemiconductor/IOS-Pods-DFU-Library/blob/master/iOSDFULibrary/Classes/Implementation/DFUServiceInitiator.swift#L191
22 | *
23 | * @param {Object} obj
24 | * @param {string} obj.deviceAddress The MAC address for the device that should be updated
25 | * @param {string} [obj.deviceName = null] The name of the device in the update notification
26 | * @param {string} obj.filePath The file system path to the zip-file used for updating
27 | * @param {Boolean} obj.alternativeAdvertisingNameEnabled Send unique name to device before it is switched into bootloader mode (iOS only)
28 | * @returns {Promise} A promise that resolves or rejects with the `deviceAddress` in the return value
29 | *
30 | * @example
31 | * import { NordicDFU, DFUEmitter } from "react-native-nordic-dfu";
32 | *
33 | * NordicDFU.startDFU({
34 | * deviceAddress: "C3:53:C0:39:2F:99",
35 | * deviceName: "Pilloxa Pillbox",
36 | * filePath: "/data/user/0/com.nordicdfuexample/files/RNFetchBlobTmp4of.zip"
37 | * })
38 | * .then(res => console.log("Transfer done:", res))
39 | * .catch(console.log);
40 | */
41 | function startDFU({
42 | deviceAddress,
43 | deviceName = null,
44 | filePath,
45 | alternativeAdvertisingNameEnabled = true
46 | }) {
47 | if (deviceAddress == undefined) {
48 | return rejectPromise("No deviceAddress defined");
49 | }
50 | if (filePath == undefined) {
51 | return rejectPromise("No filePath defined");
52 | }
53 | const upperDeviceAddress = deviceAddress.toUpperCase();
54 | if (Platform.OS === 'ios') {
55 | return RNNordicDfu.startDFU(upperDeviceAddress, deviceName, filePath, alternativeAdvertisingNameEnabled);
56 | }
57 | return RNNordicDfu.startDFU(upperDeviceAddress, deviceName, filePath);
58 | }
59 |
60 | /**
61 | * Event emitter for DFU state and progress events
62 | *
63 | * @const DFUEmitter
64 | *
65 | * @example
66 | * import { NordicDFU, DFUEmitter } from "react-native-nordic-dfu";
67 | *
68 | * DFUEmitter.addlistener("DFUProgress",({percent, currentPart, partsTotal, avgSpeed, speed}) => {
69 | * console.log("DFU progress: " + percent +"%");
70 | * });
71 | *
72 | * DFUEmitter.addListener("DFUStateChanged", ({state}) => {
73 | * console.log("DFU State:", state);
74 | * })
75 | */
76 | const DFUEmitter = new NativeEventEmitter(RNNordicDfu);
77 |
78 | export { NordicDFU, DFUEmitter };
79 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - boost-for-react-native (1.63.0)
3 | - DoubleConversion (1.1.6)
4 | - Folly (2018.10.22.00):
5 | - boost-for-react-native
6 | - DoubleConversion
7 | - glog
8 | - glog (0.3.5)
9 | - iOSDFULibrary (4.4.1):
10 | - ZIPFoundation (~> 0.9.9)
11 | - React (0.59.4):
12 | - React/Core (= 0.59.4)
13 | - react-native-ble-manager (6.6.2):
14 | - React
15 | - react-native-nordic-dfu (3.0.0):
16 | - iOSDFULibrary (~> 4.4.0)
17 | - React
18 | - ZIPFoundation (~> 0.9.8)
19 | - React/Core (0.59.4):
20 | - yoga (= 0.59.4.React)
21 | - React/CxxBridge (0.59.4):
22 | - Folly (= 2018.10.22.00)
23 | - React/Core
24 | - React/cxxreact
25 | - React/jsiexecutor
26 | - React/cxxreact (0.59.4):
27 | - boost-for-react-native (= 1.63.0)
28 | - DoubleConversion
29 | - Folly (= 2018.10.22.00)
30 | - glog
31 | - React/jsinspector
32 | - React/DevSupport (0.59.4):
33 | - React/Core
34 | - React/RCTWebSocket
35 | - React/fishhook (0.59.4)
36 | - React/jsi (0.59.4):
37 | - DoubleConversion
38 | - Folly (= 2018.10.22.00)
39 | - glog
40 | - React/jsiexecutor (0.59.4):
41 | - DoubleConversion
42 | - Folly (= 2018.10.22.00)
43 | - glog
44 | - React/cxxreact
45 | - React/jsi
46 | - React/jsinspector (0.59.4)
47 | - React/RCTBlob (0.59.4):
48 | - React/Core
49 | - React/RCTImage (0.59.4):
50 | - React/Core
51 | - React/RCTNetwork
52 | - React/RCTLinkingIOS (0.59.4):
53 | - React/Core
54 | - React/RCTNetwork (0.59.4):
55 | - React/Core
56 | - React/RCTText (0.59.4):
57 | - React/Core
58 | - React/RCTWebSocket (0.59.4):
59 | - React/Core
60 | - React/fishhook
61 | - React/RCTBlob
62 | - rn-fetch-blob (0.10.6):
63 | - React/Core
64 | - yoga (0.59.4.React)
65 | - ZIPFoundation (0.9.9)
66 |
67 | DEPENDENCIES:
68 | - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
69 | - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
70 | - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
71 | - react-native-ble-manager (from `../node_modules/react-native-ble-manager`)
72 | - react-native-nordic-dfu (from `../../`)
73 | - React/Core (from `../node_modules/react-native`)
74 | - React/CxxBridge (from `../node_modules/react-native`)
75 | - React/DevSupport (from `../node_modules/react-native`)
76 | - React/RCTBlob (from `../node_modules/react-native`)
77 | - React/RCTImage (from `../node_modules/react-native`)
78 | - React/RCTLinkingIOS (from `../node_modules/react-native`)
79 | - React/RCTText (from `../node_modules/react-native`)
80 | - rn-fetch-blob (from `../node_modules/rn-fetch-blob`)
81 | - yoga (from `../node_modules/react-native/ReactCommon/yoga`)
82 |
83 | SPEC REPOS:
84 | https://github.com/cocoapods/specs.git:
85 | - boost-for-react-native
86 | - iOSDFULibrary
87 | - ZIPFoundation
88 |
89 | EXTERNAL SOURCES:
90 | DoubleConversion:
91 | :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
92 | Folly:
93 | :podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec"
94 | glog:
95 | :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
96 | React:
97 | :path: "../node_modules/react-native"
98 | react-native-ble-manager:
99 | :path: "../node_modules/react-native-ble-manager"
100 | react-native-nordic-dfu:
101 | :path: "../../"
102 | rn-fetch-blob:
103 | :path: "../node_modules/rn-fetch-blob"
104 | yoga:
105 | :path: "../node_modules/react-native/ReactCommon/yoga"
106 |
107 | SPEC CHECKSUMS:
108 | boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
109 | DoubleConversion: bb338842f62ab1d708ceb63ec3d999f0f3d98ecd
110 | Folly: de497beb10f102453a1afa9edbf8cf8a251890de
111 | glog: aefd1eb5dda2ab95ba0938556f34b98e2da3a60d
112 | iOSDFULibrary: cd43d0c1db731dbc116a67d55ea23d4c39d16c40
113 | React: 5cb71fb1a15b5ce04794ab49e24b48ebe4c94e65
114 | react-native-ble-manager: ea54402df086ead2c234e360b41606f206a2e8b8
115 | react-native-nordic-dfu: 13c96e0093d89d9a018ac4cffce6c964436756b1
116 | rn-fetch-blob: 766f85cabd2992300dfa1be2bc9e4e258abc6f04
117 | yoga: 596e61c9b57751d08a22b07aba310dbd3e65ab75
118 | ZIPFoundation: 89df685c971926b0323087952320bdfee9f0b6ef
119 |
120 | PODFILE CHECKSUM: cb820ecf6246ea4ab1fde3a11b0880f6cc0f1108
121 |
122 | COCOAPODS: 1.6.1
123 |
--------------------------------------------------------------------------------
/example/app.js:
--------------------------------------------------------------------------------
1 | /**
2 | * An example project that downloads a zip file, connects to a device and then flashes
3 | * it.
4 | */
5 |
6 | import React, { Component } from "react";
7 | import {
8 | AppRegistry,
9 | TouchableHighlight,
10 | NativeModules,
11 | NativeEventEmitter,
12 | Platform,
13 | StyleSheet,
14 | Text,
15 | View,
16 | Image
17 | } from "react-native";
18 | import { NordicDFU, DFUEmitter } from "react-native-nordic-dfu";
19 | import RNFetchBlob from "rn-fetch-blob";
20 | import BleManager from "react-native-ble-manager";
21 |
22 | const BleManagerModule = NativeModules.BleManager;
23 | const bleManagerEmitter = new NativeEventEmitter(BleManagerModule);
24 | const DEVICE_ID = "C3:53:A0:31:2F:14";
25 |
26 | const FB = RNFetchBlob.config({
27 | fileCache: true,
28 | appendExt: "zip"
29 | });
30 |
31 | export default class NordicDFUExample extends Component {
32 | constructor(props) {
33 | super(props);
34 | this.handleDeviceDiscovered = this.handleDeviceDiscovered.bind(this);
35 | this.startScan = this.startScan.bind(this);
36 | this.handleStopScan = this.handleStopScan.bind(this);
37 | this.state = {
38 | imagefile: false,
39 | scanning: false,
40 | deviceFound: false,
41 | dfuState: "Not started",
42 | progress: 0
43 | };
44 | }
45 |
46 | componentDidMount() {
47 | DFUEmitter.addListener("DFUProgress", ({ percent }) => {
48 | console.log("DFU progress:", percent);
49 | this.setState({ progress: percent });
50 | });
51 | DFUEmitter.addListener("DFUStateChanged", ({ state }) => {
52 | console.log("DFU state:", state);
53 | this.setState({ dfuState: state });
54 | });
55 |
56 | FB.fetch("GET", "http://localhost:1234/app.zip").then(res => {
57 | console.log("file saved to", res.path());
58 | this.setState({ imagefile: res.path() });
59 | });
60 |
61 | BleManager.start({ showAlert: false, allowDuplicates: false });
62 | bleManagerEmitter.addListener("BleManagerStopScan", this.handleStopScan);
63 | bleManagerEmitter.addListener(
64 | "BleManagerDiscoverPeripheral",
65 | this.handleDeviceDiscovered
66 | );
67 | this.startScan();
68 | }
69 |
70 | // #### DFU #######################################################
71 |
72 | startDFU() {
73 | console.log("Starting DFU");
74 | NordicDFU.startDFU({
75 | deviceAddress: DEVICE_ID,
76 | name: "Pilloxa Board",
77 | filePath: this.state.imagefile
78 | })
79 | .then(res => console.log("Transfer done: ", res))
80 | .catch(console.log);
81 | }
82 |
83 | // #### BLUETOOTH #################################################
84 |
85 | handleDeviceDiscovered({ id }) {
86 | if (id == DEVICE_ID) {
87 | this.setState({
88 | deviceFound: true,
89 | scanning: false
90 | });
91 | }
92 | }
93 |
94 | handleStopScan() {
95 | console.log("Scan is stopped");
96 | if (this.state.scanning) {
97 | this.startScan();
98 | }
99 | }
100 |
101 | startScan() {
102 | BleManager.scan([], 3, true).then(results => {
103 | console.log("Scanning...");
104 | this.setState({ scanning: true });
105 | });
106 | }
107 |
108 | // #### RENDER #########################################################
109 |
110 | render() {
111 | return (
112 |
113 |
114 | {this.state.dfuState}
115 |
116 |
117 | {"DFU progress: " + this.state.progress + " %"}
118 |
119 |
120 | {this.state.scanning ? "Scanning for: " + DEVICE_ID : "Not scanning"}
121 |
122 |
123 | {this.state.deviceFound
124 | ? "Found device: " + DEVICE_ID
125 | : "Device not found"}
126 |
127 |
128 | {this.state.deviceFound
129 | ?
133 | Start DFU
134 |
135 | : null}
136 |
137 | );
138 | }
139 | }
140 |
141 | const styles = StyleSheet.create({
142 | container: {
143 | flex: 1,
144 | justifyContent: "center",
145 | alignItems: "center",
146 | backgroundColor: "#F5FCFF"
147 | },
148 | welcome: {
149 | fontSize: 20,
150 | textAlign: "center",
151 | margin: 10
152 | },
153 | instructions: {
154 | textAlign: "center",
155 | color: "#333333",
156 | marginBottom: 5
157 | }
158 | });
159 |
160 | AppRegistry.registerComponent("NordicDFUExample", () => NordicDFUExample);
161 |
--------------------------------------------------------------------------------
/example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample.xcodeproj/xcshareddata/xcschemes/NordicDFUExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
43 |
49 |
50 |
51 |
57 |
63 |
64 |
65 |
66 |
67 |
72 |
73 |
75 |
81 |
82 |
83 |
84 |
85 |
91 |
92 |
93 |
94 |
95 |
96 |
106 |
108 |
114 |
115 |
116 |
117 |
118 |
119 |
125 |
127 |
133 |
134 |
135 |
136 |
138 |
139 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // the entry file for bundle generation
19 | * entryFile: "index.android.js",
20 | *
21 | * // whether to bundle JS and assets in debug mode
22 | * bundleInDebug: false,
23 | *
24 | * // whether to bundle JS and assets in release mode
25 | * bundleInRelease: true,
26 | *
27 | * // whether to bundle JS and assets in another build variant (if configured).
28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
29 | * // The configuration property can be in the following formats
30 | * // 'bundleIn${productFlavor}${buildType}'
31 | * // 'bundleIn${buildType}'
32 | * // bundleInFreeDebug: true,
33 | * // bundleInPaidRelease: true,
34 | * // bundleInBeta: true,
35 | *
36 | * // whether to disable dev mode in custom build variants (by default only disabled in release)
37 | * // for example: to disable dev mode in the staging build type (if configured)
38 | * devDisabledInStaging: true,
39 | * // The configuration property can be in the following formats
40 | * // 'devDisabledIn${productFlavor}${buildType}'
41 | * // 'devDisabledIn${buildType}'
42 | *
43 | * // the root of your project, i.e. where "package.json" lives
44 | * root: "../../",
45 | *
46 | * // where to put the JS bundle asset in debug mode
47 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
48 | *
49 | * // where to put the JS bundle asset in release mode
50 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
51 | *
52 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
53 | * // require('./image.png')), in debug mode
54 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
55 | *
56 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
57 | * // require('./image.png')), in release mode
58 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
59 | *
60 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
61 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
62 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
63 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
64 | * // for example, you might want to remove it from here.
65 | * inputExcludes: ["android/**", "ios/**"],
66 | *
67 | * // override which node gets called and with what additional arguments
68 | * nodeExecutableAndArgs: ["node"],
69 | *
70 | * // supply additional arguments to the packager
71 | * extraPackagerArgs: []
72 | * ]
73 | */
74 |
75 | apply from: "../../node_modules/react-native/react.gradle"
76 |
77 | /**
78 | * Set this to true to create two separate APKs instead of one:
79 | * - An APK that only works on ARM devices
80 | * - An APK that only works on x86 devices
81 | * The advantage is the size of the APK is reduced by about 4MB.
82 | * Upload all the APKs to the Play Store and people will download
83 | * the correct one based on the CPU architecture of their device.
84 | */
85 | def enableSeparateBuildPerCPUArchitecture = false
86 |
87 | /**
88 | * Run Proguard to shrink the Java bytecode in release builds.
89 | */
90 | def enableProguardInReleaseBuilds = false
91 |
92 | android {
93 | compileSdkVersion 23
94 | buildToolsVersion '23.0.1'
95 |
96 | defaultConfig {
97 | applicationId "com.nordicdfuexample"
98 | minSdkVersion 18
99 | targetSdkVersion 22
100 | versionCode 1
101 | versionName "1.0"
102 | ndk {
103 | abiFilters "armeabi-v7a", "x86"
104 | }
105 | }
106 | splits {
107 | abi {
108 | reset()
109 | enable enableSeparateBuildPerCPUArchitecture
110 | universalApk false // If true, also generate a universal APK
111 | include "armeabi-v7a", "x86"
112 | }
113 | }
114 | buildTypes {
115 | release {
116 | minifyEnabled enableProguardInReleaseBuilds
117 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
118 | }
119 | }
120 | // applicationVariants are e.g. debug, release
121 | applicationVariants.all { variant ->
122 | variant.outputs.each { output ->
123 | // For each separate APK per architecture, set a unique version code as described here:
124 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
125 | def versionCodes = ["armeabi-v7a":1, "x86":2]
126 | def abi = output.getFilter(OutputFile.ABI)
127 | if (abi != null) { // null for the universal-debug, universal-release variants
128 | output.versionCodeOverride =
129 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
130 | }
131 | }
132 | }
133 | }
134 |
135 | dependencies {
136 | compile project(':react-native-fetch-blob')
137 | compile project(':react-native-nordic-dfu')
138 | compile project(':react-native-ble-manager')
139 | compile fileTree(dir: "libs", include: ["*.jar"])
140 | compile "com.android.support:appcompat-v7:23.0.1"
141 | compile "com.facebook.react:react-native:+" // From node_modules
142 | }
143 |
144 | // Run this once to be able to run the application with BUCK
145 | // puts all compile dependencies into folder libs for BUCK to use
146 | task copyDownloadableDepsToLibs(type: Copy) {
147 | from configurations.compile
148 | into 'libs'
149 | }
150 |
--------------------------------------------------------------------------------
/android/src/main/java/com/pilloxa/dfu/RNNordicDfuModule.java:
--------------------------------------------------------------------------------
1 |
2 | package com.pilloxa.dfu;
3 |
4 | import android.app.NotificationManager;
5 | import android.content.Context;
6 | import android.os.Build;
7 | import android.os.Handler;
8 | import androidx.annotation.Nullable;
9 | import android.util.Log;
10 | import com.facebook.react.bridge.*;
11 | import com.facebook.react.modules.core.RCTNativeAppEventEmitter;
12 | import no.nordicsemi.android.dfu.*;
13 |
14 | public class RNNordicDfuModule extends ReactContextBaseJavaModule implements LifecycleEventListener {
15 |
16 | private final String dfuStateEvent = "DFUStateChanged";
17 | private final String progressEvent = "DFUProgress";
18 | private static final String name = "RNNordicDfu";
19 | public static final String LOG_TAG = name;
20 | private final ReactApplicationContext reactContext;
21 | private Promise mPromise = null;
22 |
23 | public RNNordicDfuModule(ReactApplicationContext reactContext) {
24 | super(reactContext);
25 | reactContext.addLifecycleEventListener(this);
26 | this.reactContext = reactContext;
27 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
28 | DfuServiceInitiator.createDfuNotificationChannel(reactContext);
29 | }
30 | }
31 |
32 | @ReactMethod
33 | public void startDFU(String address, String name, String filePath, Promise promise) {
34 | mPromise = promise;
35 | final DfuServiceInitiator starter = new DfuServiceInitiator(address)
36 | .setKeepBond(false);
37 | if (name != null) {
38 | starter.setDeviceName(name);
39 | }
40 | starter.setUnsafeExperimentalButtonlessServiceInSecureDfuEnabled(true);
41 | starter.setZip(filePath);
42 | final DfuServiceController controller = starter.start(this.reactContext, DfuService.class);
43 | }
44 |
45 | @Override
46 | public String getName() {
47 | return name;
48 | }
49 |
50 |
51 | private void sendEvent(String eventName, @Nullable WritableMap params) {
52 | getReactApplicationContext()
53 | .getJSModule(RCTNativeAppEventEmitter.class)
54 | .emit(eventName, params);
55 | }
56 |
57 | private void sendStateUpdate(String state, String deviceAddress) {
58 | WritableMap map = new WritableNativeMap();
59 | Log.d(LOG_TAG, "State: " + state);
60 | map.putString("state", state);
61 | map.putString("deviceAddress", deviceAddress);
62 | sendEvent(dfuStateEvent, map);
63 | }
64 |
65 |
66 | @Override
67 | public void onHostResume() {
68 | DfuServiceListenerHelper.registerProgressListener(this.reactContext, mDfuProgressListener);
69 |
70 | }
71 |
72 | @Override
73 | public void onHostPause() {
74 | }
75 |
76 | @Override
77 | public void onHostDestroy() {
78 | DfuServiceListenerHelper.unregisterProgressListener(this.reactContext, mDfuProgressListener);
79 |
80 | }
81 |
82 |
83 | /**
84 | * The progress listener receives events from the DFU Service.
85 | * If is registered in onCreate() and unregistered in onDestroy() so methods here may also be called
86 | * when the screen is locked or the app went to the background. This is because the UI needs to have the
87 | * correct information after user comes back to the activity and this information can't be read from the service
88 | * as it might have been killed already (DFU completed or finished with error).
89 | */
90 | private final DfuProgressListener mDfuProgressListener = new DfuProgressListenerAdapter() {
91 | @Override
92 | public void onDeviceConnecting(final String deviceAddress) {
93 | sendStateUpdate("CONNECTING", deviceAddress);
94 | }
95 |
96 | @Override
97 | public void onDfuProcessStarting(final String deviceAddress) {
98 | sendStateUpdate("DFU_PROCESS_STARTING", deviceAddress);
99 | }
100 |
101 | @Override
102 | public void onEnablingDfuMode(final String deviceAddress) {
103 | sendStateUpdate("ENABLING_DFU_MODE", deviceAddress);
104 | }
105 |
106 | @Override
107 | public void onFirmwareValidating(final String deviceAddress) {
108 | sendStateUpdate("FIRMWARE_VALIDATING", deviceAddress);
109 | }
110 |
111 | @Override
112 | public void onDeviceDisconnecting(final String deviceAddress) {
113 | sendStateUpdate("DEVICE_DISCONNECTING", deviceAddress);
114 | }
115 |
116 | @Override
117 | public void onDfuCompleted(final String deviceAddress) {
118 | if (mPromise != null) {
119 | WritableMap map = new WritableNativeMap();
120 | map.putString("deviceAddress", deviceAddress);
121 | mPromise.resolve(map);
122 | mPromise = null;
123 | }
124 | sendStateUpdate("DFU_COMPLETED", deviceAddress);
125 |
126 |
127 | new Handler().postDelayed(new Runnable() {
128 | @Override
129 | public void run() {
130 |
131 | // if this activity is still open and upload process was completed, cancel the notification
132 | final NotificationManager manager = (NotificationManager) reactContext.getSystemService(Context.NOTIFICATION_SERVICE);
133 | manager.cancel(DfuService.NOTIFICATION_ID);
134 | }
135 | }, 200);
136 |
137 | }
138 |
139 | @Override
140 | public void onDfuAborted(final String deviceAddress) {
141 | sendStateUpdate("DFU_ABORTED", deviceAddress);
142 | if (mPromise != null) {
143 | mPromise.reject("2", "DFU ABORTED");
144 | mPromise = null;
145 | }
146 |
147 | }
148 |
149 | @Override
150 | public void onProgressChanged(final String deviceAddress, final int percent, final float speed, final float avgSpeed, final int currentPart, final int partsTotal) {
151 | WritableMap map = new WritableNativeMap();
152 | map.putString("deviceAddress", deviceAddress);
153 | map.putInt("percent", percent);
154 | map.putDouble("speed", speed);
155 | map.putDouble("avgSpeed", avgSpeed);
156 | map.putInt("currentPart", currentPart);
157 | map.putInt("partsTotal", partsTotal);
158 | sendEvent(progressEvent, map);
159 |
160 | }
161 |
162 | @Override
163 | public void onError(final String deviceAddress, final int error, final int errorType, final String message) {
164 | sendStateUpdate("DFU_FAILED", deviceAddress);
165 | if (mPromise != null) {
166 | mPromise.reject(Integer.toString(error), message);
167 | mPromise = null;
168 | }
169 | }
170 | };
171 | }
--------------------------------------------------------------------------------
/ios/RNNordicDfu.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B3E7B58A1CC2AC0600A0062D /* RNNordicDfu.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNNordicDfu.m */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = "include/$(PRODUCT_NAME)";
18 | dstSubfolderSpec = 16;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 0;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | 134814201AA4EA6300B7C361 /* libRNNordicDfu.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNNordicDfu.a; sourceTree = BUILT_PRODUCTS_DIR; };
27 | B3E7B5881CC2AC0600A0062D /* RNNordicDfu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNordicDfu.h; sourceTree = ""; };
28 | B3E7B5891CC2AC0600A0062D /* RNNordicDfu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNordicDfu.m; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 58B511D81A9E6C8500147676 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 134814211AA4EA7D00B7C361 /* Products */ = {
43 | isa = PBXGroup;
44 | children = (
45 | 134814201AA4EA6300B7C361 /* libRNNordicDfu.a */,
46 | );
47 | name = Products;
48 | sourceTree = "";
49 | };
50 | 58B511D21A9E6C8500147676 = {
51 | isa = PBXGroup;
52 | children = (
53 | B3E7B5881CC2AC0600A0062D /* RNNordicDfu.h */,
54 | B3E7B5891CC2AC0600A0062D /* RNNordicDfu.m */,
55 | 134814211AA4EA7D00B7C361 /* Products */,
56 | );
57 | sourceTree = "";
58 | };
59 | /* End PBXGroup section */
60 |
61 | /* Begin PBXNativeTarget section */
62 | 58B511DA1A9E6C8500147676 /* RNNordicDfu */ = {
63 | isa = PBXNativeTarget;
64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNNordicDfu" */;
65 | buildPhases = (
66 | 58B511D71A9E6C8500147676 /* Sources */,
67 | 58B511D81A9E6C8500147676 /* Frameworks */,
68 | 58B511D91A9E6C8500147676 /* CopyFiles */,
69 | );
70 | buildRules = (
71 | );
72 | dependencies = (
73 | );
74 | name = RNNordicDfu;
75 | productName = RCTDataManager;
76 | productReference = 134814201AA4EA6300B7C361 /* libRNNordicDfu.a */;
77 | productType = "com.apple.product-type.library.static";
78 | };
79 | /* End PBXNativeTarget section */
80 |
81 | /* Begin PBXProject section */
82 | 58B511D31A9E6C8500147676 /* Project object */ = {
83 | isa = PBXProject;
84 | attributes = {
85 | LastUpgradeCheck = 0610;
86 | ORGANIZATIONNAME = Facebook;
87 | TargetAttributes = {
88 | 58B511DA1A9E6C8500147676 = {
89 | CreatedOnToolsVersion = 6.1.1;
90 | };
91 | };
92 | };
93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNNordicDfu" */;
94 | compatibilityVersion = "Xcode 3.2";
95 | developmentRegion = English;
96 | hasScannedForEncodings = 0;
97 | knownRegions = (
98 | en,
99 | );
100 | mainGroup = 58B511D21A9E6C8500147676;
101 | productRefGroup = 58B511D21A9E6C8500147676;
102 | projectDirPath = "";
103 | projectRoot = "";
104 | targets = (
105 | 58B511DA1A9E6C8500147676 /* RNNordicDfu */,
106 | );
107 | };
108 | /* End PBXProject section */
109 |
110 | /* Begin PBXSourcesBuildPhase section */
111 | 58B511D71A9E6C8500147676 /* Sources */ = {
112 | isa = PBXSourcesBuildPhase;
113 | buildActionMask = 2147483647;
114 | files = (
115 | B3E7B58A1CC2AC0600A0062D /* RNNordicDfu.m in Sources */,
116 | );
117 | runOnlyForDeploymentPostprocessing = 0;
118 | };
119 | /* End PBXSourcesBuildPhase section */
120 |
121 | /* Begin XCBuildConfiguration section */
122 | 58B511ED1A9E6C8500147676 /* Debug */ = {
123 | isa = XCBuildConfiguration;
124 | buildSettings = {
125 | ALWAYS_SEARCH_USER_PATHS = NO;
126 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
127 | CLANG_CXX_LIBRARY = "libc++";
128 | CLANG_ENABLE_MODULES = YES;
129 | CLANG_ENABLE_OBJC_ARC = YES;
130 | CLANG_WARN_BOOL_CONVERSION = YES;
131 | CLANG_WARN_CONSTANT_CONVERSION = YES;
132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
133 | CLANG_WARN_EMPTY_BODY = YES;
134 | CLANG_WARN_ENUM_CONVERSION = YES;
135 | CLANG_WARN_INT_CONVERSION = YES;
136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
137 | CLANG_WARN_UNREACHABLE_CODE = YES;
138 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
139 | COPY_PHASE_STRIP = NO;
140 | ENABLE_STRICT_OBJC_MSGSEND = YES;
141 | GCC_C_LANGUAGE_STANDARD = gnu99;
142 | GCC_DYNAMIC_NO_PIC = NO;
143 | GCC_OPTIMIZATION_LEVEL = 0;
144 | GCC_PREPROCESSOR_DEFINITIONS = (
145 | "DEBUG=1",
146 | "$(inherited)",
147 | );
148 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
149 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
150 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
151 | GCC_WARN_UNDECLARED_SELECTOR = YES;
152 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
153 | GCC_WARN_UNUSED_FUNCTION = YES;
154 | GCC_WARN_UNUSED_VARIABLE = YES;
155 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
156 | MTL_ENABLE_DEBUG_INFO = YES;
157 | ONLY_ACTIVE_ARCH = YES;
158 | SDKROOT = iphoneos;
159 | };
160 | name = Debug;
161 | };
162 | 58B511EE1A9E6C8500147676 /* Release */ = {
163 | isa = XCBuildConfiguration;
164 | buildSettings = {
165 | ALWAYS_SEARCH_USER_PATHS = NO;
166 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
167 | CLANG_CXX_LIBRARY = "libc++";
168 | CLANG_ENABLE_MODULES = YES;
169 | CLANG_ENABLE_OBJC_ARC = YES;
170 | CLANG_WARN_BOOL_CONVERSION = YES;
171 | CLANG_WARN_CONSTANT_CONVERSION = YES;
172 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
173 | CLANG_WARN_EMPTY_BODY = YES;
174 | CLANG_WARN_ENUM_CONVERSION = YES;
175 | CLANG_WARN_INT_CONVERSION = YES;
176 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
177 | CLANG_WARN_UNREACHABLE_CODE = YES;
178 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
179 | COPY_PHASE_STRIP = YES;
180 | ENABLE_NS_ASSERTIONS = NO;
181 | ENABLE_STRICT_OBJC_MSGSEND = YES;
182 | GCC_C_LANGUAGE_STANDARD = gnu99;
183 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
184 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
185 | GCC_WARN_UNDECLARED_SELECTOR = YES;
186 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
187 | GCC_WARN_UNUSED_FUNCTION = YES;
188 | GCC_WARN_UNUSED_VARIABLE = YES;
189 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
190 | MTL_ENABLE_DEBUG_INFO = NO;
191 | SDKROOT = iphoneos;
192 | VALIDATE_PRODUCT = YES;
193 | };
194 | name = Release;
195 | };
196 | 58B511F01A9E6C8500147676 /* Debug */ = {
197 | isa = XCBuildConfiguration;
198 | buildSettings = {
199 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/**";
200 | HEADER_SEARCH_PATHS = (
201 | "$(inherited)",
202 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
203 | "$(SRCROOT)/../../../React/**",
204 | "$(SRCROOT)/../../react-native/React/**",
205 | "$(PROJECT_DIR)/iOSDFULibrary.framework/**",
206 | "$(PROJECT_DIR)/../../../ios/Pods/Headers/Public/**",
207 | );
208 | LIBRARY_SEARCH_PATHS = "$(inherited)";
209 | OTHER_LDFLAGS = "-ObjC";
210 | PRODUCT_NAME = RNNordicDfu;
211 | SKIP_INSTALL = YES;
212 | };
213 | name = Debug;
214 | };
215 | 58B511F11A9E6C8500147676 /* Release */ = {
216 | isa = XCBuildConfiguration;
217 | buildSettings = {
218 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/**";
219 | HEADER_SEARCH_PATHS = (
220 | "$(inherited)",
221 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
222 | "$(SRCROOT)/../../../React/**",
223 | "$(SRCROOT)/../../react-native/React/**",
224 | "$(PROJECT_DIR)/iOSDFULibrary.framework/**",
225 | "$(PROJECT_DIR)/../../../ios/Pods/Headers/Public/**",
226 | );
227 | LIBRARY_SEARCH_PATHS = "$(inherited)";
228 | OTHER_LDFLAGS = "-ObjC";
229 | PRODUCT_NAME = RNNordicDfu;
230 | SKIP_INSTALL = YES;
231 | };
232 | name = Release;
233 | };
234 | /* End XCBuildConfiguration section */
235 |
236 | /* Begin XCConfigurationList section */
237 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNNordicDfu" */ = {
238 | isa = XCConfigurationList;
239 | buildConfigurations = (
240 | 58B511ED1A9E6C8500147676 /* Debug */,
241 | 58B511EE1A9E6C8500147676 /* Release */,
242 | );
243 | defaultConfigurationIsVisible = 0;
244 | defaultConfigurationName = Release;
245 | };
246 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNNordicDfu" */ = {
247 | isa = XCConfigurationList;
248 | buildConfigurations = (
249 | 58B511F01A9E6C8500147676 /* Debug */,
250 | 58B511F11A9E6C8500147676 /* Release */,
251 | );
252 | defaultConfigurationIsVisible = 0;
253 | defaultConfigurationName = Release;
254 | };
255 | /* End XCConfigurationList section */
256 | };
257 | rootObject = 58B511D31A9E6C8500147676 /* Project object */;
258 | }
259 |
--------------------------------------------------------------------------------
/ios/RNNordicDfu.m:
--------------------------------------------------------------------------------
1 | #import "RNNordicDfu.h"
2 | #import
3 | @import iOSDFULibrary;
4 |
5 | static CBCentralManager * (^getCentralManager)();
6 | static void (^onDFUComplete)();
7 | static void (^onDFUError)();
8 |
9 | @implementation RNNordicDfu
10 |
11 | RCT_EXPORT_MODULE();
12 |
13 | NSString * const DFUProgressEvent = @"DFUProgress";
14 | NSString * const DFUStateChangedEvent = @"DFUStateChanged";
15 |
16 | - (NSArray *)supportedEvents
17 | {
18 | return @[DFUProgressEvent,
19 | DFUStateChangedEvent,];
20 | }
21 |
22 | - (NSString *)stateDescription:(enum DFUState)state
23 | {
24 | switch (state)
25 | {
26 | case DFUStateAborted:
27 | return @"DFU_ABORTED";
28 | case DFUStateStarting:
29 | return @"DFU_PROCESS_STARTING";
30 | case DFUStateCompleted:
31 | return @"DFU_COMPLETED";
32 | case DFUStateUploading:
33 | return @"DFU_STATE_UPLOADING";
34 | case DFUStateConnecting:
35 | return @"CONNECTING";
36 | case DFUStateValidating:
37 | return @"FIRMWARE_VALIDATING";
38 | case DFUStateDisconnecting:
39 | return @"DEVICE_DISCONNECTING";
40 | case DFUStateEnablingDfuMode:
41 | return @"ENABLING_DFU_MODE";
42 | default:
43 | return @"UNKNOWN_STATE";
44 | }
45 | }
46 |
47 | - (NSString *)errorDescription:(enum DFUError)error
48 | {
49 | switch(error)
50 | {
51 | case DFUErrorCrcError:
52 | return @"DFUErrorCrcError";
53 | case DFUErrorBytesLost:
54 | return @"DFUErrorBytesLost";
55 | case DFUErrorFileInvalid:
56 | return @"DFUErrorFileInvalid";
57 | case DFUErrorFailedToConnect:
58 | return @"DFUErrorFailedToConnect";
59 | case DFUErrorFileNotSpecified:
60 | return @"DFUErrorFileNotSpecified";
61 | case DFUErrorBluetoothDisabled:
62 | return @"DFUErrorBluetoothDisabled";
63 | case DFUErrorDeviceDisconnected:
64 | return @"DFUErrorDeviceDisconnected";
65 | case DFUErrorDeviceNotSupported:
66 | return @"DFUErrorDeviceNotSupported";
67 | case DFUErrorInitPacketRequired:
68 | return @"DFUErrorInitPacketRequired";
69 | case DFUErrorUnsupportedResponse:
70 | return @"DFUErrorUnsupportedResponse";
71 | case DFUErrorReadingVersionFailed:
72 | return @"DFUErrorReadingVersionFailed";
73 | case DFUErrorRemoteLegacyDFUSuccess:
74 | return @"DFUErrorRemoteLegacyDFUSuccess";
75 | case DFUErrorRemoteSecureDFUSuccess:
76 | return @"DFUErrorRemoteSecureDFUSuccess";
77 | case DFUErrorServiceDiscoveryFailed:
78 | return @"DFUErrorServiceDiscoveryFailed";
79 | case DFUErrorRemoteLegacyDFUCrcError:
80 | return @"DFUErrorRemoteLegacyDFUCrcError";
81 | case DFUErrorEnablingControlPointFailed:
82 | return @"DFUErrorEnablingControlPointFailed";
83 | case DFUErrorExtendedInitPacketRequired:
84 | return @"DFUErrorExtendedInitPacketRequired";
85 | case DFUErrorReceivingNotificationFailed:
86 | return @"DFUErrorReceivingNotificationFailed";
87 | case DFUErrorRemoteButtonlessDFUSuccess:
88 | return @"DFUErrorRemoteButtonlessDFUSuccess";
89 | case DFUErrorRemoteLegacyDFUInvalidState:
90 | return @"DFUErrorRemoteLegacyDFUInvalidState";
91 | case DFUErrorRemoteLegacyDFUNotSupported:
92 | return @"DFUErrorRemoteLegacyDFUNotSupported";
93 | case DFUErrorWritingCharacteristicFailed:
94 | return @"DFUErrorWritingCharacteristicFailed";
95 | case DFUErrorRemoteSecureDFUExtendedError:
96 | return @"DFUErrorRemoteSecureDFUExtendedError";
97 | case DFUErrorRemoteSecureDFUInvalidObject:
98 | return @"DFUErrorRemoteSecureDFUInvalidObject";
99 | case DFUErrorRemoteLegacyDFUOperationFailed:
100 | return @"DFUErrorRemoteLegacyDFUOperationFailed";
101 | case DFUErrorRemoteSecureDFUOperationFailed:
102 | return @"DFUErrorRemoteSecureDFUOperationFailed";
103 | case DFUErrorRemoteSecureDFUUnsupportedType:
104 | return @"DFUErrorRemoteSecureDFUUnsupportedType";
105 | case DFUErrorRemoteLegacyDFUDataExceedsLimit:
106 | return @"DFUErrorRemoteLegacyDFUDataExceedsLimit";
107 | case DFUErrorRemoteSecureDFUInvalidParameter:
108 | return @"DFUErrorRemoteSecureDFUInvalidParameter";
109 | case DFUErrorRemoteSecureDFUSignatureMismatch:
110 | return @"DFUErrorRemoteSecureDFUSignatureMismatch";
111 | case DFUErrorRemoteSecureDFUOpCodeNotSupported:
112 | return @"DFUErrorRemoteSecureDFUOpCodeNotSupported";
113 | case DFUErrorRemoteButtonlessDFUOperationFailed:
114 | return @"DFUErrorRemoteButtonlessDFUOperationFailed";
115 | case DFUErrorRemoteSecureDFUInsufficientResources:
116 | return @"DFUErrorRemoteSecureDFUInsufficientResources";
117 | case DFUErrorRemoteSecureDFUOperationNotPermitted:
118 | return @"DFUErrorRemoteSecureDFUOperationNotPermitted";
119 | case DFUErrorRemoteButtonlessDFUOpCodeNotSupported:
120 | return @"DFUErrorRemoteButtonlessDFUOpCodeNotSupported";
121 | case DFUErrorRemoteExperimentalButtonlessDFUSuccess:
122 | return @"DFUErrorRemoteExperimentalButtonlessDFUSuccess";
123 | case DFUErrorRemoteExperimentalButtonlessDFUOperationFailed:
124 | return @"DFUErrorRemoteExperimentalButtonlessDFUOperationFailed";
125 | case DFUErrorRemoteExperimentalButtonlessDFUOpCodeNotSupported:
126 | return @"DFUErrorRemoteExperimentalButtonlessDFUOpCodeNotSupported";
127 | default:
128 | return @"UNKNOWN_ERROR";
129 | }
130 | }
131 |
132 | - (void)dfuStateDidChangeTo:(enum DFUState)state
133 | {
134 | NSDictionary * evtBody = @{@"deviceAddress": self.deviceAddress,
135 | @"state": [self stateDescription:state],};
136 |
137 | [self sendEventWithName:DFUStateChangedEvent body:evtBody];
138 |
139 | if (state == DFUStateCompleted) {
140 | if (onDFUComplete) {
141 | onDFUComplete();
142 | }
143 | NSDictionary * resolveBody = @{@"deviceAddress": self.deviceAddress,};
144 |
145 | self.resolve(resolveBody);
146 | }
147 | }
148 |
149 | - (void) dfuError:(enum DFUError)error
150 | didOccurWithMessage:(NSString * _Nonnull)message
151 | {
152 | if (onDFUError) {
153 | onDFUError();
154 | }
155 |
156 | NSDictionary * evtBody = @{@"deviceAddress": self.deviceAddress,
157 | @"state": @"DFU_FAILED",};
158 |
159 | [self sendEventWithName:DFUStateChangedEvent body:evtBody];
160 |
161 | self.reject([self errorDescription:error], message, nil);
162 | }
163 |
164 | - (void)dfuProgressDidChangeFor:(NSInteger)part
165 | outOf:(NSInteger)totalParts
166 | to:(NSInteger)progress
167 | currentSpeedBytesPerSecond:(double)currentSpeedBytesPerSecond
168 | avgSpeedBytesPerSecond:(double)avgSpeedBytesPerSecond
169 | {
170 | NSDictionary * evtBody = @{@"deviceAddress": self.deviceAddress,
171 | @"currentPart": [NSNumber numberWithInteger:part],
172 | @"partsTotal": [NSNumber numberWithInteger:totalParts],
173 | @"percent": [NSNumber numberWithInteger:progress],
174 | @"speed": [NSNumber numberWithDouble:currentSpeedBytesPerSecond],
175 | @"avgSpeed": [NSNumber numberWithDouble:avgSpeedBytesPerSecond],};
176 |
177 | [self sendEventWithName:DFUProgressEvent body:evtBody];
178 | }
179 |
180 | - (void)logWith:(enum LogLevel)level message:(NSString * _Nonnull)message
181 | {
182 | NSLog(@"logWith: %ld message: '%@'", (long)level, message);
183 | }
184 |
185 | RCT_EXPORT_METHOD(startDFU:(NSString *)deviceAddress
186 | deviceName:(NSString *)deviceName
187 | filePath:(NSString *)filePath
188 | alternativeAdvertisingNameEnabled:(BOOL *)alternativeAdvertisingNameEnabled
189 | resolver:(RCTPromiseResolveBlock)resolve
190 | rejecter:(RCTPromiseRejectBlock)reject)
191 | {
192 | self.deviceAddress = deviceAddress;
193 | self.resolve = resolve;
194 | self.reject = reject;
195 |
196 | if (!getCentralManager) {
197 | reject(@"nil_central_manager_getter", @"Attempted to start DFU without central manager getter", nil);
198 | } else {
199 | CBCentralManager * centralManager = getCentralManager();
200 |
201 | if (!centralManager) {
202 | reject(@"nil_central_manager", @"Call to getCentralManager returned nil", nil);
203 | } else if (!deviceAddress) {
204 | reject(@"nil_device_address", @"Attempted to start DFU with nil deviceAddress", nil);
205 | } else if (!filePath) {
206 | reject(@"nil_file_path", @"Attempted to start DFU with nil filePath", nil);
207 | } else {
208 | NSUUID * uuid = [[NSUUID alloc] initWithUUIDString:deviceAddress];
209 |
210 | NSArray * peripherals = [centralManager retrievePeripheralsWithIdentifiers:@[uuid]];
211 |
212 | if ([peripherals count] != 1) {
213 | reject(@"unable_to_find_device", @"Could not find device with deviceAddress", nil);
214 | } else {
215 | CBPeripheral * peripheral = [peripherals objectAtIndex:0];
216 |
217 | NSURL * url = [NSURL URLWithString:filePath];
218 |
219 | DFUFirmware * firmware = [[DFUFirmware alloc] initWithUrlToZipFile:url];
220 |
221 | DFUServiceInitiator * initiator = [[[DFUServiceInitiator alloc]
222 | initWithCentralManager:centralManager
223 | target:peripheral]
224 | withFirmware:firmware];
225 |
226 | initiator.logger = self;
227 | initiator.delegate = self;
228 | initiator.progressDelegate = self;
229 | initiator.alternativeAdvertisingNameEnabled = alternativeAdvertisingNameEnabled;
230 |
231 | DFUServiceController * controller = [initiator start];
232 | }
233 | }
234 | }
235 | }
236 |
237 | + (void)setCentralManagerGetter:(CBCentralManager * (^)())getter
238 | {
239 | getCentralManager = getter;
240 | }
241 |
242 | + (void)setOnDFUComplete:(void (^)())onComplete
243 | {
244 | onDFUComplete = onComplete;
245 | }
246 |
247 | + (void)setOnDFUError:(void (^)())onError
248 | {
249 | onDFUError = onError;
250 | }
251 |
252 | @end
253 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-nordic-dfu [](https://badge.fury.io/js/react-native-nordic-dfu) [](https://circleci.com/gh/Pilloxa/react-native-nordic-dfu) [](https://snyk.io/test/github/pilloxa/react-native-nordic-dfu)
2 |
3 | > ⚠️ Warning! This library is no longer actively maintained. For a more up to date version check out: [Salt-PepperEngineering/react-native-nordic-dfu](https://github.com/Salt-PepperEngineering/react-native-nordic-dfu)
4 |
5 | This library allows you to do a Device Firmware Update (DFU) of your nrf51 or
6 | nrf52 chip from Nordic Semiconductor. It works for both iOS and Android.
7 |
8 | For more info about the DFU process, see: [Resources](#resources)
9 |
10 | ## Installation
11 |
12 | Install and link the NPM package per usual with
13 |
14 | ```bash
15 | npm install --save react-native-nordic-dfu
16 | ```
17 |
18 | or
19 |
20 | ```bash
21 | yarn add react-native-nordic-dfu
22 | ```
23 |
24 | For React Native below 60.0 version
25 |
26 | ```bash
27 | react-native link react-native-nordic-dfu
28 | ```
29 |
30 | ### Minimum requirements
31 |
32 | This project has been verified to work with the following dependencies, though other versions may work as well.
33 |
34 | | Dependency | Version |
35 | | ------------ | ------- |
36 | | React Native | 0.59.4 |
37 | | XCode | 10.2 |
38 | | Swift | 5.0 |
39 | | CocoaPods | 1.6.1 |
40 | | Gradle | 5.3.1 |
41 |
42 | ### iOS
43 |
44 | The iOS version of this library has native dependencies that need to be installed via `CocoaPods`, which is currently the only supported method for installing this library. (PR's for alternative installation methods are welcome!)
45 |
46 | Previous versions supported manual linking, but this was prone to errors every time a new version of XCode and/or Swift was released, which is why this support was dropped. If you've previously installed this library manually, you'll want to remove the old installation and replace it with CocoaPods.
47 |
48 | #### CocoaPods
49 |
50 | On your project directory;
51 |
52 | ```bash
53 | cd ios && pod install
54 | ```
55 |
56 | If your React Native version below 0.60 or any problem occures on pod command, you can try these steps;
57 |
58 | Add the following to your `Podfile`
59 |
60 | ```ruby
61 | target "YourApp" do
62 |
63 | ...
64 | pod "react-native-nordic-dfu", path: "../node_modules/react-native-nordic-dfu"
65 | ...
66 |
67 | end
68 | ```
69 |
70 | and in the same folder as the Podfile run
71 |
72 | ```bash
73 | pod install
74 | ```
75 |
76 | Since there's native Swift dependencies you need to set which Swift version your project complies with. If you haven't already done this, open up your project with XCode and add a User-Defined setting under Build Settings: `SWIFT_VERSION = `.
77 |
78 | If your React Native version is higher than 0.60, probably it's already there.
79 |
80 | #### Bluetooth integration
81 |
82 | This library needs access to an instance of `CBCentralManager`, which you most likely will have instantiated already if you're using Bluetooth for other purposes than DFU in your project.
83 |
84 | To integrate with your existing Bluetooth setup, call `[RNNordicDfu setCentralManagerGetter:<...>]` with a block argument that returns your `CBCentralManager` instance.
85 |
86 | If you want control over the `CBCentralManager` instance after the DFU process is done you might need to provide the `onDFUComplete` and `onDFUError` callbacks to transfer back delegate control.
87 |
88 | Example code;
89 |
90 | ```swift
91 | ...
92 | ...
93 | #import "RNNordicDfu.h"
94 | #import "BleManager.h"
95 |
96 | @implementation AppDelegate
97 |
98 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
99 | ...
100 | ...
101 |
102 | [RNNordicDfu setCentralManagerGetter:^() {
103 | return [BleManager getCentralManager];
104 | }];
105 |
106 | // Reset manager delegate since the Nordic DFU lib "steals" control over it
107 | [RNNordicDfu setOnDFUComplete:^() {
108 | NSLog(@"onDFUComplete");
109 | CBCentralManager * manager = [BleManager getCentralManager];
110 | manager.delegate = [BleManager getInstance];
111 | }];
112 |
113 | [RNNordicDfu setOnDFUError:^() {
114 | NSLog(@"onDFUError");
115 | CBCentralManager * manager = [BleManager getCentralManager];
116 | manager.delegate = [BleManager getInstance];
117 | }];
118 |
119 | return YES;
120 | }
121 |
122 | ```
123 |
124 | You can find them aslo in example project.
125 |
126 | On iOS side this library requires to BleManager module which that [react-native-ble-manager](https://github.com/innoveit/react-native-ble-manager) provides.
127 |
128 | It required because;
129 |
130 | - You need `BleManager.h` module on AppDelegate file for integration.
131 | - You should call `BleManager.start()` (for once) before the trigger a DFU process on iOS or you will get error like [this issue](https://github.com/Pilloxa/react-native-nordic-dfu/issues/82).
132 |
133 | ### Android
134 |
135 | Android requires that you have `FOREGROUND_SERVICE` permissions.
136 | You will need the following in your AndroidManifest.xml
137 |
138 | ```
139 |
140 | ```
141 |
142 | ## API
143 |
144 |
145 |
146 | ### startDFU
147 |
148 | Starts the DFU process
149 |
150 | Observe: The peripheral must have been discovered by the native BLE side so that the
151 | bluetooth stack knows about it. This library will not do a scan but only
152 | the actual connect and then the transfer. See the example project to see how it can be
153 | done in React Native.
154 |
155 | **Parameters**
156 |
157 | - `obj` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)**
158 | - `obj.deviceAddress` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The `identifier`\* of the device that should be updated
159 | - `obj.deviceName` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The name of the device in the update notification (optional, default `null`)
160 | - `obj.filePath` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The file system path to the zip-file used for updating
161 | - `obj.alternativeAdvertisingNameEnabled` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Send unique name to device before it is switched into bootloader mode (iOS only) - defaults to `true`
162 |
163 | \* `identifier` — MAC address (Android) / UUID (iOS)
164 |
165 | **Examples**
166 |
167 | ```javascript
168 | import { NordicDFU, DFUEmitter } from "react-native-nordic-dfu";
169 |
170 | NordicDFU.startDFU({
171 | deviceAddress: "C3:53:C0:39:2F:99",
172 | deviceName: "Pilloxa Pillbox",
173 | filePath: "/data/user/0/com.nordicdfuexample/files/RNFetchBlobTmp4of.zip",
174 | })
175 | .then((res) => console.log("Transfer done:", res))
176 | .catch(console.log);
177 | ```
178 |
179 | Returns **[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)** A promise that resolves or rejects with the `deviceAddress` in the return value
180 |
181 | ### DFUEmitter
182 |
183 | Event emitter for DFU state and progress events
184 |
185 | **Examples**
186 |
187 | ```javascript
188 | import { NordicDFU, DFUEmitter } from "react-native-nordic-dfu";
189 |
190 | DFUEmitter.addListener(
191 | "DFUProgress",
192 | ({ percent, currentPart, partsTotal, avgSpeed, speed }) => {
193 | console.log("DFU progress: " + percent + "%");
194 | }
195 | );
196 |
197 | DFUEmitter.addListener("DFUStateChanged", ({ state }) => {
198 | console.log("DFU State:", state);
199 | });
200 | ```
201 |
202 | ## Selecting firmware file from local storage
203 |
204 | If your user will select the firmware file from local storage you should keep on mind some issues;
205 |
206 | You can use [react-native-document-picker](https://github.com/Elyx0/react-native-document-picker) library for file selecting process.
207 |
208 | ### On iOS
209 |
210 | You should select file type as `public.archive` or you will get null type error as like [this issue](https://github.com/Pilloxa/react-native-nordic-dfu/issues/100)
211 |
212 | ```js
213 | DocumentPicker.pick({ type: "public.archive" });
214 | ```
215 |
216 | If your device getting disconnect after enable DFU, you should set `false` value to `alternativeAdvertisingNameEnabled` prop while starting DFU.
217 |
218 | ```js
219 | NordicDFU.startDFU({
220 | deviceAddress: "XXXXXXXX-XXXX-XXXX-XXXX-XX",
221 | filePath: firmwareFile.uri,
222 | alternativeAdvertisingNameEnabled: false,
223 | });
224 | ```
225 |
226 | ### On Android
227 |
228 | Some Android versions directly selecting file may can cause errors. If you get any file error you should copy it to your local storage. Like cache directory.
229 |
230 | You can use [react-native-fs](https://github.com/itinance/react-native-fs) for copying file.
231 |
232 | ```js
233 | const firmwareFile = await DocumentPicker.pick({ type: DocumentPicker.types.zip })
234 | const destination = RNFS.CachesDirectoryPath + "/firmwareFile.zip");
235 |
236 | await RNFS.copyFile(formatFile.uri, destination);
237 |
238 | NordicDFU.startDFU({ deviceAddress: "XX:XX:XX:XX:XX:XX", filePath: destination })
239 | ```
240 |
241 | If you getting disconnect error sometimes while starting DFU process, you should connect the device before start it.
242 |
243 | ## Example project
244 |
245 | Navigate to `example/` and run
246 |
247 | ```bash
248 | npm install
249 | ```
250 |
251 | Run the iOS project with
252 |
253 | ```bash
254 | react-native run-ios
255 | ```
256 |
257 | and the Android project with
258 |
259 | ```bash
260 | react-native run-android
261 | ```
262 |
263 | ## Development
264 |
265 | PR's are always welcome!
266 |
267 | ## Resources
268 |
269 | - [DFU Introduction](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/examples_ble_dfu.html?cp=6_0_0_4_3_1 "BLE Bootloader/DFU")
270 | - [Secure DFU Introduction](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v12.0.0/ble_sdk_app_dfu_bootloader.html?cp=4_0_0_4_3_1 "BLE Secure DFU Bootloader")
271 | - [How to create init packet](https://github.com/NordicSemiconductor/Android-nRF-Connect/tree/master/init%20packet%20handling "Init packet handling")
272 | - [nRF51 Development Kit (DK)](http://www.nordicsemi.com/eng/Products/nRF51-DK "nRF51 DK") (compatible with Arduino Uno Revision 3)
273 | - [nRF52 Development Kit (DK)](http://www.nordicsemi.com/eng/Products/Bluetooth-Smart-Bluetooth-low-energy/nRF52-DK "nRF52 DK") (compatible with Arduino Uno Revision 3)
274 |
275 | ## Sponsored by
276 |
277 | [](https://pilloxa.com)
278 |
--------------------------------------------------------------------------------
/example/ios/NordicDFUExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
11 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
12 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
14 | AFBD98CE42EE4D292DE30278 /* Pods_NordicDFUExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6478854F2D98962939006428 /* Pods_NordicDFUExample.framework */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXCopyFilesBuildPhase section */
18 | A53E61CC1F45E7370001EB4F /* Embed Frameworks */ = {
19 | isa = PBXCopyFilesBuildPhase;
20 | buildActionMask = 2147483647;
21 | dstPath = "";
22 | dstSubfolderSpec = 10;
23 | files = (
24 | );
25 | name = "Embed Frameworks";
26 | runOnlyForDeploymentPostprocessing = 0;
27 | };
28 | /* End PBXCopyFilesBuildPhase section */
29 |
30 | /* Begin PBXFileReference section */
31 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; };
32 | 13B07F961A680F5B00A75B9A /* NordicDFUExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NordicDFUExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
33 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = NordicDFUExample/AppDelegate.h; sourceTree = ""; };
34 | 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = NordicDFUExample/AppDelegate.m; sourceTree = ""; };
35 | 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
36 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = NordicDFUExample/Images.xcassets; sourceTree = ""; };
37 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NordicDFUExample/Info.plist; sourceTree = ""; };
38 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NordicDFUExample/main.m; sourceTree = ""; };
39 | 23DB7F518D38EFB05D9954C8 /* Pods-NordicDFUExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NordicDFUExample.release.xcconfig"; path = "Target Support Files/Pods-NordicDFUExample/Pods-NordicDFUExample.release.xcconfig"; sourceTree = ""; };
40 | 6478854F2D98962939006428 /* Pods_NordicDFUExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NordicDFUExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
41 | FA2EA6D15548AF2E9141F82E /* Pods-NordicDFUExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NordicDFUExample.debug.xcconfig"; path = "Target Support Files/Pods-NordicDFUExample/Pods-NordicDFUExample.debug.xcconfig"; sourceTree = ""; };
42 | /* End PBXFileReference section */
43 |
44 | /* Begin PBXFrameworksBuildPhase section */
45 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
46 | isa = PBXFrameworksBuildPhase;
47 | buildActionMask = 2147483647;
48 | files = (
49 | AFBD98CE42EE4D292DE30278 /* Pods_NordicDFUExample.framework in Frameworks */,
50 | );
51 | runOnlyForDeploymentPostprocessing = 0;
52 | };
53 | /* End PBXFrameworksBuildPhase section */
54 |
55 | /* Begin PBXGroup section */
56 | 13B07FAE1A68108700A75B9A /* NordicDFUExample */ = {
57 | isa = PBXGroup;
58 | children = (
59 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */,
60 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */,
61 | 13B07FB01A68108700A75B9A /* AppDelegate.m */,
62 | 13B07FB51A68108700A75B9A /* Images.xcassets */,
63 | 13B07FB61A68108700A75B9A /* Info.plist */,
64 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
65 | 13B07FB71A68108700A75B9A /* main.m */,
66 | );
67 | name = NordicDFUExample;
68 | sourceTree = "";
69 | };
70 | 3A4D31ACCE1F1F6885CF77A1 /* Pods */ = {
71 | isa = PBXGroup;
72 | children = (
73 | FA2EA6D15548AF2E9141F82E /* Pods-NordicDFUExample.debug.xcconfig */,
74 | 23DB7F518D38EFB05D9954C8 /* Pods-NordicDFUExample.release.xcconfig */,
75 | );
76 | path = Pods;
77 | sourceTree = "";
78 | };
79 | 83CBB9F61A601CBA00E9B192 = {
80 | isa = PBXGroup;
81 | children = (
82 | 13B07FAE1A68108700A75B9A /* NordicDFUExample */,
83 | 83CBBA001A601CBA00E9B192 /* Products */,
84 | 3A4D31ACCE1F1F6885CF77A1 /* Pods */,
85 | CD8C38820690DE8FB4BF3E99 /* Frameworks */,
86 | );
87 | indentWidth = 2;
88 | sourceTree = "";
89 | tabWidth = 2;
90 | };
91 | 83CBBA001A601CBA00E9B192 /* Products */ = {
92 | isa = PBXGroup;
93 | children = (
94 | 13B07F961A680F5B00A75B9A /* NordicDFUExample.app */,
95 | );
96 | name = Products;
97 | sourceTree = "";
98 | };
99 | CD8C38820690DE8FB4BF3E99 /* Frameworks */ = {
100 | isa = PBXGroup;
101 | children = (
102 | 6478854F2D98962939006428 /* Pods_NordicDFUExample.framework */,
103 | );
104 | name = Frameworks;
105 | sourceTree = "";
106 | };
107 | /* End PBXGroup section */
108 |
109 | /* Begin PBXNativeTarget section */
110 | 13B07F861A680F5B00A75B9A /* NordicDFUExample */ = {
111 | isa = PBXNativeTarget;
112 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NordicDFUExample" */;
113 | buildPhases = (
114 | 554227AE062BEDCA14FCD59E /* [CP] Check Pods Manifest.lock */,
115 | 13B07F871A680F5B00A75B9A /* Sources */,
116 | 13B07F8C1A680F5B00A75B9A /* Frameworks */,
117 | 13B07F8E1A680F5B00A75B9A /* Resources */,
118 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
119 | A53E61CC1F45E7370001EB4F /* Embed Frameworks */,
120 | 4B0AD483234F0DC3E0F75BEF /* [CP] Embed Pods Frameworks */,
121 | );
122 | buildRules = (
123 | );
124 | dependencies = (
125 | );
126 | name = NordicDFUExample;
127 | productName = "Hello World";
128 | productReference = 13B07F961A680F5B00A75B9A /* NordicDFUExample.app */;
129 | productType = "com.apple.product-type.application";
130 | };
131 | /* End PBXNativeTarget section */
132 |
133 | /* Begin PBXProject section */
134 | 83CBB9F71A601CBA00E9B192 /* Project object */ = {
135 | isa = PBXProject;
136 | attributes = {
137 | LastUpgradeCheck = 0830;
138 | ORGANIZATIONNAME = Facebook;
139 | TargetAttributes = {
140 | 13B07F861A680F5B00A75B9A = {
141 | DevelopmentTeam = X8M4Z7CAY5;
142 | };
143 | };
144 | };
145 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NordicDFUExample" */;
146 | compatibilityVersion = "Xcode 3.2";
147 | developmentRegion = English;
148 | hasScannedForEncodings = 0;
149 | knownRegions = (
150 | English,
151 | en,
152 | Base,
153 | );
154 | mainGroup = 83CBB9F61A601CBA00E9B192;
155 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
156 | projectDirPath = "";
157 | projectRoot = "";
158 | targets = (
159 | 13B07F861A680F5B00A75B9A /* NordicDFUExample */,
160 | );
161 | };
162 | /* End PBXProject section */
163 |
164 | /* Begin PBXResourcesBuildPhase section */
165 | 13B07F8E1A680F5B00A75B9A /* Resources */ = {
166 | isa = PBXResourcesBuildPhase;
167 | buildActionMask = 2147483647;
168 | files = (
169 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
170 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
171 | );
172 | runOnlyForDeploymentPostprocessing = 0;
173 | };
174 | /* End PBXResourcesBuildPhase section */
175 |
176 | /* Begin PBXShellScriptBuildPhase section */
177 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
178 | isa = PBXShellScriptBuildPhase;
179 | buildActionMask = 2147483647;
180 | files = (
181 | );
182 | inputPaths = (
183 | );
184 | name = "Bundle React Native code and images";
185 | outputPaths = (
186 | );
187 | runOnlyForDeploymentPostprocessing = 0;
188 | shellPath = /bin/sh;
189 | shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
190 | };
191 | 4B0AD483234F0DC3E0F75BEF /* [CP] Embed Pods Frameworks */ = {
192 | isa = PBXShellScriptBuildPhase;
193 | buildActionMask = 2147483647;
194 | files = (
195 | );
196 | inputFileListPaths = (
197 | );
198 | inputPaths = (
199 | "${PODS_ROOT}/Target Support Files/Pods-NordicDFUExample/Pods-NordicDFUExample-frameworks.sh",
200 | "${BUILT_PRODUCTS_DIR}/DoubleConversion/DoubleConversion.framework",
201 | "${BUILT_PRODUCTS_DIR}/Folly/folly.framework",
202 | "${BUILT_PRODUCTS_DIR}/React/React.framework",
203 | "${BUILT_PRODUCTS_DIR}/ZIPFoundation/ZIPFoundation.framework",
204 | "${BUILT_PRODUCTS_DIR}/glog/glog.framework",
205 | "${BUILT_PRODUCTS_DIR}/iOSDFULibrary/iOSDFULibrary.framework",
206 | "${BUILT_PRODUCTS_DIR}/react-native-ble-manager/react_native_ble_manager.framework",
207 | "${BUILT_PRODUCTS_DIR}/react-native-nordic-dfu/react_native_nordic_dfu.framework",
208 | "${BUILT_PRODUCTS_DIR}/rn-fetch-blob/rn_fetch_blob.framework",
209 | "${BUILT_PRODUCTS_DIR}/yoga/yoga.framework",
210 | );
211 | name = "[CP] Embed Pods Frameworks";
212 | outputFileListPaths = (
213 | );
214 | outputPaths = (
215 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DoubleConversion.framework",
216 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/folly.framework",
217 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework",
218 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZIPFoundation.framework",
219 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework",
220 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/iOSDFULibrary.framework",
221 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_ble_manager.framework",
222 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_nordic_dfu.framework",
223 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/rn_fetch_blob.framework",
224 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/yoga.framework",
225 | );
226 | runOnlyForDeploymentPostprocessing = 0;
227 | shellPath = /bin/sh;
228 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NordicDFUExample/Pods-NordicDFUExample-frameworks.sh\"\n";
229 | showEnvVarsInLog = 0;
230 | };
231 | 554227AE062BEDCA14FCD59E /* [CP] Check Pods Manifest.lock */ = {
232 | isa = PBXShellScriptBuildPhase;
233 | buildActionMask = 2147483647;
234 | files = (
235 | );
236 | inputFileListPaths = (
237 | );
238 | inputPaths = (
239 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
240 | "${PODS_ROOT}/Manifest.lock",
241 | );
242 | name = "[CP] Check Pods Manifest.lock";
243 | outputFileListPaths = (
244 | );
245 | outputPaths = (
246 | "$(DERIVED_FILE_DIR)/Pods-NordicDFUExample-checkManifestLockResult.txt",
247 | );
248 | runOnlyForDeploymentPostprocessing = 0;
249 | shellPath = /bin/sh;
250 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
251 | showEnvVarsInLog = 0;
252 | };
253 | /* End PBXShellScriptBuildPhase section */
254 |
255 | /* Begin PBXSourcesBuildPhase section */
256 | 13B07F871A680F5B00A75B9A /* Sources */ = {
257 | isa = PBXSourcesBuildPhase;
258 | buildActionMask = 2147483647;
259 | files = (
260 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
261 | 13B07FC11A68108700A75B9A /* main.m in Sources */,
262 | );
263 | runOnlyForDeploymentPostprocessing = 0;
264 | };
265 | /* End PBXSourcesBuildPhase section */
266 |
267 | /* Begin PBXVariantGroup section */
268 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
269 | isa = PBXVariantGroup;
270 | children = (
271 | 13B07FB21A68108700A75B9A /* Base */,
272 | );
273 | name = LaunchScreen.xib;
274 | path = NordicDFUExample;
275 | sourceTree = "";
276 | };
277 | /* End PBXVariantGroup section */
278 |
279 | /* Begin XCBuildConfiguration section */
280 | 13B07F941A680F5B00A75B9A /* Debug */ = {
281 | isa = XCBuildConfiguration;
282 | baseConfigurationReference = FA2EA6D15548AF2E9141F82E /* Pods-NordicDFUExample.debug.xcconfig */;
283 | buildSettings = {
284 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
285 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
286 | CURRENT_PROJECT_VERSION = 1;
287 | DEAD_CODE_STRIPPING = NO;
288 | DEVELOPMENT_TEAM = X8M4Z7CAY5;
289 | ENABLE_BITCODE = NO;
290 | INFOPLIST_FILE = NordicDFUExample/Info.plist;
291 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
292 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
293 | ONLY_ACTIVE_ARCH = YES;
294 | OTHER_LDFLAGS = (
295 | "$(inherited)",
296 | "-ObjC",
297 | "-lc++",
298 | );
299 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
300 | PRODUCT_NAME = NordicDFUExample;
301 | VALID_ARCHS = "arm64 armv7 armv7s";
302 | VERSIONING_SYSTEM = "apple-generic";
303 | };
304 | name = Debug;
305 | };
306 | 13B07F951A680F5B00A75B9A /* Release */ = {
307 | isa = XCBuildConfiguration;
308 | baseConfigurationReference = 23DB7F518D38EFB05D9954C8 /* Pods-NordicDFUExample.release.xcconfig */;
309 | buildSettings = {
310 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
311 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
312 | CURRENT_PROJECT_VERSION = 1;
313 | DEVELOPMENT_TEAM = X8M4Z7CAY5;
314 | ENABLE_BITCODE = NO;
315 | INFOPLIST_FILE = NordicDFUExample/Info.plist;
316 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
317 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
318 | ONLY_ACTIVE_ARCH = NO;
319 | OTHER_LDFLAGS = (
320 | "$(inherited)",
321 | "-ObjC",
322 | "-lc++",
323 | );
324 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
325 | PRODUCT_NAME = NordicDFUExample;
326 | VALID_ARCHS = "arm64 armv7 armv7s";
327 | VERSIONING_SYSTEM = "apple-generic";
328 | };
329 | name = Release;
330 | };
331 | 83CBBA201A601CBA00E9B192 /* Debug */ = {
332 | isa = XCBuildConfiguration;
333 | buildSettings = {
334 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
335 | ALWAYS_SEARCH_USER_PATHS = NO;
336 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
337 | CLANG_CXX_LIBRARY = "libc++";
338 | CLANG_ENABLE_MODULES = YES;
339 | CLANG_ENABLE_OBJC_ARC = YES;
340 | CLANG_WARN_BOOL_CONVERSION = YES;
341 | CLANG_WARN_CONSTANT_CONVERSION = YES;
342 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
343 | CLANG_WARN_EMPTY_BODY = YES;
344 | CLANG_WARN_ENUM_CONVERSION = YES;
345 | CLANG_WARN_INFINITE_RECURSION = YES;
346 | CLANG_WARN_INT_CONVERSION = YES;
347 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
348 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
349 | CLANG_WARN_UNREACHABLE_CODE = YES;
350 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
351 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
352 | COPY_PHASE_STRIP = NO;
353 | ENABLE_STRICT_OBJC_MSGSEND = YES;
354 | ENABLE_TESTABILITY = YES;
355 | GCC_C_LANGUAGE_STANDARD = gnu99;
356 | GCC_DYNAMIC_NO_PIC = NO;
357 | GCC_NO_COMMON_BLOCKS = YES;
358 | GCC_OPTIMIZATION_LEVEL = 0;
359 | GCC_PREPROCESSOR_DEFINITIONS = (
360 | "DEBUG=1",
361 | "$(inherited)",
362 | );
363 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
365 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
366 | GCC_WARN_UNDECLARED_SELECTOR = YES;
367 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
368 | GCC_WARN_UNUSED_FUNCTION = YES;
369 | GCC_WARN_UNUSED_VARIABLE = YES;
370 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
371 | MTL_ENABLE_DEBUG_INFO = YES;
372 | ONLY_ACTIVE_ARCH = YES;
373 | SDKROOT = iphoneos;
374 | SWIFT_VERSION = 5;
375 | };
376 | name = Debug;
377 | };
378 | 83CBBA211A601CBA00E9B192 /* Release */ = {
379 | isa = XCBuildConfiguration;
380 | buildSettings = {
381 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
382 | ALWAYS_SEARCH_USER_PATHS = NO;
383 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
384 | CLANG_CXX_LIBRARY = "libc++";
385 | CLANG_ENABLE_MODULES = YES;
386 | CLANG_ENABLE_OBJC_ARC = YES;
387 | CLANG_WARN_BOOL_CONVERSION = YES;
388 | CLANG_WARN_CONSTANT_CONVERSION = YES;
389 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
390 | CLANG_WARN_EMPTY_BODY = YES;
391 | CLANG_WARN_ENUM_CONVERSION = YES;
392 | CLANG_WARN_INFINITE_RECURSION = YES;
393 | CLANG_WARN_INT_CONVERSION = YES;
394 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
395 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
396 | CLANG_WARN_UNREACHABLE_CODE = YES;
397 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
398 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
399 | COPY_PHASE_STRIP = YES;
400 | ENABLE_NS_ASSERTIONS = NO;
401 | ENABLE_STRICT_OBJC_MSGSEND = YES;
402 | GCC_C_LANGUAGE_STANDARD = gnu99;
403 | GCC_NO_COMMON_BLOCKS = YES;
404 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
405 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
406 | GCC_WARN_UNDECLARED_SELECTOR = YES;
407 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
408 | GCC_WARN_UNUSED_FUNCTION = YES;
409 | GCC_WARN_UNUSED_VARIABLE = YES;
410 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
411 | MTL_ENABLE_DEBUG_INFO = NO;
412 | SDKROOT = iphoneos;
413 | SWIFT_VERSION = 5;
414 | VALIDATE_PRODUCT = YES;
415 | };
416 | name = Release;
417 | };
418 | /* End XCBuildConfiguration section */
419 |
420 | /* Begin XCConfigurationList section */
421 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NordicDFUExample" */ = {
422 | isa = XCConfigurationList;
423 | buildConfigurations = (
424 | 13B07F941A680F5B00A75B9A /* Debug */,
425 | 13B07F951A680F5B00A75B9A /* Release */,
426 | );
427 | defaultConfigurationIsVisible = 0;
428 | defaultConfigurationName = Release;
429 | };
430 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NordicDFUExample" */ = {
431 | isa = XCConfigurationList;
432 | buildConfigurations = (
433 | 83CBBA201A601CBA00E9B192 /* Debug */,
434 | 83CBBA211A601CBA00E9B192 /* Release */,
435 | );
436 | defaultConfigurationIsVisible = 0;
437 | defaultConfigurationName = Release;
438 | };
439 | /* End XCConfigurationList section */
440 | };
441 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
442 | }
443 |
--------------------------------------------------------------------------------