├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── android ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── estimote │ └── react │ ├── RNEstimoteProximityModule.java │ └── RNEstimoteProximityPackage.java ├── estimote-react-native-proximity.podspec ├── example ├── .buckconfig ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .watchmanconfig ├── App.js ├── __tests__ │ └── App-test.js ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── proximityexample │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── Podfile │ ├── Podfile.lock │ ├── ProximityExample-tvOS │ │ └── Info.plist │ ├── ProximityExample-tvOSTests │ │ └── Info.plist │ ├── ProximityExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── ProximityExample-tvOS.xcscheme │ │ │ └── ProximityExample.xcscheme │ ├── ProximityExample.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── ProximityExample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── ProximityExampleTests │ │ ├── Info.plist │ │ └── ProximityExampleTests.m ├── metro.config.js ├── package.json └── proximityObserver.js ├── index.js ├── ios ├── EPXHeaders │ ├── EPXCloudCredentials.h │ ├── EPXProximityObserver.h │ ├── EPXProximityObserverConfiguration.h │ ├── EPXProximityRange.h │ ├── EPXProximityZone.h │ ├── EPXProximityZoneContext.h │ ├── EstimoteProximitySDK-Swift.h │ └── EstimoteProximitySDK.h ├── RNEstimoteProximity.h ├── RNEstimoteProximity.m └── RNEstimoteProximity.xcodeproj │ └── project.pbxproj └── package.json /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | estimote-react-native-proximity-*.tgz 2 | example/package-lock.json 3 | Pods 4 | 5 | # OSX 6 | # 7 | .DS_Store 8 | 9 | # Xcode 10 | # 11 | build 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata 21 | *.xccheckout 22 | *.moved-aside 23 | DerivedData 24 | *.hmap 25 | *.ipa 26 | *.xcuserstate 27 | project.xcworkspace 28 | 29 | # Android/IntelliJ 30 | # 31 | build 32 | .idea 33 | .gradle 34 | local.properties 35 | *.iml 36 | 37 | # node.js 38 | # 39 | node_modules 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # BUCK 44 | buck-out 45 | \.buckd 46 | *.keystore 47 | 48 | # fastlane 49 | # 50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 51 | # screenshots whenever they are needed. 52 | # For more information about the recommended setup visit: 53 | # https://docs.fastlane.tools/best-practices/source-control/ 54 | 55 | */fastlane/report.xml 56 | */fastlane/Preview.html 57 | */fastlane/screenshots 58 | 59 | # Bundle artifact 60 | *.jsbundle 61 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.6.0 4 | 5 | - Updated for compatibility with React Native 0.60. 6 | 7 | - Added a podspec for the new, built-in CocoaPods support. This means you no longer need to manually include Estimote Proximity SDK dependency in your Podfile. Instead, the new auto-linking will automatically pull the plugin's podspec, and the plugin's podspec will automatically pull Estimote Proximity SDK. 8 | 9 | - Migrated the native Android code to AndroidX. 10 | 11 | - This is a **breaking change**, and means that **0.6.0 can no longer be used with React Native < 0.60**. 12 | - If you happen to know a good way to support both AndroidX and the previous support libraries, please open an issue and let us know. 13 | 14 | - Updated the native Android Proximity SDK to 1.0.3, and the Android com.estimote:scanning-plugin to 0.25.2. 15 | 16 | - This fixes a potential crash if there's an Estimote LTE Beacon in range. 17 | 18 | ## 0.5.0 19 | 20 | - Fixed "undefined is not an object" error, as reported in https://github.com/Estimote/react-native-proximity/issues/21. 21 | 22 | - This error happened when the Observer hasn't been stopped properly before calling another `startObservingZones`. 23 | - Instead, the plugin will now automatically stop the previous observation, and log a warning about this. 24 | - Most commonly, this is tied to improper lifecycle management of the Observer. There's a new section in the README which explains this topic in more detail, and lays out some recommendations and best practices: https://github.com/Estimote/react-native-proximity#already-observing. The new warning also points to this section. 25 | 26 | - Updated the native Android module's build.gradle, getting rid of the warnings. 27 | 28 | ## 0.4.0 29 | 30 | - Updated the native iOS and Android Estimote Proximity SDKs to 1.0.0. 31 | 32 | - Updated the plugin to compile against Android 26 SDK, and target the Android API level 26. This is to [match the latest React Native version, 0.56][0.4.0-1]. 33 | 34 | - The bundled "example" app was also updated to React Native 0.56. 35 | 36 | - Since the Android plugin now targets API level 26, the background-scanning notification now requires to be assigned to a notification channel. You specify the channel ID and name in the `config` object, next to the notification's title, text, and icon, for example: 37 | 38 | ``` 39 | const config = { 40 | notification: { 41 | title: "Exploration mode is on", 42 | text: "We'll notify you when you're next to something interesting.", 43 | icon: 'ic_exploration_mode', 44 | 45 | channel: { 46 | id: "exploration-mode", 47 | name: "Exploration Mode" 48 | } 49 | } 50 | }; 51 | RNEP.proximityObserver.initialize(credentials, config); 52 | ``` 53 | 54 | You can learn more about notifications channels in [Notifications Overview: Notification channels][0.4.0-2]. 55 | 56 | [0.4.0-1]: https://github.com/react-native-community/react-native-releases/blob/master/CHANGELOG.md#android-projects-are-now-compiled-using-the-android-26-sdk 57 | [0.4.0-2]: https://developer.android.com/guide/topics/ui/notifiers/notifications#ManageChannels 58 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2018 Estimote, Inc. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-proximity 2 | 3 | React Native wrapper for Estimote Proximity SDK. 4 | 5 | You can read more about Estimote Proximity on [developer.estimote.com](https://developer.estimote.com). 6 | 7 | - [Prerequisites](#prerequisites) 8 | - [Installation](#installation) 9 | - [Location permission](#location-permission) 10 | - [Bluetooth permission](#bluetooth-permission) 11 | - [Background support](#background-support) 12 | - [Usage & examples](#usage--examples) 13 | - ["Already observing"](#already-observing) 14 | - [Contact & feedback](#contact--feedback) 15 | 16 | ## Prerequisites 17 | 18 | - React Native 0.60 19 | 20 | - if you're on React Native < 0.60, use version 0.5.0 of this plugin: 21 | 22 | ```console 23 | $ yarn add @estimote/react-native-proximity@0.5.0 24 | $ # or, if you use npm: 25 | $ npm install @estimote/react-native-proximity@0.5.0 --save --save-exact 26 | 27 | $ react-native link @estimote/react-native-proximity 28 | ``` 29 | 30 | then, follow the README from the 0.5.0 version: 31 | 32 | https://github.com/Estimote/react-native-proximity/blob/v0.5.0/README.md 33 | 34 | - "ejected" React Native project 35 | - see [Getting Started](https://facebook.github.io/react-native/docs/getting-started) and the "React Native CLI Quickstart" tab for everything you'll need to build native code 36 | 37 | - while normally you only need Xcode 9.4 or later, this plugin instead requires Xcode 10.2 or later 38 | 39 | ## Installation 40 | 41 | ```console 42 | $ yarn add @estimote/react-native-proximity 43 | $ # or, if you use npm: 44 | $ npm install @estimote/react-native-proximity --save 45 | ``` 46 | 47 | On **iOS**, you'll also need to: 48 | 49 | - edit `ios/Podfile` and change `platform :ios, '9.0'` to `platform :ios, '10.0'` 50 | - run `pod --repo-update install` inside the `ios` directory 51 | - in your Xcode project's Build Settings, find and set "Always Embed Swift in Standard Libraries" to "YES" 52 | - exception: if you only target iOS 12.2 or later, you can leave this at "NO" (that's because starting with iOS 12.2, Swift standard libraries are included in the system itself, and no longer need to be bundled with the app) 53 | 54 | On **Android**, you'll also need to: 55 | 56 | - edit `android/build.gradle` and change `minSdkVersion = 16` to `minSdkVersion = 18` 57 | 58 | ## Location permission 59 | 60 | Since detecting proximity to Bluetooth beacons gives you some idea of the user's location, both iOS and Android require that the user agrees to that, even though we're not actually using GPS or the likes. Location services must also be globally enabled in the system. 61 | 62 | ```javascript 63 | import * as RNEP from '@estimote/react-native-proximity' 64 | 65 | // this will trigger a popup with "allow this app to access your location?" 66 | RNEP.locationPermission.request() 67 | .then(permission => { // this is the user's decision 68 | // permission can be equal to: 69 | // * RNEP.locationPermission.DENIED - proximity detection won't work 70 | // * RNEP.locationPermission.WHEN_IN_USE - only when the app is active 71 | // * RNEP.locationPermission.ALWAYS - even when the app is not active 72 | }) 73 | ``` 74 | 75 | On **iOS**, you also need to make sure you have the following entries in your app's Info.plist file: (you'll usually find it at `ios/APP_NAME/Info.plist`) 76 | 77 | ```xml 78 | NSLocationWhenInUseUsageDescription 79 | We'll show you things near you in the app. 80 | NSLocationAlwaysAndWhenInUseUsageDescription 81 | We'll show you things near you in the app. With "always" access, we'll 82 | also send you notifications when you're near something interesting. 83 | ``` 84 | 85 | These are the messages that iOS will show as part of the location permission popup. 86 | 87 | On **Android**, the `targetSdkVersion` needs to be at least 23. New versions of react-native (0.56+) use 26+, so you don't need to do anything. If you're still on an older version, then in the `android/app/build.gradle` file: find `targetSdkVersion 22` and change it to `23`. 88 | 89 | ## Bluetooth permission 90 | 91 | On **iOS**, you also need to add the following entry in your app's Info.plist file: (you'll usually find it at `ios/APP_NAME/Info.plist`) 92 | 93 | ```xml 94 | NSBluetoothAlwaysUsageDescription 95 | We use Bluetooth beacons for better location accuracy indoors. 96 | ``` 97 | 98 | This message will show as part of the Bluetooth permission popup introduced in iOS 13. 99 | 100 | ## Background support 101 | 102 | Other than obtaining the `ALWAYS` location permission, there's just a little bit more to do if you want your app to keep getting the enter/exit/change callbacks in the background. 103 | 104 | On **iOS**, you need to: 105 | 106 | 1. Open the Xcode project. 107 | 2. Click on the top-level item in the project navigator to access the project settings. 108 | 3. Make sure your app is selected in the "TARGETS" section. 109 | 4. Go to the "Capabilities" tab. 110 | 5. Enable "Background Modes" and check "Uses Bluetooth LE accessories". 111 | 112 | **Note**: Background Modes undergo extra scrutiny during App Store review. If you're submitting your app to the App Store, we recommend proactively explaining in the notes why/how your app uses Bluetooth in the background. 113 | 114 | On **Android**, you need to: 115 | 116 | 1. Make sure your target API level is at least 23. 117 | 118 | - New versions of react-native (0.56+) use 26+, so you don't need to do anything. 119 | - If you're still on an older version, then in the `android/app/build.gradle` file: find `targetSdkVersion 22` and change it to `23`. 120 | 121 | 2. When initializing the Proximity Observer in your JavaScript code, make sure to pass a "notification" config. See the `example/proximityObserver.js` for more. 122 | 123 | 3. Add the following line to android/main/src/AndroidManifest.xml: 124 | 125 | ``` 126 | 127 | ``` 128 | 129 | ## Usage & examples 130 | 131 | Check [`example/proximityObserver.js`](https://github.com/Estimote/react-native-proximity/blob/master/example/proximityObserver.js) for a quick run-down of how to use this library. 132 | 133 | To set up the included example app for running: 134 | 135 | 1. Run `npm install` or `yarn install` inside `example`. 136 | 2. Run `pod --repo-update install` inside `example/ios`. 137 | 138 | Then, you can do the usual `react-native run-android` and `run-ios --device`. Note that iOS and Android simulators don't support Bluetooth, so **you need to run it on a physical device**. 139 | 140 | ### "Already observing" 141 | 142 | Some consideration is needed as to where to put the code that starts the Proximity Observer, and to properly stopping the Observer when necessary, or you might see this warning: 143 | 144 | > 'startObservingZones' was called while already observing. 145 | 146 | Generally speaking, there are two options, depending on your use case: 147 | 148 | 1. **Foreground**, with proximity events tied to a particular component. For example, maybe you have a map component, where you want to mark the user's approximate location, and re-render the map based on the proximity events you're getting. In this case, it's usually best to: 149 | 150 | - set up your zones in the `constructor` 151 | - start the Proximity Observer in the `constructor` or in `componentDidMount` 152 | - stop the Proximity Observer in the `componentWillUnmount` 153 | 154 | 2. **Background**, with proximity events tied to the app itself, and not to any particular component—not even the `App` component! This is important, because given proper configuration (see "Location permission" and "Background support" above), proximity events usually work even if the user swipes the app away at the app switcher. When this happens, the UI and all the components get removed, but the app itself can still process proximity events—for example, to show local notifications. 155 | 156 | In this case, you **must**\* start the Proximity Observer somewhere down the chain which starts in `index.js`, just like in the example app. There's usually no need to stop the Observer, since you want it running at all times. 157 | 158 | > \* well, technically, there are other options that'll work equally well; but when in doubt, use `index.js` 159 | 160 | These are just two general recommendations, but every app is different, so if you're not sure how to handle your particular use case, drop a post at [forums.estimote.com][forums], and we'll be happy to help. 161 | 162 | > If you're using redux for your state management, a good idea might be to start the Proximity Observer where you create your redux store, and have the proximity events dispatch appropriate actions. The rest of your app can then subscribe to state/store changes as needed, and benefit from the proximity events this way. What a beautiful separation of concerns! 163 | 164 | ## Contact & feedback 165 | 166 | Let us know your thoughts, feedback, and questions on [forums.estimote.com][forums]. 167 | 168 | [forums]: https://forums.estimote.com 169 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:3.4.1' 8 | } 9 | } 10 | 11 | apply plugin: 'com.android.library' 12 | 13 | android { 14 | compileSdkVersion 28 15 | buildToolsVersion "28.0.3" 16 | defaultConfig { 17 | minSdkVersion 18 18 | targetSdkVersion 28 19 | versionCode 1 20 | versionName "1.0" 21 | } 22 | lintOptions { 23 | abortOnError false 24 | } 25 | } 26 | 27 | repositories { 28 | jcenter() 29 | maven { url 'https://maven.google.com' } 30 | } 31 | 32 | dependencies { 33 | implementation 'com.facebook.react:react-native:+' 34 | implementation 'com.estimote:proximity-sdk:1.0.5' 35 | implementation 'com.estimote:scanning-plugin:0.25.4' 36 | } 37 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue May 15 12:34:30 CEST 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.10.2-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 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 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/java/com/estimote/react/RNEstimoteProximityModule.java: -------------------------------------------------------------------------------- 1 | package com.estimote.react; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationChannel; 5 | import android.app.NotificationManager; 6 | import android.os.Build; 7 | import android.util.Log; 8 | import androidx.core.app.NotificationCompat; 9 | 10 | import com.estimote.proximity_sdk.api.EstimoteCloudCredentials; 11 | import com.estimote.proximity_sdk.api.ProximityObserver; 12 | import com.estimote.proximity_sdk.api.ProximityObserverBuilder; 13 | import com.estimote.proximity_sdk.api.ProximityZone; 14 | import com.estimote.proximity_sdk.api.ProximityZoneBuilder; 15 | import com.estimote.proximity_sdk.api.ProximityZoneContext; 16 | 17 | import com.facebook.react.bridge.ReactApplicationContext; 18 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 19 | import com.facebook.react.bridge.ReactMethod; 20 | import com.facebook.react.bridge.ReadableArray; 21 | import com.facebook.react.bridge.ReadableMap; 22 | import com.facebook.react.bridge.WritableArray; 23 | import com.facebook.react.bridge.WritableMap; 24 | import com.facebook.react.bridge.WritableNativeArray; 25 | import com.facebook.react.bridge.WritableNativeMap; 26 | import com.facebook.react.modules.core.DeviceEventManagerModule; 27 | 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | import java.util.Map; 31 | import java.util.Set; 32 | 33 | import kotlin.Unit; 34 | import kotlin.jvm.functions.Function1; 35 | 36 | public class RNEstimoteProximityModule extends ReactContextBaseJavaModule { 37 | 38 | private static final String TAG = "RNEstimoteProximity"; 39 | 40 | private final ReactApplicationContext reactContext; 41 | 42 | private ProximityObserver observer; 43 | private ProximityObserver.Handler observationHandler; 44 | 45 | public RNEstimoteProximityModule(ReactApplicationContext reactContext) { 46 | super(reactContext); 47 | this.reactContext = reactContext; 48 | } 49 | 50 | @Override 51 | public String getName() { 52 | return "RNEstimoteProximity"; 53 | } 54 | 55 | @ReactMethod 56 | public void initialize(ReadableMap config) { 57 | Log.i(TAG, "Initializing with config: " + config.toString()); 58 | 59 | EstimoteCloudCredentials credentials = new EstimoteCloudCredentials( 60 | config.getString("appId"), config.getString("appToken")); 61 | 62 | ProximityObserverBuilder builder = new ProximityObserverBuilder(reactContext, credentials) 63 | .withBalancedPowerMode() 64 | .onError(new Function1() { 65 | @Override 66 | public Unit invoke(Throwable throwable) { 67 | Log.e(TAG, "Proximity Observer error: " + throwable); 68 | return null; 69 | } 70 | }); 71 | 72 | 73 | if (config.hasKey("notification")) { 74 | ReadableMap notificationConfig = config.getMap("notification"); 75 | 76 | String icon = notificationConfig.hasKey("icon") 77 | ? notificationConfig.getString("icon") 78 | : null; 79 | 80 | String title = notificationConfig.hasKey("title") 81 | ? notificationConfig.getString("title") 82 | : "Scanning for beacons..."; 83 | 84 | String text = notificationConfig.hasKey("text") 85 | ? notificationConfig.getString("text") 86 | : null; 87 | 88 | String channelId = "est-proximity-sdk"; 89 | String channelName = "Beacon Scanning"; 90 | 91 | if (notificationConfig.hasKey("channel")) { 92 | ReadableMap channelConfig = notificationConfig.getMap("channel"); 93 | 94 | if (channelConfig.hasKey("id")) { 95 | channelId = channelConfig.getString("id"); 96 | } 97 | if (channelConfig.hasKey("name")) { 98 | channelName = channelConfig.getString("name"); 99 | } 100 | } 101 | 102 | createNotificationChannel(channelId, channelName); 103 | builder.withScannerInForegroundService(createNotification(icon, title, text, channelId)); 104 | } 105 | 106 | observer = builder.build(); 107 | } 108 | 109 | @ReactMethod 110 | public void startObservingZones(ReadableArray zonesJSON) { 111 | Log.d(TAG, "startObservingZones: " + zonesJSON); 112 | 113 | List zones = new ArrayList(zonesJSON.size()); 114 | 115 | for (int i = 0; i < zonesJSON.size(); i++) { 116 | ReadableMap zoneJSON = zonesJSON.getMap(i); 117 | 118 | final String _id = zoneJSON.getString("_id"); 119 | double range = zoneJSON.getDouble("range"); 120 | String tag = zoneJSON.getString("tag"); 121 | 122 | ProximityZone zone = new ProximityZoneBuilder() 123 | .forTag(tag) 124 | .inCustomRange(range) 125 | .onEnter(new Function1() { 126 | @Override 127 | public Unit invoke(ProximityZoneContext context) { 128 | Log.i(TAG, "onEnter, zoneId = " + _id + ", context = " + context.toString()); 129 | WritableMap map = new WritableNativeMap(); 130 | map.putString("zoneId", _id); 131 | map.putMap("context", contextToMap(context)); 132 | sendEvent("Enter", map); 133 | return null; 134 | } 135 | }) 136 | .onExit(new Function1() { 137 | @Override 138 | public Unit invoke(ProximityZoneContext context) { 139 | Log.i(TAG, "onExit, zoneId = " + _id + ", context = " + context.toString()); 140 | WritableMap map = new WritableNativeMap(); 141 | map.putString("zoneId", _id); 142 | map.putMap("context", contextToMap(context)); 143 | sendEvent("Exit", map); 144 | return null; 145 | } 146 | }) 147 | .onContextChange(new Function1, Unit>() { 148 | @Override 149 | public Unit invoke(Set contexts) { 150 | Log.i(TAG, "onContextChange, zoneId = " + _id + ", contexts = " + contexts.toString()); 151 | WritableMap map = new WritableNativeMap(); 152 | map.putString("zoneId", _id); 153 | map.putArray("contexts", contextsToArray(contexts)); 154 | sendEvent("Change", map); 155 | return null; 156 | } 157 | }) 158 | .build(); 159 | 160 | zones.add(zone); 161 | } 162 | 163 | // clean up after the previous observer, if any 164 | if (observationHandler != null) { 165 | Log.e(TAG, "startObservingZones called without stopping the previous observer; this will cause problems"); 166 | observationHandler.stop(); 167 | } 168 | 169 | observationHandler = observer.startObserving(zones); 170 | } 171 | 172 | @ReactMethod 173 | public void stopObservingZones() { 174 | Log.d(TAG, "stopObservingZones"); 175 | if (observationHandler != null) { 176 | Log.d(TAG, "observationHandler.stop()"); 177 | observationHandler.stop(); 178 | observationHandler = null; 179 | } 180 | } 181 | 182 | @Override 183 | public void onCatalystInstanceDestroy() { 184 | Log.d(TAG, "onCatalystInstanceDestroy"); 185 | if (observationHandler != null) { 186 | Log.d(TAG, "observationHandler.stop()"); 187 | observationHandler.stop(); 188 | observationHandler = null; 189 | } 190 | } 191 | 192 | // serialization helpers 193 | 194 | private WritableMap attachmentsToMap(Map attachments) { 195 | WritableMap map = new WritableNativeMap(); 196 | for (Map.Entry entry : attachments.entrySet()) { 197 | map.putString(entry.getKey(), entry.getValue()); 198 | } 199 | return map; 200 | } 201 | 202 | private WritableMap contextToMap(ProximityZoneContext context) { 203 | WritableMap map = new WritableNativeMap(); 204 | map.putString("tag", context.getTag()); 205 | map.putMap("attachments", attachmentsToMap(context.getAttachments())); 206 | map.putString("deviceIdentifier", context.getDeviceId()); 207 | return map; 208 | } 209 | 210 | private WritableArray contextsToArray(Set contexts) { 211 | WritableArray array = new WritableNativeArray(); 212 | for (ProximityZoneContext context : contexts) { 213 | array.pushMap(contextToMap(context)); 214 | } 215 | return array; 216 | } 217 | 218 | // event helper 219 | 220 | private void sendEvent(String eventName, Object params) { 221 | reactContext 222 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) 223 | .emit(eventName, params); 224 | } 225 | 226 | // notification helper 227 | 228 | private Notification createNotification(String icon, String title, String text, String channelId) { 229 | 230 | int iconRes = 0; 231 | if (icon != null) { 232 | iconRes = reactContext.getResources().getIdentifier(icon, "drawable", reactContext.getPackageName()); 233 | } 234 | if (iconRes == 0) { 235 | iconRes = reactContext.getResources().getIdentifier("ic_launcher", "mipmap", reactContext.getPackageName()); 236 | } 237 | 238 | return new NotificationCompat.Builder(reactContext, channelId) 239 | .setSmallIcon(iconRes) 240 | .setContentTitle(title) 241 | .setContentText(text) 242 | .setPriority(NotificationCompat.PRIORITY_LOW) 243 | .build(); 244 | } 245 | 246 | private void createNotificationChannel(String id, String name) { 247 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 248 | NotificationChannel channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW); 249 | NotificationManager notificationManager = reactContext.getSystemService(NotificationManager.class); 250 | notificationManager.createNotificationChannel(channel); 251 | } 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /android/src/main/java/com/estimote/react/RNEstimoteProximityPackage.java: -------------------------------------------------------------------------------- 1 | package com.estimote.react; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.NativeModule; 5 | import com.facebook.react.bridge.ReactApplicationContext; 6 | import com.facebook.react.uimanager.ViewManager; 7 | 8 | import java.util.Arrays; 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | public class RNEstimoteProximityPackage implements ReactPackage { 13 | 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | return Arrays.asList(new RNEstimoteProximityModule(reactContext)); 17 | } 18 | 19 | @Override 20 | public List createViewManagers(ReactApplicationContext reactContext) { 21 | return Collections.emptyList(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /estimote-react-native-proximity.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 = 'estimote-react-native-proximity' 7 | s.version = package['version'] 8 | s.summary = package['description'] 9 | s.license = package['license'] 10 | 11 | s.authors = package['author'] 12 | s.homepage = package['homepage'] 13 | s.platform = :ios, "10.0" 14 | 15 | s.source = { :git => "https://github.com/estimote/react-native-proximity.git", :tag => "v#{s.version}" } 16 | s.source_files = "ios/**/*.{h,m}" 17 | 18 | s.dependency 'React' 19 | s.dependency 'EstimoteProximitySDK', '~> 1.5' 20 | end 21 | -------------------------------------------------------------------------------- /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/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /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 | node_modules/react-native/Libraries/react-native/React.js 15 | 16 | ; Ignore polyfills 17 | node_modules/react-native/Libraries/polyfills/.* 18 | 19 | ; These should not be required directly 20 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 21 | node_modules/warning/.* 22 | 23 | ; Flow doesn't support platforms 24 | .*/Libraries/Utilities/HMRLoadingView.js 25 | 26 | [untyped] 27 | .*/node_modules/@react-native-community/cli/.*/.* 28 | 29 | [include] 30 | 31 | [libs] 32 | node_modules/react-native/Libraries/react-native/react-native-interface.js 33 | node_modules/react-native/flow/ 34 | 35 | [options] 36 | emoji=true 37 | 38 | esproposal.optional_chaining=enable 39 | esproposal.nullish_coalescing=enable 40 | 41 | module.file_ext=.js 42 | module.file_ext=.json 43 | module.file_ext=.ios.js 44 | 45 | module.system=haste 46 | module.system.haste.use_name_reducers=true 47 | # get basename 48 | module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1' 49 | # strip .js or .js.flow suffix 50 | module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1' 51 | # strip .ios suffix 52 | module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' 53 | module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' 54 | module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' 55 | module.system.haste.paths.blacklist=.*/__tests__/.* 56 | module.system.haste.paths.blacklist=.*/__mocks__/.* 57 | module.system.haste.paths.whitelist=/node_modules/react-native/Libraries/.* 58 | module.system.haste.paths.whitelist=/node_modules/react-native/RNTester/.* 59 | module.system.haste.paths.whitelist=/node_modules/react-native/IntegrationTests/.* 60 | module.system.haste.paths.blacklist=/node_modules/react-native/Libraries/react-native/react-native-implementation.js 61 | module.system.haste.paths.blacklist=/node_modules/react-native/Libraries/Animated/src/polyfills/.* 62 | 63 | munge_underscores=true 64 | 65 | 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' 66 | 67 | suppress_type=$FlowIssue 68 | suppress_type=$FlowFixMe 69 | suppress_type=$FlowFixMeProps 70 | suppress_type=$FlowFixMeState 71 | 72 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 73 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 74 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 75 | 76 | [lints] 77 | sketchy-null-number=warn 78 | sketchy-null-mixed=warn 79 | sketchy-number=warn 80 | untyped-type-import=warn 81 | nonstrict-import=warn 82 | deprecated-type=warn 83 | unsafe-getters-setters=warn 84 | inexact-spread=warn 85 | unnecessary-invariant=warn 86 | signature-verification-failure=warn 87 | deprecated-utility=error 88 | 89 | [strict] 90 | deprecated-type 91 | nonstrict-import 92 | sketchy-null 93 | unclear-type 94 | unsafe-getters-setters 95 | untyped-import 96 | untyped-type-import 97 | 98 | [version] 99 | ^0.98.0 100 | -------------------------------------------------------------------------------- /example/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /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://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/App.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | * @flow 7 | */ 8 | 9 | import React, {Fragment} from 'react'; 10 | import { 11 | SafeAreaView, 12 | StyleSheet, 13 | ScrollView, 14 | View, 15 | Text, 16 | StatusBar, 17 | } from 'react-native'; 18 | 19 | import { 20 | Header, 21 | LearnMoreLinks, 22 | Colors, 23 | DebugInstructions, 24 | ReloadInstructions, 25 | } from 'react-native/Libraries/NewAppScreen'; 26 | 27 | const App = () => { 28 | return ( 29 | 30 | 31 | 32 | 35 |
36 | 37 | 38 | Step One 39 | 40 | Edit App.js to change this 41 | screen and then come back to see your edits. 42 | 43 | 44 | 45 | See Your Changes 46 | 47 | 48 | 49 | 50 | 51 | Debug 52 | 53 | 54 | 55 | 56 | 57 | Learn More 58 | 59 | Read the docs to discover what to do next: 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | ); 68 | }; 69 | 70 | const styles = StyleSheet.create({ 71 | scrollView: { 72 | backgroundColor: Colors.lighter, 73 | }, 74 | body: { 75 | backgroundColor: Colors.white, 76 | }, 77 | sectionContainer: { 78 | marginTop: 32, 79 | paddingHorizontal: 24, 80 | }, 81 | sectionTitle: { 82 | fontSize: 24, 83 | fontWeight: '600', 84 | color: Colors.black, 85 | }, 86 | sectionDescription: { 87 | marginTop: 8, 88 | fontSize: 18, 89 | fontWeight: '400', 90 | color: Colors.dark, 91 | }, 92 | highlight: { 93 | fontWeight: '700', 94 | }, 95 | }); 96 | 97 | export default App; 98 | -------------------------------------------------------------------------------- /example/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /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 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.proximityexample", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.proximityexample", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /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 | * // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format 22 | * bundleCommand: "ram-bundle", 23 | * 24 | * // whether to bundle JS and assets in debug mode 25 | * bundleInDebug: false, 26 | * 27 | * // whether to bundle JS and assets in release mode 28 | * bundleInRelease: true, 29 | * 30 | * // whether to bundle JS and assets in another build variant (if configured). 31 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 32 | * // The configuration property can be in the following formats 33 | * // 'bundleIn${productFlavor}${buildType}' 34 | * // 'bundleIn${buildType}' 35 | * // bundleInFreeDebug: true, 36 | * // bundleInPaidRelease: true, 37 | * // bundleInBeta: true, 38 | * 39 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 40 | * // for example: to disable dev mode in the staging build type (if configured) 41 | * devDisabledInStaging: true, 42 | * // The configuration property can be in the following formats 43 | * // 'devDisabledIn${productFlavor}${buildType}' 44 | * // 'devDisabledIn${buildType}' 45 | * 46 | * // the root of your project, i.e. where "package.json" lives 47 | * root: "../../", 48 | * 49 | * // where to put the JS bundle asset in debug mode 50 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 51 | * 52 | * // where to put the JS bundle asset in release mode 53 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 54 | * 55 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 56 | * // require('./image.png')), in debug mode 57 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 58 | * 59 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 60 | * // require('./image.png')), in release mode 61 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 62 | * 63 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 64 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 65 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 66 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 67 | * // for example, you might want to remove it from here. 68 | * inputExcludes: ["android/**", "ios/**"], 69 | * 70 | * // override which node gets called and with what additional arguments 71 | * nodeExecutableAndArgs: ["node"], 72 | * 73 | * // supply additional arguments to the packager 74 | * extraPackagerArgs: [] 75 | * ] 76 | */ 77 | 78 | project.ext.react = [ 79 | entryFile: "index.js" 80 | ] 81 | 82 | apply from: "../../node_modules/react-native/react.gradle" 83 | 84 | /** 85 | * Set this to true to create two separate APKs instead of one: 86 | * - An APK that only works on ARM devices 87 | * - An APK that only works on x86 devices 88 | * The advantage is the size of the APK is reduced by about 4MB. 89 | * Upload all the APKs to the Play Store and people will download 90 | * the correct one based on the CPU architecture of their device. 91 | */ 92 | def enableSeparateBuildPerCPUArchitecture = false 93 | 94 | /** 95 | * Run Proguard to shrink the Java bytecode in release builds. 96 | */ 97 | def enableProguardInReleaseBuilds = false 98 | 99 | /** 100 | * Use international variant JavaScriptCore 101 | * International variant includes ICU i18n library and necessary data allowing to use 102 | * e.g. Date.toLocaleString and String.localeCompare that give correct results 103 | * when using with locales other than en-US. 104 | * Note that this variant is about 6MiB larger per architecture than default. 105 | */ 106 | def useIntlJsc = false 107 | 108 | android { 109 | compileSdkVersion rootProject.ext.compileSdkVersion 110 | 111 | compileOptions { 112 | sourceCompatibility JavaVersion.VERSION_1_8 113 | targetCompatibility JavaVersion.VERSION_1_8 114 | } 115 | 116 | defaultConfig { 117 | applicationId "com.proximityexample" 118 | minSdkVersion rootProject.ext.minSdkVersion 119 | targetSdkVersion rootProject.ext.targetSdkVersion 120 | versionCode 1 121 | versionName "1.0" 122 | } 123 | splits { 124 | abi { 125 | reset() 126 | enable enableSeparateBuildPerCPUArchitecture 127 | universalApk false // If true, also generate a universal APK 128 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 129 | } 130 | } 131 | signingConfigs { 132 | debug { 133 | storeFile file('debug.keystore') 134 | storePassword 'android' 135 | keyAlias 'androiddebugkey' 136 | keyPassword 'android' 137 | } 138 | } 139 | buildTypes { 140 | debug { 141 | signingConfig signingConfigs.debug 142 | } 143 | release { 144 | // Caution! In production, you need to generate your own keystore file. 145 | // see https://facebook.github.io/react-native/docs/signed-apk-android. 146 | signingConfig signingConfigs.debug 147 | minifyEnabled enableProguardInReleaseBuilds 148 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 149 | } 150 | } 151 | // applicationVariants are e.g. debug, release 152 | applicationVariants.all { variant -> 153 | variant.outputs.each { output -> 154 | // For each separate APK per architecture, set a unique version code as described here: 155 | // https://developer.android.com/studio/build/configure-apk-splits.html 156 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 157 | def abi = output.getFilter(OutputFile.ABI) 158 | if (abi != null) { // null for the universal-debug, universal-release variants 159 | output.versionCodeOverride = 160 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 161 | } 162 | } 163 | } 164 | } 165 | 166 | dependencies { 167 | implementation fileTree(dir: "libs", include: ["*.jar"]) 168 | implementation "com.facebook.react:react-native:+" // From node_modules 169 | 170 | // JSC from node_modules 171 | if (useIntlJsc) { 172 | implementation 'org.webkit:android-jsc-intl:+' 173 | } else { 174 | implementation 'org.webkit:android-jsc:+' 175 | } 176 | } 177 | 178 | // Run this once to be able to run the application with BUCK 179 | // puts all compile dependencies into folder libs for BUCK to use 180 | task copyDownloadableDepsToLibs(type: Copy) { 181 | from configurations.compile 182 | into 'libs' 183 | } 184 | 185 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 186 | -------------------------------------------------------------------------------- /example/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/proximityexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.proximityexample; 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 "ProximityExample"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/proximityexample/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.proximityexample; 2 | 3 | import android.app.Application; 4 | 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.soloader.SoLoader; 10 | 11 | import java.util.List; 12 | 13 | public class MainApplication extends Application implements ReactApplication { 14 | 15 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 16 | @Override 17 | public boolean getUseDeveloperSupport() { 18 | return BuildConfig.DEBUG; 19 | } 20 | 21 | @Override 22 | protected List getPackages() { 23 | @SuppressWarnings("UnnecessaryLocalVariable") 24 | List packages = new PackageList(this).getPackages(); 25 | // Packages that cannot be autolinked yet can be added manually here, for example: 26 | // packages.add(new MyReactNativePackage()); 27 | return packages; 28 | } 29 | 30 | @Override 31 | protected String getJSMainModuleName() { 32 | return "index"; 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/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ProximityExample 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /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 | ext { 5 | buildToolsVersion = "28.0.3" 6 | minSdkVersion = 18 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | supportLibVersion = "28.0.0" 10 | } 11 | repositories { 12 | google() 13 | jcenter() 14 | } 15 | dependencies { 16 | classpath("com.android.tools.build:gradle:3.4.1") 17 | 18 | // NOTE: Do not place your application dependencies here; they belong 19 | // in the individual module build.gradle files 20 | } 21 | } 22 | 23 | allprojects { 24 | repositories { 25 | mavenLocal() 26 | maven { 27 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 28 | url("$rootDir/../node_modules/react-native/android") 29 | } 30 | maven { 31 | // Android JSC is installed from npm 32 | url("$rootDir/../node_modules/jsc-android/dist") 33 | } 34 | 35 | google() 36 | jcenter() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /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.useAndroidX=true 21 | android.enableJetifier=true 22 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Estimote/react-native-proximity/13887046f767cf7e304b5dd7884c38ecc15ff8f1/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin, switch paths to Windows format before running java 129 | if $cygwin ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem http://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ProximityExample' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ProximityExample", 3 | "displayName": "ProximityExample" 4 | } -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | 11 | 12 | 13 | import {startProximityObserver, stopProximityObserver} from './proximityObserver'; 14 | // if you want the Proximity Observer constantly running, even if the user swipes the app away, start it here: 15 | startProximityObserver(); 16 | // see also: https://github.com/Estimote/react-native-proximity#already-observing 17 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '10.0' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | target 'ProximityExample' do 5 | # Pods for ProximityExample 6 | pod 'React', :path => '../node_modules/react-native/' 7 | pod 'React-Core', :path => '../node_modules/react-native/React' 8 | pod 'React-DevSupport', :path => '../node_modules/react-native/React' 9 | pod 'React-fishhook', :path => '../node_modules/react-native/Libraries/fishhook' 10 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' 11 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' 12 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' 13 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' 14 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' 15 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' 16 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' 17 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' 18 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' 19 | pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket' 20 | 21 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' 22 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' 23 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' 24 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' 25 | pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga' 26 | 27 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' 28 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' 29 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' 30 | 31 | target 'ProximityExampleTests' do 32 | inherit! :search_paths 33 | # Pods for testing 34 | end 35 | 36 | use_native_modules! 37 | end 38 | 39 | target 'ProximityExample-tvOS' do 40 | # Pods for ProximityExample-tvOS 41 | 42 | target 'ProximityExample-tvOSTests' do 43 | inherit! :search_paths 44 | # Pods for testing 45 | end 46 | 47 | end 48 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - boost-for-react-native (1.63.0) 3 | - DoubleConversion (1.1.6) 4 | - estimote-react-native-proximity (0.6.0): 5 | - EstimoteProximitySDK (~> 1.0) 6 | - React 7 | - EstimoteBluetoothScanning (1.0.6) 8 | - EstimoteProximitySDK (1.5.0): 9 | - EstimoteBluetoothScanning (~> 1.0.6) 10 | - Folly (2018.10.22.00): 11 | - boost-for-react-native 12 | - DoubleConversion 13 | - Folly/Default (= 2018.10.22.00) 14 | - glog 15 | - Folly/Default (2018.10.22.00): 16 | - boost-for-react-native 17 | - DoubleConversion 18 | - glog 19 | - glog (0.3.5) 20 | - React (0.60.0): 21 | - React-Core (= 0.60.0) 22 | - React-DevSupport (= 0.60.0) 23 | - React-RCTActionSheet (= 0.60.0) 24 | - React-RCTAnimation (= 0.60.0) 25 | - React-RCTBlob (= 0.60.0) 26 | - React-RCTImage (= 0.60.0) 27 | - React-RCTLinking (= 0.60.0) 28 | - React-RCTNetwork (= 0.60.0) 29 | - React-RCTSettings (= 0.60.0) 30 | - React-RCTText (= 0.60.0) 31 | - React-RCTVibration (= 0.60.0) 32 | - React-RCTWebSocket (= 0.60.0) 33 | - React-Core (0.60.0): 34 | - Folly (= 2018.10.22.00) 35 | - React-cxxreact (= 0.60.0) 36 | - React-jsiexecutor (= 0.60.0) 37 | - yoga (= 0.60.0.React) 38 | - React-cxxreact (0.60.0): 39 | - boost-for-react-native (= 1.63.0) 40 | - DoubleConversion 41 | - Folly (= 2018.10.22.00) 42 | - glog 43 | - React-jsinspector (= 0.60.0) 44 | - React-DevSupport (0.60.0): 45 | - React-Core (= 0.60.0) 46 | - React-RCTWebSocket (= 0.60.0) 47 | - React-fishhook (0.60.0) 48 | - React-jsi (0.60.0): 49 | - boost-for-react-native (= 1.63.0) 50 | - DoubleConversion 51 | - Folly (= 2018.10.22.00) 52 | - glog 53 | - React-jsi/Default (= 0.60.0) 54 | - React-jsi/Default (0.60.0): 55 | - boost-for-react-native (= 1.63.0) 56 | - DoubleConversion 57 | - Folly (= 2018.10.22.00) 58 | - glog 59 | - React-jsiexecutor (0.60.0): 60 | - DoubleConversion 61 | - Folly (= 2018.10.22.00) 62 | - glog 63 | - React-cxxreact (= 0.60.0) 64 | - React-jsi (= 0.60.0) 65 | - React-jsinspector (0.60.0) 66 | - React-RCTActionSheet (0.60.0): 67 | - React-Core (= 0.60.0) 68 | - React-RCTAnimation (0.60.0): 69 | - React-Core (= 0.60.0) 70 | - React-RCTBlob (0.60.0): 71 | - React-Core (= 0.60.0) 72 | - React-RCTNetwork (= 0.60.0) 73 | - React-RCTWebSocket (= 0.60.0) 74 | - React-RCTImage (0.60.0): 75 | - React-Core (= 0.60.0) 76 | - React-RCTNetwork (= 0.60.0) 77 | - React-RCTLinking (0.60.0): 78 | - React-Core (= 0.60.0) 79 | - React-RCTNetwork (0.60.0): 80 | - React-Core (= 0.60.0) 81 | - React-RCTSettings (0.60.0): 82 | - React-Core (= 0.60.0) 83 | - React-RCTText (0.60.0): 84 | - React-Core (= 0.60.0) 85 | - React-RCTVibration (0.60.0): 86 | - React-Core (= 0.60.0) 87 | - React-RCTWebSocket (0.60.0): 88 | - React-Core (= 0.60.0) 89 | - React-fishhook (= 0.60.0) 90 | - yoga (0.60.0.React) 91 | 92 | DEPENDENCIES: 93 | - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) 94 | - "estimote-react-native-proximity (from `../node_modules/@estimote/react-native-proximity`)" 95 | - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`) 96 | - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) 97 | - React (from `../node_modules/react-native/`) 98 | - React-Core (from `../node_modules/react-native/React`) 99 | - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) 100 | - React-DevSupport (from `../node_modules/react-native/React`) 101 | - React-fishhook (from `../node_modules/react-native/Libraries/fishhook`) 102 | - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) 103 | - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) 104 | - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) 105 | - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) 106 | - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) 107 | - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) 108 | - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) 109 | - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) 110 | - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) 111 | - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) 112 | - React-RCTText (from `../node_modules/react-native/Libraries/Text`) 113 | - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) 114 | - React-RCTWebSocket (from `../node_modules/react-native/Libraries/WebSocket`) 115 | - yoga (from `../node_modules/react-native/ReactCommon/yoga`) 116 | 117 | SPEC REPOS: 118 | https://github.com/cocoapods/specs.git: 119 | - boost-for-react-native 120 | - EstimoteBluetoothScanning 121 | - EstimoteProximitySDK 122 | 123 | EXTERNAL SOURCES: 124 | DoubleConversion: 125 | :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" 126 | estimote-react-native-proximity: 127 | :path: "../node_modules/@estimote/react-native-proximity" 128 | Folly: 129 | :podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec" 130 | glog: 131 | :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" 132 | React: 133 | :path: "../node_modules/react-native/" 134 | React-Core: 135 | :path: "../node_modules/react-native/React" 136 | React-cxxreact: 137 | :path: "../node_modules/react-native/ReactCommon/cxxreact" 138 | React-DevSupport: 139 | :path: "../node_modules/react-native/React" 140 | React-fishhook: 141 | :path: "../node_modules/react-native/Libraries/fishhook" 142 | React-jsi: 143 | :path: "../node_modules/react-native/ReactCommon/jsi" 144 | React-jsiexecutor: 145 | :path: "../node_modules/react-native/ReactCommon/jsiexecutor" 146 | React-jsinspector: 147 | :path: "../node_modules/react-native/ReactCommon/jsinspector" 148 | React-RCTActionSheet: 149 | :path: "../node_modules/react-native/Libraries/ActionSheetIOS" 150 | React-RCTAnimation: 151 | :path: "../node_modules/react-native/Libraries/NativeAnimation" 152 | React-RCTBlob: 153 | :path: "../node_modules/react-native/Libraries/Blob" 154 | React-RCTImage: 155 | :path: "../node_modules/react-native/Libraries/Image" 156 | React-RCTLinking: 157 | :path: "../node_modules/react-native/Libraries/LinkingIOS" 158 | React-RCTNetwork: 159 | :path: "../node_modules/react-native/Libraries/Network" 160 | React-RCTSettings: 161 | :path: "../node_modules/react-native/Libraries/Settings" 162 | React-RCTText: 163 | :path: "../node_modules/react-native/Libraries/Text" 164 | React-RCTVibration: 165 | :path: "../node_modules/react-native/Libraries/Vibration" 166 | React-RCTWebSocket: 167 | :path: "../node_modules/react-native/Libraries/WebSocket" 168 | yoga: 169 | :path: "../node_modules/react-native/ReactCommon/yoga" 170 | 171 | SPEC CHECKSUMS: 172 | boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c 173 | DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2 174 | estimote-react-native-proximity: d567ac92120a97afcb09d68a10bfdf438c0456d7 175 | EstimoteBluetoothScanning: a8bfa6dfb36d0e7a2a811adbcfb3b87b3e343482 176 | EstimoteProximitySDK: b8b4d96ed872431e7941863d009bb99d28ceaf99 177 | Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51 178 | glog: 1f3da668190260b06b429bb211bfbee5cd790c28 179 | React: 4b3c068e793e96672dcd186a2b572fac43e4b031 180 | React-Core: 3dc86b22920597f813c62a96db3165950b64826b 181 | React-cxxreact: 0dacb291e59b81e7c3f22a2118bee853ba8a60d2 182 | React-DevSupport: 4eb4135386acd10c2586cc9c759bf96b4dac035e 183 | React-fishhook: 86ca737527bb9d860efbb943c11c729a5b69aa3d 184 | React-jsi: 8e128c4d0d8febc2977ef617d1c09bb54326069c 185 | React-jsiexecutor: 7a3554f703a58963ec80b860144ea0f0e9b910e1 186 | React-jsinspector: d4ed52225912efe0019bb7f1a225aec20f23049a 187 | React-RCTActionSheet: b27ff3cf3a68f917c46d2b94abf938b625b96570 188 | React-RCTAnimation: 9e4708e5bd65fca8285ce7c0aa076f3f4fa5c2f8 189 | React-RCTBlob: 6eafcc3a24f33785692a7be24918ade607bc8719 190 | React-RCTImage: 46b965d7225b428ea11580ead08a4318aef1d6be 191 | React-RCTLinking: d65b9f56cf0b8e171575a86764df7bb019ac28d6 192 | React-RCTNetwork: 783ee2f430740e58f724e46adc79fe7feff64202 193 | React-RCTSettings: aa28315aadfbfaf94206d865673ae509f1e97c07 194 | React-RCTText: 685fca2e13b024271048e7e247ef24476f28a41e 195 | React-RCTVibration: 4ee1cf208ab17a50fafb1c16ffe28fe594a64e4f 196 | React-RCTWebSocket: fca087d583724aa0e5fef7d911f0f2a28d0f2736 197 | yoga: 616fde658be980aa60a2158835170f3f9c2d04b4 198 | 199 | PODFILE CHECKSUM: 3e2797c449100b78e90303a2d7ef53abd64088d7 200 | 201 | COCOAPODS: 1.7.3 202 | -------------------------------------------------------------------------------- /example/ios/ProximityExample-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /example/ios/ProximityExample-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/ios/ProximityExample.xcodeproj/xcshareddata/xcschemes/ProximityExample-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /example/ios/ProximityExample.xcodeproj/xcshareddata/xcschemes/ProximityExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /example/ios/ProximityExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/ProximityExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/ProximityExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (nonatomic, strong) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /example/ios/ProximityExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import "AppDelegate.h" 9 | 10 | #import 11 | #import 12 | #import 13 | 14 | @implementation AppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 19 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 20 | moduleName:@"ProximityExample" 21 | initialProperties:nil]; 22 | 23 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 24 | 25 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 26 | UIViewController *rootViewController = [UIViewController new]; 27 | rootViewController.view = rootView; 28 | self.window.rootViewController = rootViewController; 29 | [self.window makeKeyAndVisible]; 30 | return YES; 31 | } 32 | 33 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 34 | { 35 | #if DEBUG 36 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 37 | #else 38 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 39 | #endif 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /example/ios/ProximityExample/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/ProximityExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /example/ios/ProximityExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/ProximityExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ProximityExample 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 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationAlwaysAndWhenInUseUsageDescription 41 | Change me in the Info.plist file 42 | NSLocationWhenInUseUsageDescription 43 | Change me in the Info.plist file 44 | UIBackgroundModes 45 | 46 | bluetooth-central 47 | 48 | UILaunchStoryboardName 49 | LaunchScreen 50 | UIRequiredDeviceCapabilities 51 | 52 | armv7 53 | 54 | UISupportedInterfaceOrientations 55 | 56 | UIInterfaceOrientationPortrait 57 | UIInterfaceOrientationLandscapeLeft 58 | UIInterfaceOrientationLandscapeRight 59 | 60 | UIViewControllerBasedStatusBarAppearance 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /example/ios/ProximityExample/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /example/ios/ProximityExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/ios/ProximityExampleTests/ProximityExampleTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | #import 12 | #import 13 | 14 | #define TIMEOUT_SECONDS 600 15 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 16 | 17 | @interface ProximityExampleTests : XCTestCase 18 | 19 | @end 20 | 21 | @implementation ProximityExampleTests 22 | 23 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 24 | { 25 | if (test(view)) { 26 | return YES; 27 | } 28 | for (UIView *subview in [view subviews]) { 29 | if ([self findSubviewInView:subview matching:test]) { 30 | return YES; 31 | } 32 | } 33 | return NO; 34 | } 35 | 36 | - (void)testRendersWelcomeScreen 37 | { 38 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 39 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 40 | BOOL foundElement = NO; 41 | 42 | __block NSString *redboxError = nil; 43 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 44 | if (level >= RCTLogLevelError) { 45 | redboxError = message; 46 | } 47 | }); 48 | 49 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 50 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 51 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 52 | 53 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 54 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 55 | return YES; 56 | } 57 | return NO; 58 | }]; 59 | } 60 | 61 | RCTSetLogFunction(RCTDefaultLogFunction); 62 | 63 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 64 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 65 | } 66 | 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: false, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ProximityExample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-native start", 7 | "test": "jest", 8 | "lint": "eslint ." 9 | }, 10 | "dependencies": { 11 | "@estimote/react-native-proximity": "0.6.0", 12 | "react": "16.8.6", 13 | "react-native": "0.60.0" 14 | }, 15 | "devDependencies": { 16 | "@babel/core": "7.5.4", 17 | "@babel/runtime": "7.5.4", 18 | "@react-native-community/eslint-config": "0.0.3", 19 | "babel-jest": "24.8.0", 20 | "eslint": "6.0.1", 21 | "jest": "24.8.0", 22 | "metro-react-native-babel-preset": "0.54.1", 23 | "react-test-renderer": "16.8.6" 24 | }, 25 | "jest": { 26 | "preset": "react-native" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/proximityObserver.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | "use strict"; 3 | 4 | import * as RNEP from "@estimote/react-native-proximity"; 5 | 6 | const startProximityObserver = () => { 7 | 8 | // generate Estimote Cloud credentials for your app at: 9 | // https://cloud.estimote.com/#/apps/add/your-own-app 10 | const ESTIMOTE_APP_ID = "<#APP_ID#>"; 11 | const ESTIMOTE_APP_TOKEN = "<#APP_TOKEN#>"; 12 | 13 | // will trigger when the user is within ~ 5 m of any beacon with tag "lobby" 14 | // you can add tags to your beacons on https://cloud.estimote.com, in Beacon Settings 15 | const zone1 = new RNEP.ProximityZone(5, "lobby"); 16 | zone1.onEnterAction = context => { 17 | // context properties are: 18 | // - attachments: all the key-value attachments assigned in Estimote Cloud to the beacon that triggered the action 19 | // - tag: the tag used when defining the zone, repeated here for convenience 20 | // - deviceIdentifier: Estimote-specific device identifier of the beacon that triggered the action 21 | console.log("zone1 onEnter", context); 22 | }; 23 | zone1.onExitAction = context => { 24 | console.log("zone1 onExit", context); 25 | }; 26 | zone1.onChangeAction = contexts => { 27 | // onChange event gives you granular data about which exact beacons are in range 28 | // 29 | // imagine there are 2 beacons tagged "lobby", to help cover the entire lobby area; here's an example sequence of events: 30 | // 31 | // 1. when you enter the range of the 1st one, you'll get: 32 | // lobby onEnter 33 | // lobby onChange with array [beacon1's context] 34 | // 35 | // 2. when you enter the range of the 2nd one, and are still in range of the 1st one: 36 | // lobby onChange with array [beacon1's context, beacon2's context] 37 | // 38 | // 3. when you exit the range of the 1st one, but are still in range of the 2nd one: 39 | // lobby onChange with array [beacon2's context] 40 | // 41 | // 4. when you finally exit the range of the 2nd one: 42 | // lobby onChange with empty array [] 43 | // lobby onExit 44 | console.log("zone1 onChange", contexts); 45 | }; 46 | 47 | const zone2 = new RNEP.ProximityZone(5, "conf-room"); 48 | zone2.onEnterAction = context => { 49 | console.log("zone2 onEnter", context); 50 | }; 51 | zone2.onExitAction = context => { 52 | console.log("zone2 onExit", context); 53 | }; 54 | zone2.onChangeAction = contexts => { 55 | console.log("zone2 onChange", contexts); 56 | }; 57 | 58 | // detecting proximity to Bluetooth beacons gives you information about the user's location, and so 59 | // on both iOS and Android it's required to ask the user for permission to do that 60 | // 61 | // - on iOS, the user can choose between "never", "only when using the app" and "always" (background) 62 | // - however, background support also requires that you enable the "Uses Bluetooth LE accessories" 63 | // Background Mode for your app 64 | // - you can do that in Xcode project settings, on the Capabilities tab 65 | // - you might also need to explain/defend your app's background usage during the App Store review 66 | // 67 | // - on Android, it'll be a simple "yes/no" popup, which is equivalent to "never" and "always" 68 | // - however, to have it work in the background, you're also required to show a notification, so 69 | // that the user knows that the app keeps running/detecting beacons even if they close it 70 | // - see the `config` section below for how to enable/configure such notification 71 | // 72 | // see also: "Location permission" and "Background support" sections in the README 73 | RNEP.locationPermission.request().then( 74 | permission => { 75 | // `permission` will be one of RNEP.locationPermission.DENIED, .ALWAYS, or .WHEN_IN_USE 76 | console.log(`location permission: ${permission}`); 77 | 78 | if (permission !== RNEP.locationPermission.DENIED) { 79 | const credentials = new RNEP.CloudCredentials( 80 | ESTIMOTE_APP_ID, 81 | ESTIMOTE_APP_TOKEN 82 | ); 83 | 84 | const config = { 85 | // modern versions of Android require a notification informing the user that the app is active in the background 86 | // if you don't need proximity observation to work in the background, you can omit the entire `notification` config 87 | // 88 | // see also: "Background support" section in the README 89 | notification: { 90 | title: "Exploration mode is on", 91 | text: "We'll notify you when you're next to something interesting.", 92 | //icon: 'my_drawable', // if omitted, will default to the app icon (i.e., mipmap/ic_launcher) 93 | 94 | // in apps targeting Android API 26, notifications must specify a channel 95 | // https://developer.android.com/guide/topics/ui/notifiers/notifications#ManageChannels 96 | channel: { 97 | id: "exploration-mode", 98 | name: "Exploration Mode" 99 | } 100 | } 101 | }; 102 | 103 | RNEP.proximityObserver.initialize(credentials, config); 104 | RNEP.proximityObserver.startObservingZones([zone1, zone2]); 105 | } 106 | }, 107 | error => { 108 | console.error("Error when trying to obtain location permission", error); 109 | } 110 | ); 111 | 112 | }; 113 | 114 | const stopProximityObserver = () => { RNEP.proximityObserver.stopObservingZones(); }; 115 | 116 | export {startProximityObserver, stopProximityObserver}; 117 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | "use strict"; 3 | 4 | import { 5 | NativeModules, 6 | NativeEventEmitter, 7 | Platform, 8 | PermissionsAndroid 9 | } from "react-native"; 10 | 11 | const { RNEstimoteProximity } = NativeModules; 12 | const RNEstimoteProximityEmitter = new NativeEventEmitter(RNEstimoteProximity); 13 | 14 | export class ProximityContext { 15 | tag: string; 16 | attachments: { [string]: string }; 17 | deviceIdentifier: string; 18 | 19 | static fromJSON(json: any): ProximityContext { 20 | const context = new ProximityContext(); 21 | context.tag = json["tag"]; 22 | context.attachments = json["attachments"]; 23 | context.deviceIdentifier = json["deviceIdentifier"]; 24 | return context; 25 | } 26 | } 27 | 28 | export class ProximityZone { 29 | range: number; 30 | tag: string; 31 | 32 | onEnterAction: (context: ProximityContext) => void; 33 | onExitAction: (context: ProximityContext) => void; 34 | onChangeAction: (contexts: Array) => void; 35 | 36 | _id: string; 37 | 38 | constructor(range: number, tag: string) { 39 | this.range = range; 40 | this.tag = tag; 41 | 42 | this._id = Math.random() 43 | .toString(36) 44 | .substring(2); 45 | } 46 | } 47 | 48 | export class CloudCredentials { 49 | appId: string; 50 | appToken: string; 51 | 52 | constructor(appId: string, appToken: string) { 53 | this.appId = appId; 54 | this.appToken = appToken; 55 | } 56 | } 57 | 58 | type ProximityObserverConfig = { 59 | notification?: { 60 | title?: string, 61 | text?: string, 62 | icon?: string 63 | } 64 | }; 65 | 66 | // singleton object 67 | export const proximityObserver = { 68 | 69 | isObserving: false, 70 | 71 | initialize(credentials: CloudCredentials, config: ProximityObserverConfig) { 72 | RNEstimoteProximity.initialize( 73 | Object.assign({}, config, { 74 | appId: credentials.appId, 75 | appToken: credentials.appToken 76 | }) 77 | ); 78 | }, 79 | 80 | startObservingZones(zones: Array) { 81 | if (this.isObserving) { 82 | console.warn("'startObservingZones' was called while already observing. I'll stop the previous observation for you, but make sure that you're properly managing the lifecycle of the observer. See also: https://github.com/Estimote/react-native-proximity#already-observing"); 83 | this.stopObservingZones(); 84 | } 85 | this.isObserving = true; 86 | 87 | const zonesById: Map = zones.reduce((map, z) => { 88 | return map.set(z._id, z); 89 | }, new Map()); 90 | 91 | this.onEnterSubscription = RNEstimoteProximityEmitter.addListener( 92 | `Enter`, 93 | event => { 94 | const zone = zonesById.get(event.zoneId); 95 | if (zone === undefined) { 96 | return; 97 | } 98 | const onEnterAction = zone.onEnterAction; 99 | if (typeof onEnterAction === "function") { 100 | const context = ProximityContext.fromJSON(event.context); 101 | onEnterAction(context); 102 | } 103 | } 104 | ); 105 | 106 | this.onExitSubscription = RNEstimoteProximityEmitter.addListener( 107 | `Exit`, 108 | event => { 109 | const zone = zonesById.get(event.zoneId); 110 | if (zone === undefined) { 111 | return; 112 | } 113 | const onExitAction = zone.onExitAction; 114 | if (typeof onExitAction === "function") { 115 | const context = ProximityContext.fromJSON(event.context); 116 | onExitAction(context); 117 | } 118 | } 119 | ); 120 | 121 | this.onChangeSubscription = RNEstimoteProximityEmitter.addListener( 122 | `Change`, 123 | event => { 124 | const zone = zonesById.get(event.zoneId); 125 | if (zone === undefined) { 126 | console.error('Got a proximity event for an unknown zone. This is most likely a bug, please report to https://github.com/Estimote/react-native-proximity/issues'); 127 | return; 128 | } 129 | const onChangeAction = zone.onChangeAction; 130 | if (typeof onChangeAction === "function") { 131 | const contexts = event.contexts.map(context => 132 | ProximityContext.fromJSON(context) 133 | ); 134 | onChangeAction(contexts); 135 | } 136 | } 137 | ); 138 | 139 | const zonesJSON = zones.map(z => ({ 140 | _id: z._id, 141 | range: z.range, 142 | tag: z.tag 143 | })); 144 | 145 | RNEstimoteProximity.startObservingZones(zonesJSON); 146 | this.isObserving = true; 147 | }, 148 | 149 | stopObservingZones() { 150 | RNEstimoteProximity.stopObservingZones(); 151 | this.isObserving = false; 152 | 153 | this.onEnterSubscription.remove(); 154 | this.onExitSubscription.remove(); 155 | this.onChangeSubscription.remove(); 156 | } 157 | }; 158 | 159 | type PermissionStatus = "always" | "when_in_use" | "denied"; 160 | 161 | export const locationPermission = { 162 | ALWAYS: "always", 163 | WHEN_IN_USE: "when_in_use", 164 | DENIED: "denied", 165 | 166 | request: async (): Promise => { 167 | if (Platform.OS === "ios") { 168 | const result = await RNEstimoteProximity.requestLocationPermission(); 169 | return result; 170 | } else if (Platform.OS === "android") { 171 | const result = await PermissionsAndroid.request( 172 | PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION 173 | ); 174 | return result === "granted" ? "always" : "denied"; 175 | } 176 | throw "Unsupported platform"; 177 | } 178 | }; 179 | -------------------------------------------------------------------------------- /ios/EPXHeaders/EPXCloudCredentials.h: -------------------------------------------------------------------------------- 1 | // 2 | // ____ _ _ _ ____ ____ _ __ 3 | // | _ \ _ __ _____ _(_)_ __ ___ (_) |_ _ _ / ___|| _ \| |/ / 4 | // | |_) | '__/ _ \ \/ / | '_ ` _ \| | __| | | | \___ \| | | | ' / 5 | // | __/| | | (_) > <| | | | | | | | |_| |_| | ___) | |_| | . \ 6 | // |_| |_| \___/_/\_\_|_| |_| |_|_|\__|\__, | |____/|____/|_|\_\ 7 | // |___/ 8 | // 9 | // Copyright © 2017 Estimote. All rights reserved. 10 | // 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | /** 17 | Estimote Cloud credentials encapsulated in a value object. To acquire App ID & App Token go to 18 | https://cloud.estimote.com/#/apps. 19 | */ 20 | NS_SWIFT_NAME(CloudCredentials) 21 | @interface EPXCloudCredentials : NSObject 22 | 23 | /** 24 | App ID generated in Estimote Cloud. 25 | */ 26 | @property(nonatomic, strong, readonly) NSString *appID; 27 | 28 | /** 29 | App Token generated in Estimote Cloud. 30 | */ 31 | @property(nonatomic, strong, readonly) NSString *appToken; 32 | 33 | /** 34 | Init is disabled for this class. 35 | */ 36 | - (instancetype)init NS_UNAVAILABLE; 37 | 38 | /** 39 | New is disabled for this class. 40 | */ 41 | + (instancetype) new NS_UNAVAILABLE; 42 | 43 | /** 44 | Designated initializer. 45 | 46 | @param appID App ID generated in Estimote Cloud. 47 | @param appToken App Token generated in Estimote Cloud. 48 | */ 49 | - (instancetype)initWithAppID:(NSString *)appID appToken:(NSString *)appToken NS_DESIGNATED_INITIALIZER; 50 | 51 | @end 52 | 53 | NS_ASSUME_NONNULL_END 54 | -------------------------------------------------------------------------------- /ios/EPXHeaders/EPXProximityObserver.h: -------------------------------------------------------------------------------- 1 | // 2 | // ____ _ _ _ ____ ____ _ __ 3 | // | _ \ _ __ _____ _(_)_ __ ___ (_) |_ _ _ / ___|| _ \| |/ / 4 | // | |_) | '__/ _ \ \/ / | '_ ` _ \| | __| | | | \___ \| | | | ' / 5 | // | __/| | | (_) > <| | | | | | | | |_| |_| | ___) | |_| | . \ 6 | // |_| |_| \___/_/\_\_|_| |_| |_|_|\__|\__, | |____/|____/|_|\_\ 7 | // |___/ 8 | // 9 | // Copyright © 2017 Estimote. All rights reserved. 10 | // 11 | 12 | #import 13 | 14 | @class EPXCloudCredentials; 15 | @class EPXProximityZone; 16 | @class EPXProximityObserverConfiguration; 17 | 18 | NS_ASSUME_NONNULL_BEGIN 19 | 20 | FOUNDATION_EXPORT NSString *const EPXProximityObserverErrorDomain; 21 | 22 | /** 23 | Possible errors invoked with Proximity Observer's error block. 24 | */ 25 | typedef NS_ENUM(NSUInteger, EPXProximityObserverError) { 26 | /* Unknown error probably due to a bug. If you're getting errors with this code please report it on 27 | * https://forums.estimote.com, using contact@estimote.com or filing an issue on Github. */ 28 | EPXProximityObserverErrorUnknown = 0, 29 | 30 | /* Fetching tags from Cloud failed. */ 31 | EPXProximityObserverErrorFetchingTagsFailed, 32 | 33 | /* Fetching attachments from Cloud failed. */ 34 | EPXProximityObserverErrorFetchingAttachmentsFailed, 35 | 36 | /* Bluetooth is unsupported on this iOS device. */ 37 | EPXProximityObserverErrorBluetoothUnsupported, 38 | 39 | /* Bluetooth is turned off. */ 40 | EPXProximityObserverErrorBluetoothOff, 41 | 42 | /* Couldn't use motion detection. */ 43 | EPXProximityObserverErrorMotionDetectionFailed, 44 | 45 | /* Core Location Services interferred with monitoring */ 46 | EPXProximityObserverErrorMonitoringNotPermitted 47 | }; 48 | 49 | /** 50 | Observes and reports proximity of Estimote devices. 51 | Uses Estimote Monitoring under the hood. Encapsulates it under tag-based beacon identification and callback blocks. 52 | */ 53 | NS_SWIFT_NAME(ProximityObserver) 54 | @interface EPXProximityObserver : NSObject 55 | 56 | /** 57 | Init is disabled for this class. 58 | */ 59 | - (instancetype)init NS_UNAVAILABLE; 60 | 61 | /** 62 | New is disabled for this class. 63 | */ 64 | + (instancetype) new NS_UNAVAILABLE; 65 | 66 | /** 67 | Convenience initializer. Calls designated initializer with default configuration. 68 | @param credentials Cloud Credentials object used to authorize requests sent to Estimote Cloud. 69 | @param errorBlock Block invoked whenever error occurs. The parameter is an NSError object, with 70 | domain equal to EPXProximityObserverErrorDomain and code from EPXProximityObserverError enum. 71 | */ 72 | - (instancetype)initWithCredentials:(EPXCloudCredentials *)credentials onError:(void (^)(NSError *error))errorBlock; 73 | 74 | /** 75 | Designated initializer. 76 | @param credentials Cloud Credentials object used to authorize requests sent to Estimote Cloud. 77 | @param configuration Proximity observer configuration that can be used for Proximity Observer's behaviour customization. 78 | @param errorBlock Block invoked whenever error occurs. The parameter is an NSError object, with 79 | domain equal to EPXProximityObserverErrorDomain and code from EPXProximityObserverError enum. 80 | */ 81 | - (instancetype)initWithCredentials:(EPXCloudCredentials *)credentials 82 | configuration:(EPXProximityObserverConfiguration *)configuration 83 | onError:(void (^)(NSError *error))errorBlock; 84 | 85 | /** 86 | Start observing and calling callbacks on provided proximity zones: 87 | - request device details for all user's devices from Estimote Cloud, 88 | - start Estimote Monitoring at registered ranges, 89 | - call registered enter/exit/change blocks when proximity event occurs. 90 | 91 | Subsequent calls of this method cause overwriting previously observed zones. 92 | 93 | Note: at the moment, Proximity SDK supports monitoring only 100 devices per zone. If more devices have their attachments 94 | matching the key, value defined in the zone, the first 100 are monitored. 95 | 96 | @param zones Zones to be observed. 97 | */ 98 | - (void)startObservingZones:(NSArray *)zones; 99 | 100 | /** 101 | Stop observing and calling callbacks for all zones that were provided with -startObservingZones:, 102 | release memory resources allocated for monitoring the zones. 103 | 104 | Subsequent calls of this method (without re-starting observing zones) have the same effect as calling it just once. 105 | */ 106 | - (void)stopObservingZones; 107 | 108 | @end 109 | 110 | NS_ASSUME_NONNULL_END 111 | -------------------------------------------------------------------------------- /ios/EPXHeaders/EPXProximityObserverConfiguration.h: -------------------------------------------------------------------------------- 1 | // 2 | // ____ _ _ _ ____ ____ _ __ 3 | // | _ \ _ __ _____ _(_)_ __ ___ (_) |_ _ _ / ___|| _ \| |/ / 4 | // | |_) | '__/ _ \ \/ / | '_ ` _ \| | __| | | | \___ \| | | | ' / 5 | // | __/| | | (_) > <| | | | | | | | |_| |_| | ___) | |_| | . \ 6 | // |_| |_| \___/_/\_\_|_| |_| |_|_|\__|\__, | |____/|____/|_|\_\ 7 | // |___/ 8 | // 9 | // Copyright © 2017 Estimote. All rights reserved. 10 | // 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | /** 17 | Defines logger level. 18 | */ 19 | typedef NS_ENUM(NSUInteger, EPXLogLevel) { 20 | /* Mute all logs. */ 21 | EPXLogLevelNone = 0, 22 | 23 | /* Log errors only. */ 24 | EPXLogLevelError = 1, 25 | 26 | /* Log errors and warnings. */ 27 | EPXLogLevelWarning = 2, 28 | 29 | /* Log errors, warnings and regular messages. */ 30 | EPXLogLevelInfo = 3 31 | }; 32 | 33 | /** 34 | Used to customize Proximity Observer behaviour. 35 | */ 36 | NS_SWIFT_NAME(ProximityObserverConfiguration) 37 | @interface EPXProximityObserverConfiguration : NSObject 38 | 39 | /** 40 | Creates a default Proximity Observer configuration object. 41 | */ 42 | @property(nonatomic, strong, readonly, class) EPXProximityObserverConfiguration *defaultConfiguration; 43 | 44 | /** 45 | Logger level. Defines which logs generated by Estimote Proximity SDK are printed to the Xcode's console. 46 | */ 47 | @property(nonatomic, assign, readwrite) EPXLogLevel logLevel; 48 | 49 | @end 50 | 51 | NS_ASSUME_NONNULL_END 52 | -------------------------------------------------------------------------------- /ios/EPXHeaders/EPXProximityRange.h: -------------------------------------------------------------------------------- 1 | // 2 | // ____ _ _ _ ____ ____ _ __ 3 | // | _ \ _ __ _____ _(_)_ __ ___ (_) |_ _ _ / ___|| _ \| |/ / 4 | // | |_) | '__/ _ \ \/ / | '_ ` _ \| | __| | | | \___ \| | | | ' / 5 | // | __/| | | (_) > <| | | | | | | | |_| |_| | ___) | |_| | . \ 6 | // |_| |_| \___/_/\_\_|_| |_| |_|_|\__|\__, | |____/|____/|_|\_\ 7 | // |___/ 8 | // 9 | // Copyright © 2017 Estimote. All rights reserved. 10 | // 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | /** 17 | Represents range of a proximity where enter/exit events should occur. 18 | 19 | Note: 20 | Due to BLE signal instability the actual place where notifications occur will differ. 21 | The `meanTriggerDistance` value defines the desired mean of distance at which events occur. 22 | 23 | The distance is rounded up to decimeters. Don't expect decimeter accuracy; this is only for simplification 24 | of EPXProximityRange objects comparison. 25 | */ 26 | NS_SWIFT_NAME(ProximityRange) 27 | @interface EPXProximityRange : NSObject 28 | 29 | /** 30 | Distance in meters where enter/exit events should occur passed in initializer rounded to decimeters (to 0.1). 31 | */ 32 | @property(nonatomic, assign, readonly) double desiredMeanTriggerDistance; 33 | 34 | /** 35 | Convenience factory for near range. Returns range with meanTriggerDistance set to 1m. 36 | 37 | It's a class property instead of class method to enable good-looking Swift code. 38 | */ 39 | @property(nonatomic, copy, readonly, class) EPXProximityRange *nearRange; 40 | 41 | /** 42 | Convenience factory for far range. Returns range with meanTriggerDistance set to 5m. 43 | 44 | It's a class property instead of class method to enable good-looking Swift code. 45 | */ 46 | @property(nonatomic, copy, readonly, class) EPXProximityRange *farRange; 47 | 48 | /** 49 | Init is disabled for this class. 50 | */ 51 | - (instancetype)init NS_UNAVAILABLE; 52 | 53 | /** 54 | New is disabled for this class. 55 | */ 56 | + (instancetype) new NS_UNAVAILABLE; 57 | 58 | /** 59 | Designated initializer. 60 | 61 | @param desiredMeanTriggerDistance Distance in meters where enter/exit events should occur rounded to decimeters (to 0.1). 62 | It has to be a non-negative number. 63 | 64 | @return Initialized object. Nil if passed desiredMeanTriggerDistance is negative. 65 | */ 66 | - (nullable instancetype)initWithDesiredMeanTriggerDistance:(double)desiredMeanTriggerDistance NS_DESIGNATED_INITIALIZER; 67 | 68 | /** 69 | Convenience factory method. Calls `-initWithMeanTriggerDistance:`. 70 | 71 | @param desiredMeanTriggerDistance Distance in meters where enter/exit events should occur rounded to decimeters (to 0.1). 72 | It has to be a non-negative number. 73 | 74 | @return Initialized object. Nil if passed desiredMeanTriggerDistance is negative. 75 | */ 76 | + (nullable instancetype)customRangeWithDesiredMeanTriggerDistance:(double)desiredMeanTriggerDistance 77 | NS_SWIFT_NAME(custom(desiredMeanTriggerDistance:)); 78 | 79 | #pragma mark isEqual overrides 80 | - (BOOL)isEqualToRange:(EPXProximityRange *)otherRange; 81 | - (BOOL)isEqual:(nullable id)otherObject; 82 | - (NSUInteger)hash; 83 | 84 | @end 85 | 86 | NS_ASSUME_NONNULL_END 87 | -------------------------------------------------------------------------------- /ios/EPXHeaders/EPXProximityZone.h: -------------------------------------------------------------------------------- 1 | // 2 | // ____ _ _ _ ____ ____ _ __ 3 | // | _ \ _ __ _____ _(_)_ __ ___ (_) |_ _ _ / ___|| _ \| |/ / 4 | // | |_) | '__/ _ \ \/ / | '_ ` _ \| | __| | | | \___ \| | | | ' / 5 | // | __/| | | (_) > <| | | | | | | | |_| |_| | ___) | |_| | . \ 6 | // |_| |_| \___/_/\_\_|_| |_| |_|_|\__|\__, | |____/|____/|_|\_\ 7 | // |___/ 8 | // 9 | // Copyright © 2017 Estimote. All rights reserved. 10 | // 11 | 12 | #import 13 | #import "EPXProximityRange.h" 14 | #import "EPXProximityZoneContext.h" 15 | 16 | NS_ASSUME_NONNULL_BEGIN 17 | 18 | //FIXME: fix this description 19 | /** 20 | Represents a logical zone. Is represented by range from a beacon and attachment rule (attachment key + attachment value). 21 | Can be spanned by one or more beacons. Beacon identification is attachment-based 22 | (see https://github.com/Estimote/iOS-Proximity-SDK/blob/master/README.md for more info). 23 | 24 | Note: at the moment, Proximity SDK supports monitoring only 100 devices per zone. If more devices have their attachments 25 | matching the key, value defined in the zone, the first 100 are monitored. 26 | */ 27 | NS_SWIFT_NAME(ProximityZone) 28 | @interface EPXProximityZone : NSObject 29 | 30 | /** 31 | Range where the action should be reported. 32 | */ 33 | @property (nonatomic, strong, readonly) EPXProximityRange *range; 34 | 35 | /** 36 | Tag assigned in Cloud to that zone. 37 | */ 38 | @property (nonatomic, readonly) NSString *tag; 39 | 40 | /** 41 | Register block to be called when user enters proximity of Estimote devices with matching tag. 42 | Beacon identification is tag-based (see https://github.com/Estimote/iOS-SDK/blob/sdk_5/README.md for more info). 43 | */ 44 | @property (nonatomic, copy, readwrite, nullable) void (^onEnter)(EPXProximityZoneContext * zoneContext); 45 | 46 | /** 47 | Block to be called when user exits proximity of Estimote devices with matching tag. 48 | Beacon identification is tag-based (see https://github.com/Estimote/iOS-SDK/blob/sdk_5/README.md for more info). 49 | */ 50 | @property (nonatomic, copy, readwrite, nullable) void (^onExit)(EPXProximityZoneContext * zoneContext); 51 | 52 | /** 53 | Block to be called each time a new beacon is detected in user's range and each time a beacon disappears 54 | from user's range. 55 | */ 56 | @property (nonatomic, copy, readwrite, nullable) void (^onContextChange)(NSSet *zoneContexts); 57 | 58 | /** 59 | Init is unavailable. 60 | */ 61 | - (instancetype)init NS_UNAVAILABLE; 62 | /** 63 | New is unavailable. 64 | */ 65 | + (instancetype)new NS_UNAVAILABLE; 66 | 67 | /** 68 | Designated initilizer. 69 | 70 | @param tag Tag name assigned to the zone. 71 | @param range Range where the action should be reported. 72 | */ 73 | - (instancetype)initWithTag:(NSString *)tag range:(EPXProximityRange *)range NS_DESIGNATED_INITIALIZER; 74 | 75 | @end 76 | 77 | NS_ASSUME_NONNULL_END 78 | -------------------------------------------------------------------------------- /ios/EPXHeaders/EPXProximityZoneContext.h: -------------------------------------------------------------------------------- 1 | // 2 | // ____ _ _ _ ____ ____ _ __ 3 | // | _ \ _ __ _____ _(_)_ __ ___ (_) |_ _ _ / ___|| _ \| |/ / 4 | // | |_) | '__/ _ \ \/ / | '_ ` _ \| | __| | | | \___ \| | | | ' / 5 | // | __/| | | (_) > <| | | | | | | | |_| |_| | ___) | |_| | . \ 6 | // |_| |_| \___/_/\_\_|_| |_| |_|_|\__|\__, | |____/|____/|_|\_\ 7 | // |___/ 8 | // 9 | // Copyright © 2017 Estimote. All rights reserved. 10 | // 11 | 12 | #import 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | /** 17 | Interface providing all contextual data about a Proximity Zone. 18 | */ 19 | NS_SWIFT_NAME(ProximityZoneContext) 20 | @interface EPXProximityZoneContext: NSObject 21 | 22 | /** 23 | Identifier of a device that is the zone's source. 24 | */ 25 | @property (nonatomic, readonly) NSString *deviceIdentifier; 26 | /** 27 | Tag assigned in Cloud to that zone's source. 28 | */ 29 | @property (nonatomic, readonly) NSString *tag; 30 | /** 31 | Dictionary of attachments assigned in Cloud to that zone's source. 32 | */ 33 | @property (nonatomic, readonly) NSDictionary *attachments; 34 | 35 | - (instancetype)init NS_UNAVAILABLE; 36 | + (instancetype)new NS_UNAVAILABLE; 37 | 38 | /** 39 | Designated initializer. 40 | 41 | @param deviceIdentifier Zone's source. 42 | @param tag Zone's tag name. 43 | @param attachments Dicitionary of attachments. 44 | @return Initialized object. 45 | */ 46 | - (instancetype)initWithDeviceIdentifier:(NSString *)deviceIdentifier 47 | tag:(NSString *)tag 48 | attachments:(NSDictionary *)attachments NS_DESIGNATED_INITIALIZER; 49 | 50 | @end 51 | 52 | NS_ASSUME_NONNULL_END 53 | -------------------------------------------------------------------------------- /ios/EPXHeaders/EstimoteProximitySDK-Swift.h: -------------------------------------------------------------------------------- 1 | // Generated by Apple Swift version 4.1.2 (swiftlang-902.0.54 clang-902.0.39.2) 2 | #pragma clang diagnostic push 3 | #pragma clang diagnostic ignored "-Wgcc-compat" 4 | 5 | #if !defined(__has_include) 6 | # define __has_include(x) 0 7 | #endif 8 | #if !defined(__has_attribute) 9 | # define __has_attribute(x) 0 10 | #endif 11 | #if !defined(__has_feature) 12 | # define __has_feature(x) 0 13 | #endif 14 | #if !defined(__has_warning) 15 | # define __has_warning(x) 0 16 | #endif 17 | 18 | #if __has_include() 19 | # include 20 | #endif 21 | 22 | #pragma clang diagnostic ignored "-Wauto-import" 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #if !defined(SWIFT_TYPEDEFS) 29 | # define SWIFT_TYPEDEFS 1 30 | # if __has_include() 31 | # include 32 | # elif !defined(__cplusplus) 33 | typedef uint_least16_t char16_t; 34 | typedef uint_least32_t char32_t; 35 | # endif 36 | typedef float swift_float2 __attribute__((__ext_vector_type__(2))); 37 | typedef float swift_float3 __attribute__((__ext_vector_type__(3))); 38 | typedef float swift_float4 __attribute__((__ext_vector_type__(4))); 39 | typedef double swift_double2 __attribute__((__ext_vector_type__(2))); 40 | typedef double swift_double3 __attribute__((__ext_vector_type__(3))); 41 | typedef double swift_double4 __attribute__((__ext_vector_type__(4))); 42 | typedef int swift_int2 __attribute__((__ext_vector_type__(2))); 43 | typedef int swift_int3 __attribute__((__ext_vector_type__(3))); 44 | typedef int swift_int4 __attribute__((__ext_vector_type__(4))); 45 | typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); 46 | typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); 47 | typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); 48 | #endif 49 | 50 | #if !defined(SWIFT_PASTE) 51 | # define SWIFT_PASTE_HELPER(x, y) x##y 52 | # define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) 53 | #endif 54 | #if !defined(SWIFT_METATYPE) 55 | # define SWIFT_METATYPE(X) Class 56 | #endif 57 | #if !defined(SWIFT_CLASS_PROPERTY) 58 | # if __has_feature(objc_class_property) 59 | # define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ 60 | # else 61 | # define SWIFT_CLASS_PROPERTY(...) 62 | # endif 63 | #endif 64 | 65 | #if __has_attribute(objc_runtime_name) 66 | # define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) 67 | #else 68 | # define SWIFT_RUNTIME_NAME(X) 69 | #endif 70 | #if __has_attribute(swift_name) 71 | # define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) 72 | #else 73 | # define SWIFT_COMPILE_NAME(X) 74 | #endif 75 | #if __has_attribute(objc_method_family) 76 | # define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) 77 | #else 78 | # define SWIFT_METHOD_FAMILY(X) 79 | #endif 80 | #if __has_attribute(noescape) 81 | # define SWIFT_NOESCAPE __attribute__((noescape)) 82 | #else 83 | # define SWIFT_NOESCAPE 84 | #endif 85 | #if __has_attribute(warn_unused_result) 86 | # define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) 87 | #else 88 | # define SWIFT_WARN_UNUSED_RESULT 89 | #endif 90 | #if __has_attribute(noreturn) 91 | # define SWIFT_NORETURN __attribute__((noreturn)) 92 | #else 93 | # define SWIFT_NORETURN 94 | #endif 95 | #if !defined(SWIFT_CLASS_EXTRA) 96 | # define SWIFT_CLASS_EXTRA 97 | #endif 98 | #if !defined(SWIFT_PROTOCOL_EXTRA) 99 | # define SWIFT_PROTOCOL_EXTRA 100 | #endif 101 | #if !defined(SWIFT_ENUM_EXTRA) 102 | # define SWIFT_ENUM_EXTRA 103 | #endif 104 | #if !defined(SWIFT_CLASS) 105 | # if __has_attribute(objc_subclassing_restricted) 106 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA 107 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 108 | # else 109 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 110 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA 111 | # endif 112 | #endif 113 | 114 | #if !defined(SWIFT_PROTOCOL) 115 | # define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA 116 | # define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA 117 | #endif 118 | 119 | #if !defined(SWIFT_EXTENSION) 120 | # define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) 121 | #endif 122 | 123 | #if !defined(OBJC_DESIGNATED_INITIALIZER) 124 | # if __has_attribute(objc_designated_initializer) 125 | # define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) 126 | # else 127 | # define OBJC_DESIGNATED_INITIALIZER 128 | # endif 129 | #endif 130 | #if !defined(SWIFT_ENUM_ATTR) 131 | # if defined(__has_attribute) && __has_attribute(enum_extensibility) 132 | # define SWIFT_ENUM_ATTR __attribute__((enum_extensibility(open))) 133 | # else 134 | # define SWIFT_ENUM_ATTR 135 | # endif 136 | #endif 137 | #if !defined(SWIFT_ENUM) 138 | # define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_ATTR SWIFT_ENUM_EXTRA _name : _type 139 | # if __has_feature(generalized_swift_name) 140 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR SWIFT_ENUM_EXTRA _name : _type 141 | # else 142 | # define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) SWIFT_ENUM(_type, _name) 143 | # endif 144 | #endif 145 | #if !defined(SWIFT_UNAVAILABLE) 146 | # define SWIFT_UNAVAILABLE __attribute__((unavailable)) 147 | #endif 148 | #if !defined(SWIFT_UNAVAILABLE_MSG) 149 | # define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) 150 | #endif 151 | #if !defined(SWIFT_AVAILABILITY) 152 | # define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) 153 | #endif 154 | #if !defined(SWIFT_DEPRECATED) 155 | # define SWIFT_DEPRECATED __attribute__((deprecated)) 156 | #endif 157 | #if !defined(SWIFT_DEPRECATED_MSG) 158 | # define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) 159 | #endif 160 | #if __has_feature(attribute_diagnose_if_objc) 161 | # define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) 162 | #else 163 | # define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) 164 | #endif 165 | #if __has_feature(modules) 166 | @import CoreLocation; 167 | @import Foundation; 168 | #endif 169 | 170 | #pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" 171 | #pragma clang diagnostic ignored "-Wduplicate-method-arg" 172 | #if __has_warning("-Wpragma-clang-attribute") 173 | # pragma clang diagnostic ignored "-Wpragma-clang-attribute" 174 | #endif 175 | #pragma clang diagnostic ignored "-Wunknown-pragmas" 176 | #pragma clang diagnostic ignored "-Wnullability" 177 | 178 | #if __has_attribute(external_source_symbol) 179 | # pragma push_macro("any") 180 | # undef any 181 | # pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="EstimoteProximitySDK",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) 182 | # pragma pop_macro("any") 183 | #endif 184 | 185 | 186 | 187 | 188 | 189 | #if __has_attribute(external_source_symbol) 190 | # pragma clang attribute pop 191 | #endif 192 | #pragma clang diagnostic pop 193 | -------------------------------------------------------------------------------- /ios/EPXHeaders/EstimoteProximitySDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // ____ _ _ _ ____ ____ _ __ 3 | // | _ \ _ __ _____ _(_)_ __ ___ (_) |_ _ _ / ___|| _ \| |/ / 4 | // | |_) | '__/ _ \ \/ / | '_ ` _ \| | __| | | | \___ \| | | | ' / 5 | // | __/| | | (_) > <| | | | | | | | |_| |_| | ___) | |_| | . \ 6 | // |_| |_| \___/_/\_\_|_| |_| |_|_|\__|\__, | |____/|____/|_|\_\ 7 | // |___/ 8 | // 9 | // Copyright © 2017 Estimote. All rights reserved. 10 | // 11 | 12 | #import 13 | 14 | //! Project version number for EstimoteProximitySDK. 15 | FOUNDATION_EXPORT double EstimoteProximitySDKVersionNumber; 16 | 17 | //! Project version string for EstimoteProximitySDK. 18 | FOUNDATION_EXPORT const unsigned char EstimoteProximitySDKVersionString[]; 19 | 20 | // In this header, you should import all the public headers of your framework using statements like #import 21 | 22 | #import "EPXProximityObserver.h" 23 | #import "EPXProximityObserverConfiguration.h" 24 | #import "EPXProximityZone.h" 25 | #import "EPXProximityRange.h" 26 | #import "EPXCloudCredentials.h" 27 | #import "EPXProximityZoneContext.h" 28 | -------------------------------------------------------------------------------- /ios/RNEstimoteProximity.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface RNEstimoteProximity : RCTEventEmitter 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /ios/RNEstimoteProximity.m: -------------------------------------------------------------------------------- 1 | #import "RNEstimoteProximity.h" 2 | 3 | #import 4 | 5 | #import 6 | 7 | #import "EPXCloudCredentials.h" 8 | #import "EPXProximityObserver.h" 9 | #import "EPXProximityZone.h" 10 | #import "EPXProximityZoneContext.h" 11 | 12 | NSString * authStringForCurrentAuthStatus() { 13 | switch ([CLLocationManager authorizationStatus]) { 14 | case kCLAuthorizationStatusNotDetermined: 15 | return nil; 16 | case kCLAuthorizationStatusRestricted: 17 | case kCLAuthorizationStatusDenied: 18 | return @"denied"; 19 | case kCLAuthorizationStatusAuthorizedAlways: 20 | return @"always"; 21 | case kCLAuthorizationStatusAuthorizedWhenInUse: 22 | return @"when_in_use"; 23 | } 24 | } 25 | 26 | NSDictionary * contextToJSON(EPXProximityZoneContext *context) { 27 | return @{@"tag": context.tag, 28 | @"attachments": context.attachments, 29 | @"deviceIdentifier": context.deviceIdentifier}; 30 | } 31 | 32 | 33 | @interface RNEstimoteProximity () 34 | 35 | @property (nonatomic, strong) EPXProximityObserver *observer; 36 | 37 | @property (nonatomic, strong) CLLocationManager *locationManager; 38 | @property (nonatomic, strong) RCTPromiseResolveBlock locationPermissionResolver; 39 | 40 | @end 41 | 42 | @implementation RNEstimoteProximity 43 | 44 | RCT_EXPORT_MODULE() 45 | 46 | - (dispatch_queue_t)methodQueue { 47 | return dispatch_get_main_queue(); 48 | } 49 | 50 | - (NSArray *)supportedEvents { 51 | return @[@"Enter", @"Exit", @"Change"]; 52 | } 53 | 54 | - (void)dealloc { 55 | [self.observer stopObservingZones]; 56 | } 57 | 58 | RCT_EXPORT_METHOD(initialize:(NSDictionary *)config) { 59 | RCTLogInfo(@"Initializing with config: %@", config); 60 | 61 | EPXCloudCredentials *credentials = [[EPXCloudCredentials alloc] initWithAppID:config[@"appId"] appToken:config[@"appToken"]]; 62 | 63 | self.observer = [[EPXProximityObserver alloc] initWithCredentials:credentials onError:^(NSError * _Nonnull error) { 64 | RCTLogError(@"Proximity Observer error: %@", error); 65 | }]; 66 | } 67 | 68 | RCT_EXPORT_METHOD(startObservingZones:(NSArray *)zonesJSON) { 69 | NSMutableArray *zones = [NSMutableArray arrayWithCapacity:zonesJSON.count]; 70 | 71 | for (NSDictionary *zoneJSON in zonesJSON) { 72 | NSString *_id = zoneJSON[@"_id"]; 73 | NSNumber *range = zoneJSON[@"range"]; 74 | NSString *tag = zoneJSON[@"tag"]; 75 | 76 | RCTLogInfo(@"Creating Proximity Zone _id = %@, range = %@, tag = %@", _id, range, tag); 77 | 78 | EPXProximityZone *zone = [[EPXProximityZone alloc] 79 | initWithTag:tag 80 | range:[EPXProximityRange customRangeWithDesiredMeanTriggerDistance:range.doubleValue]]; 81 | 82 | __weak __typeof(self) weakSelf = self; 83 | 84 | zone.onEnter = ^(EPXProximityZoneContext *context) { 85 | RCTLogInfo(@"onEnter, zoneId = %@, context = %@", _id, context); 86 | 87 | [weakSelf sendEventWithName:@"Enter" body:@{@"zoneId": _id, 88 | @"context": contextToJSON(context)}]; 89 | }; 90 | 91 | zone.onExit = ^(EPXProximityZoneContext *context) { 92 | RCTLogInfo(@"onExit, zoneId = %@, context = %@", _id, context); 93 | 94 | [weakSelf sendEventWithName:@"Exit" body:@{@"zoneId": _id, 95 | @"context": contextToJSON(context)}]; 96 | }; 97 | 98 | zone.onContextChange = ^(NSSet *contexts) { 99 | RCTLogInfo(@"onContextChange, zoneId = %@, contexts = %@", _id, contexts); 100 | 101 | NSMutableArray *convertedContexts = [NSMutableArray arrayWithCapacity:contexts.count]; 102 | for (EPXProximityZoneContext *context in contexts) { 103 | [convertedContexts addObject:contextToJSON(context)]; 104 | } 105 | [weakSelf sendEventWithName:@"Change" body:@{@"zoneId": _id, 106 | @"contexts": convertedContexts}]; 107 | }; 108 | 109 | [zones addObject:zone]; 110 | } 111 | 112 | [self.observer startObservingZones:zones]; 113 | 114 | RCTLogInfo(@"Started observing for %lu zone(s)", (unsigned long) zones.count); 115 | } 116 | 117 | RCT_EXPORT_METHOD(stopObservingZones) { 118 | [self.observer stopObservingZones]; 119 | 120 | RCTLogInfo(@"Stopped observing"); 121 | } 122 | 123 | RCT_REMAP_METHOD(requestLocationPermission, 124 | requestLocationPermissionWithResolver:(RCTPromiseResolveBlock)resolve 125 | rejecter:(RCTPromiseRejectBlock)reject) { 126 | if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) { 127 | self.locationPermissionResolver = resolve; 128 | self.locationManager = [CLLocationManager new]; 129 | self.locationManager.delegate = self; 130 | [self.locationManager requestAlwaysAuthorization]; 131 | } else { 132 | resolve(authStringForCurrentAuthStatus()); 133 | } 134 | } 135 | 136 | - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { 137 | if (status != kCLAuthorizationStatusNotDetermined) { 138 | self.locationPermissionResolver(authStringForCurrentAuthStatus()); 139 | self.locationPermissionResolver = nil; 140 | self.locationManager = nil; 141 | } 142 | } 143 | 144 | @end 145 | -------------------------------------------------------------------------------- /ios/RNEstimoteProximity.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B3E7B58A1CC2AC0600A0062D /* RNEstimoteProximity.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNEstimoteProximity.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 /* libRNEstimoteProximity.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNEstimoteProximity.a; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | B3E7B5881CC2AC0600A0062D /* RNEstimoteProximity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNEstimoteProximity.h; sourceTree = ""; }; 28 | B3E7B5891CC2AC0600A0062D /* RNEstimoteProximity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNEstimoteProximity.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 /* libRNEstimoteProximity.a */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | 58B511D21A9E6C8500147676 = { 51 | isa = PBXGroup; 52 | children = ( 53 | B3E7B5881CC2AC0600A0062D /* RNEstimoteProximity.h */, 54 | B3E7B5891CC2AC0600A0062D /* RNEstimoteProximity.m */, 55 | 134814211AA4EA7D00B7C361 /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | /* End PBXGroup section */ 60 | 61 | /* Begin PBXNativeTarget section */ 62 | 58B511DA1A9E6C8500147676 /* RNEstimoteProximity */ = { 63 | isa = PBXNativeTarget; 64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNEstimoteProximity" */; 65 | buildPhases = ( 66 | 58B511D71A9E6C8500147676 /* Sources */, 67 | 58B511D81A9E6C8500147676 /* Frameworks */, 68 | 58B511D91A9E6C8500147676 /* CopyFiles */, 69 | ); 70 | buildRules = ( 71 | ); 72 | dependencies = ( 73 | ); 74 | name = RNEstimoteProximity; 75 | productName = RCTDataManager; 76 | productReference = 134814201AA4EA6300B7C361 /* libRNEstimoteProximity.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 = 1010; 86 | ORGANIZATIONNAME = Facebook; 87 | TargetAttributes = { 88 | 58B511DA1A9E6C8500147676 = { 89 | CreatedOnToolsVersion = 6.1.1; 90 | }; 91 | }; 92 | }; 93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNEstimoteProximity" */; 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 /* RNEstimoteProximity */, 106 | ); 107 | }; 108 | /* End PBXProject section */ 109 | 110 | /* Begin PBXSourcesBuildPhase section */ 111 | 58B511D71A9E6C8500147676 /* Sources */ = { 112 | isa = PBXSourcesBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | B3E7B58A1CC2AC0600A0062D /* RNEstimoteProximity.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_BLOCK_CAPTURE_AUTORELEASING = YES; 131 | CLANG_WARN_BOOL_CONVERSION = YES; 132 | CLANG_WARN_COMMA = YES; 133 | CLANG_WARN_CONSTANT_CONVERSION = YES; 134 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 135 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 136 | CLANG_WARN_EMPTY_BODY = YES; 137 | CLANG_WARN_ENUM_CONVERSION = YES; 138 | CLANG_WARN_INFINITE_RECURSION = YES; 139 | CLANG_WARN_INT_CONVERSION = YES; 140 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 141 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 142 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 143 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 144 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 145 | CLANG_WARN_STRICT_PROTOTYPES = YES; 146 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 147 | CLANG_WARN_UNREACHABLE_CODE = YES; 148 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 149 | COPY_PHASE_STRIP = NO; 150 | ENABLE_STRICT_OBJC_MSGSEND = YES; 151 | ENABLE_TESTABILITY = YES; 152 | GCC_C_LANGUAGE_STANDARD = gnu99; 153 | GCC_DYNAMIC_NO_PIC = NO; 154 | GCC_NO_COMMON_BLOCKS = YES; 155 | GCC_OPTIMIZATION_LEVEL = 0; 156 | GCC_PREPROCESSOR_DEFINITIONS = ( 157 | "DEBUG=1", 158 | "$(inherited)", 159 | ); 160 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 161 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 162 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 163 | GCC_WARN_UNDECLARED_SELECTOR = YES; 164 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 165 | GCC_WARN_UNUSED_FUNCTION = YES; 166 | GCC_WARN_UNUSED_VARIABLE = YES; 167 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 168 | MTL_ENABLE_DEBUG_INFO = YES; 169 | ONLY_ACTIVE_ARCH = YES; 170 | SDKROOT = iphoneos; 171 | }; 172 | name = Debug; 173 | }; 174 | 58B511EE1A9E6C8500147676 /* Release */ = { 175 | isa = XCBuildConfiguration; 176 | buildSettings = { 177 | ALWAYS_SEARCH_USER_PATHS = NO; 178 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 179 | CLANG_CXX_LIBRARY = "libc++"; 180 | CLANG_ENABLE_MODULES = YES; 181 | CLANG_ENABLE_OBJC_ARC = YES; 182 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 183 | CLANG_WARN_BOOL_CONVERSION = YES; 184 | CLANG_WARN_COMMA = YES; 185 | CLANG_WARN_CONSTANT_CONVERSION = YES; 186 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 187 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 188 | CLANG_WARN_EMPTY_BODY = YES; 189 | CLANG_WARN_ENUM_CONVERSION = YES; 190 | CLANG_WARN_INFINITE_RECURSION = YES; 191 | CLANG_WARN_INT_CONVERSION = YES; 192 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 193 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 194 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 195 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 196 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 197 | CLANG_WARN_STRICT_PROTOTYPES = YES; 198 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 199 | CLANG_WARN_UNREACHABLE_CODE = YES; 200 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 201 | COPY_PHASE_STRIP = YES; 202 | ENABLE_NS_ASSERTIONS = NO; 203 | ENABLE_STRICT_OBJC_MSGSEND = YES; 204 | GCC_C_LANGUAGE_STANDARD = gnu99; 205 | GCC_NO_COMMON_BLOCKS = YES; 206 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 207 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 208 | GCC_WARN_UNDECLARED_SELECTOR = YES; 209 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 210 | GCC_WARN_UNUSED_FUNCTION = YES; 211 | GCC_WARN_UNUSED_VARIABLE = YES; 212 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 213 | MTL_ENABLE_DEBUG_INFO = NO; 214 | SDKROOT = iphoneos; 215 | VALIDATE_PRODUCT = YES; 216 | }; 217 | name = Release; 218 | }; 219 | 58B511F01A9E6C8500147676 /* Debug */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | HEADER_SEARCH_PATHS = ( 223 | "$(inherited)", 224 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 225 | "$(SRCROOT)/../../../React/**", 226 | "$(SRCROOT)/../../react-native/React/**", 227 | "$(SRCROOT)/EPXHeaders", 228 | ); 229 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 230 | OTHER_LDFLAGS = "-ObjC"; 231 | PRODUCT_NAME = RNEstimoteProximity; 232 | SKIP_INSTALL = YES; 233 | }; 234 | name = Debug; 235 | }; 236 | 58B511F11A9E6C8500147676 /* Release */ = { 237 | isa = XCBuildConfiguration; 238 | buildSettings = { 239 | HEADER_SEARCH_PATHS = ( 240 | "$(inherited)", 241 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 242 | "$(SRCROOT)/../../../React/**", 243 | "$(SRCROOT)/../../react-native/React/**", 244 | "$(SRCROOT)/EPXHeaders", 245 | ); 246 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 247 | OTHER_LDFLAGS = "-ObjC"; 248 | PRODUCT_NAME = RNEstimoteProximity; 249 | SKIP_INSTALL = YES; 250 | }; 251 | name = Release; 252 | }; 253 | /* End XCBuildConfiguration section */ 254 | 255 | /* Begin XCConfigurationList section */ 256 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNEstimoteProximity" */ = { 257 | isa = XCConfigurationList; 258 | buildConfigurations = ( 259 | 58B511ED1A9E6C8500147676 /* Debug */, 260 | 58B511EE1A9E6C8500147676 /* Release */, 261 | ); 262 | defaultConfigurationIsVisible = 0; 263 | defaultConfigurationName = Release; 264 | }; 265 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNEstimoteProximity" */ = { 266 | isa = XCConfigurationList; 267 | buildConfigurations = ( 268 | 58B511F01A9E6C8500147676 /* Debug */, 269 | 58B511F11A9E6C8500147676 /* Release */, 270 | ); 271 | defaultConfigurationIsVisible = 0; 272 | defaultConfigurationName = Release; 273 | }; 274 | /* End XCConfigurationList section */ 275 | }; 276 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 277 | } 278 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@estimote/react-native-proximity", 3 | "version": "0.6.0", 4 | "description": "React Native wrapper for Estimote Proximity SDK", 5 | "main": "index.js", 6 | "keywords": [ 7 | "beacons", 8 | "estimote", 9 | "proximity", 10 | "react-native" 11 | ], 12 | "author": "Estimote ", 13 | "license": "Apache-2.0", 14 | "homepage": "https://github.com/Estimote/react-native-proximity", 15 | "bugs": { 16 | "url": "https://github.com/Estimote/react-native-proximity/issues" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/Estimote/react-native-proximity.git" 21 | } 22 | } 23 | --------------------------------------------------------------------------------