├── .github ├── dependabot.yml ├── setup │ └── action.yml └── workflows │ └── validate.yml ├── .gitignore ├── .tool-versions ├── CHANGELOG.md ├── LICENSE ├── README.md ├── apps ├── example │ ├── .bundle │ │ └── config │ ├── .eslintrc.js │ ├── .gitignore │ ├── .watchmanconfig │ ├── Gemfile │ ├── Gemfile.lock │ ├── README.md │ ├── android │ │ ├── app │ │ │ ├── build.gradle │ │ │ ├── debug.keystore │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── exampleapp │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ └── MainApplication.kt │ │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── 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 │ │ ├── .xcode.env │ │ ├── ExampleApp.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── ExampleApp.xcscheme │ │ ├── ExampleApp.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ ├── ExampleApp │ │ │ ├── AppDelegate.swift │ │ │ ├── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── LaunchScreen.storyboard │ │ │ └── PrivacyInfo.xcprivacy │ │ ├── Podfile │ │ └── Podfile.lock │ ├── metro.config.js │ ├── package.json │ ├── react-native.config.js │ ├── src │ │ ├── App.tsx │ │ ├── HomeScreen.tsx │ │ ├── Permissions.tsx │ │ └── queryClient.ts │ └── tsconfig.json └── expo-example-app │ ├── .babelrc.js │ ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── patwoz │ │ │ │ └── expoexampleapp │ │ │ │ ├── MainActivity.kt │ │ │ │ └── MainApplication.kt │ │ │ └── res │ │ │ ├── drawable-hdpi │ │ │ └── splashscreen_logo.png │ │ │ ├── drawable-mdpi │ │ │ └── splashscreen_logo.png │ │ │ ├── drawable-xhdpi │ │ │ └── splashscreen_logo.png │ │ │ ├── drawable-xxhdpi │ │ │ └── splashscreen_logo.png │ │ │ ├── drawable-xxxhdpi │ │ │ └── splashscreen_logo.png │ │ │ ├── drawable │ │ │ ├── ic_launcher_background.xml │ │ │ └── rn_edit_text_material.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.webp │ │ │ ├── ic_launcher_foreground.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.webp │ │ │ ├── ic_launcher_foreground.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.webp │ │ │ ├── ic_launcher_foreground.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.webp │ │ │ ├── ic_launcher_foreground.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.webp │ │ │ ├── ic_launcher_foreground.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── values-night │ │ │ └── colors.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle │ ├── app.json │ ├── assets │ ├── adaptive-icon.png │ ├── favicon.png │ ├── icon.png │ └── splash.png │ ├── eas.json │ ├── index.js │ ├── ios │ ├── .gitignore │ ├── .xcode.env │ ├── ExpoExampleApp.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── ExpoExampleApp.xcscheme │ ├── ExpoExampleApp.xcworkspace │ │ └── contents.xcworkspacedata │ ├── ExpoExampleApp │ │ ├── AppDelegate.h │ │ ├── AppDelegate.mm │ │ ├── ExpoExampleApp-Bridging-Header.h │ │ ├── ExpoExampleApp.entitlements │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── App-Icon-1024x1024@1x.png │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── SplashScreenBackground.colorset │ │ │ │ └── Contents.json │ │ │ └── SplashScreenLogo.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── image.png │ │ │ │ ├── image@2x.png │ │ │ │ └── image@3x.png │ │ ├── Info.plist │ │ ├── PrivacyInfo.xcprivacy │ │ ├── SplashScreen.storyboard │ │ ├── Supporting │ │ │ └── Expo.plist │ │ ├── main.m │ │ └── noop-file.swift │ ├── Podfile │ ├── Podfile.lock │ └── Podfile.properties.json │ ├── metro.config.js │ ├── package.json │ ├── src │ └── app │ │ └── App.tsx │ ├── tsconfig.app.json │ └── tsconfig.json ├── babel.config.json ├── bun.lock ├── nx.json ├── package.json ├── packages └── react-native-bluetooth-state-manager │ ├── .gitignore │ ├── .watchmanconfig │ ├── BluetoothStateManager.podspec │ ├── README.md │ ├── android │ ├── CMakeLists.txt │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── kls_database.db │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── cpp │ │ └── cpp-adapter.cpp │ │ └── java │ │ └── com │ │ └── margelo │ │ └── nitro │ │ └── bluetoothstatemanager │ │ ├── BluetoothStateManager.kt │ │ └── BluetoothStateManagerPackage.java │ ├── babel.config.js │ ├── ios │ └── HybridBluetoothStateManager.swift │ ├── nitro.json │ ├── nitrogen │ └── generated │ │ ├── .gitattributes │ │ ├── android │ │ ├── BluetoothStateManager+autolinking.cmake │ │ ├── BluetoothStateManager+autolinking.gradle │ │ ├── BluetoothStateManagerOnLoad.cpp │ │ ├── BluetoothStateManagerOnLoad.hpp │ │ ├── c++ │ │ │ ├── JBluetoothState.hpp │ │ │ ├── JFunc_void_BluetoothState.hpp │ │ │ ├── JHybridBluetoothStateManagerSpec.cpp │ │ │ └── JHybridBluetoothStateManagerSpec.hpp │ │ └── kotlin │ │ │ └── com │ │ │ └── margelo │ │ │ └── nitro │ │ │ └── bluetoothstatemanager │ │ │ ├── BluetoothState.kt │ │ │ ├── BluetoothStateManagerOnLoad.kt │ │ │ ├── Func_void_BluetoothState.kt │ │ │ └── HybridBluetoothStateManagerSpec.kt │ │ ├── ios │ │ ├── BluetoothStateManager+autolinking.rb │ │ ├── BluetoothStateManager-Swift-Cxx-Bridge.cpp │ │ ├── BluetoothStateManager-Swift-Cxx-Bridge.hpp │ │ ├── BluetoothStateManager-Swift-Cxx-Umbrella.hpp │ │ ├── BluetoothStateManagerAutolinking.mm │ │ ├── BluetoothStateManagerAutolinking.swift │ │ ├── c++ │ │ │ ├── HybridBluetoothStateManagerSpecSwift.cpp │ │ │ └── HybridBluetoothStateManagerSpecSwift.hpp │ │ └── swift │ │ │ ├── BluetoothState.swift │ │ │ ├── Func_void.swift │ │ │ ├── Func_void_BluetoothState.swift │ │ │ ├── Func_void_std__exception_ptr.swift │ │ │ ├── HybridBluetoothStateManagerSpec.swift │ │ │ └── HybridBluetoothStateManagerSpec_cxx.swift │ │ └── shared │ │ └── c++ │ │ ├── BluetoothState.hpp │ │ ├── HybridBluetoothStateManagerSpec.cpp │ │ └── HybridBluetoothStateManagerSpec.hpp │ ├── package.json │ ├── react-native.config.js │ ├── src │ ├── BluetoothStateManager.ts │ ├── index.ts │ ├── specs │ │ └── BluetoothStateManager.nitro.ts │ └── useBluetoothState.ts │ └── tsconfig.json ├── patches └── nx@21.1.2.patch ├── tools └── scripts │ └── eas-build-post-install.mjs ├── tsconfig.base.json └── tsconfig.json /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | labels: 9 | - "dependencies" 10 | 11 | - package-ecosystem: "gradle" 12 | directories: 13 | - "/package/android/" 14 | - "/example/android/" 15 | schedule: 16 | interval: "daily" 17 | labels: 18 | - "nitro-core" 19 | - "nitrogen" 20 | - "dependencies" 21 | - "kotlin" 22 | 23 | - package-ecosystem: "npm" 24 | directories: 25 | - "/package/" 26 | - "/example/" 27 | schedule: 28 | interval: "daily" 29 | labels: 30 | - "nitro-core" 31 | - "dependencies" 32 | - "typescript" 33 | - "nitrogen" 34 | 35 | groups: 36 | react-native-cli: 37 | patterns: 38 | - "@react-native-community/cli*" 39 | babel: 40 | patterns: 41 | - "@babel/*" 42 | react-native: 43 | patterns: 44 | - "@react-native/*" 45 | -------------------------------------------------------------------------------- /.github/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: setup 2 | 3 | runs: 4 | using: "composite" 5 | steps: 6 | - uses: oven-sh/setup-bun@v2 7 | with: 8 | bun-version-file: ".tool-versions" 9 | 10 | - name: 📦 Install dependencies 11 | run: bun install 12 | shell: bash 13 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | name: validate 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | permissions: 12 | actions: read 13 | contents: read 14 | 15 | jobs: 16 | eslint: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | - uses: ./.github/setup 24 | - uses: nrwl/nx-set-shas@v4 25 | 26 | - name: 🔎 Lint 27 | run: bunx nx affected -t lint 28 | 29 | types: 30 | runs-on: ubuntu-latest 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | with: 35 | fetch-depth: 0 36 | - uses: ./.github/setup 37 | - uses: nrwl/nx-set-shas@v4 38 | 39 | - name: 🩺 Type Checking 40 | run: bunx nx affected -t typecheck 41 | 42 | formatting: 43 | runs-on: ubuntu-latest 44 | 45 | steps: 46 | - uses: actions/checkout@v4 47 | with: 48 | fetch-depth: 0 49 | - uses: ./.github/setup 50 | - uses: nrwl/nx-set-shas@v4 51 | 52 | - name: 💅 Formatting 53 | run: bunx nx affected -t check-format 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | **/.xcode.env.local 6 | 7 | # XDE 8 | .expo/ 9 | 10 | # VSCode 11 | .vscode/ 12 | jsconfig.json 13 | 14 | # Xcode 15 | # 16 | build/ 17 | *.pbxuser 18 | !default.pbxuser 19 | *.mode1v3 20 | !default.mode1v3 21 | *.mode2v3 22 | !default.mode2v3 23 | *.perspectivev3 24 | !default.perspectivev3 25 | xcuserdata 26 | *.xccheckout 27 | *.moved-aside 28 | DerivedData 29 | *.hmap 30 | *.ipa 31 | *.xcuserstate 32 | project.xcworkspace 33 | 34 | # Android/IJ 35 | # 36 | .classpath 37 | .cxx 38 | .gradle 39 | .idea 40 | .project 41 | .settings 42 | local.properties 43 | android.iml 44 | 45 | # Cocoapods 46 | # 47 | example/ios/Pods 48 | 49 | # Ruby 50 | example/vendor/ 51 | 52 | # node.js 53 | # 54 | node_modules/ 55 | npm-debug.log 56 | yarn-debug.log 57 | yarn-error.log 58 | 59 | # Bun 60 | package-lock.json 61 | **/*.bun 62 | 63 | # BUCK 64 | buck-out/ 65 | \.buckd/ 66 | android/app/libs 67 | android/keystores/debug.keystore 68 | 69 | # Yarn 70 | .yarn/* 71 | !.yarn/patches 72 | !.yarn/plugins 73 | !.yarn/releases 74 | !.yarn/sdks 75 | !.yarn/versions 76 | 77 | # Expo 78 | .expo/ 79 | 80 | # Turborepo 81 | .turbo/ 82 | 83 | # generated by bob 84 | lib/ 85 | 86 | # TypeScript 87 | tsconfig.tsbuildinfo 88 | 89 | 90 | .nx/cache 91 | .nx/workspace-data -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | bun 1.2.5 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.0.2 (2025-05-29) 2 | 3 | ### 🩹 Fixes 4 | 5 | - **android:** fixes Java IndexOutOfBoundsException exception ([e8326ff](https://github.com/patlux/react-native-bluetooth-state-manager/commit/e8326ff)) 6 | - **ios:** lazy init of ble manager to avoid prompting bluetooth permission on app start ([dfcb901](https://github.com/patlux/react-native-bluetooth-state-manager/commit/dfcb901)) 7 | 8 | ### ❤️ Thank You 9 | 10 | - Patrick Wozniak @patlux 11 | 12 | ## 2.0.1 (2025-05-19) 13 | 14 | ### 🩹 Fixes 15 | 16 | - **docs:** wrong readme at npmjs.com ([00160c1](https://github.com/patlux/react-native-bluetooth-state-manager/commit/00160c1)) 17 | - **example:** organize code files ([969a72d](https://github.com/patlux/react-native-bluetooth-state-manager/commit/969a72d)) 18 | 19 | ### ❤️ Thank You 20 | 21 | - Patrick Wozniak @patlux 22 | 23 | # 2.0.0 (2025-05-19) 24 | 25 | ### Features 26 | 27 | - Complete rewrite using [nitro-modules](https://nitro.margelo.com/) 28 | - Native TypeScript support 29 | - New synchronous API: `getStateSync()` to retrieve Bluetooth state 30 | 31 | ### Breaking Changes 32 | 33 | - Requires `react-native-nitro-modules` to be installed 34 | - Removed `enable()` and `disable()` due to deprecation starting from Android SDK 33. If your app targets SDK < 33 and depends on these methods, remain on `v1.3.5` 35 | - Replacing programmatic Bluetooth control: use `askToEnable()` and `askToDisable()` to prompt the user instead 36 | 37 | ## 2.0.0-0 (2025-03-26) 38 | 39 | ### Features 40 | 41 | - Complete rewrite. Based on [nitro-modules](https://nitro.margelo.com/) 42 | 43 | ### ❤️ Thank You 44 | 45 | - Patrick Wozniak @patlux 46 | 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Patrick Wozniak 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /apps/example/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /apps/example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native', 4 | rules: { 5 | 'react-native/no-inline-styles': 'off', 6 | semi: 'off', 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /apps/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 | **/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # fastlane 44 | # 45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 46 | # screenshots whenever they are needed. 47 | # For more information about the recommended setup visit: 48 | # https://docs.fastlane.tools/best-practices/source-control/ 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/Preview.html 52 | **/fastlane/screenshots 53 | **/fastlane/test_output 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # Ruby / CocoaPods 59 | **/Pods/ 60 | /vendor/bundle/ 61 | 62 | # Temporary files created by Metro to check the health of the file watcher 63 | .metro-health-check* 64 | 65 | # testing 66 | /coverage 67 | 68 | # Yarn 69 | .yarn/* 70 | !.yarn/patches 71 | !.yarn/plugins 72 | !.yarn/releases 73 | !.yarn/sdks 74 | !.yarn/versions 75 | -------------------------------------------------------------------------------- /apps/example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /apps/example/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | # Exclude problematic versions of cocoapods and activesupport that causes build failures. 7 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' 8 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' 9 | gem 'xcodeproj', '< 1.26.0' 10 | gem 'concurrent-ruby', '< 1.3.4' 11 | -------------------------------------------------------------------------------- /apps/example/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.7) 5 | base64 6 | nkf 7 | rexml 8 | activesupport (7.2.2.1) 9 | base64 10 | benchmark (>= 0.3) 11 | bigdecimal 12 | concurrent-ruby (~> 1.0, >= 1.3.1) 13 | connection_pool (>= 2.2.5) 14 | drb 15 | i18n (>= 1.6, < 2) 16 | logger (>= 1.4.2) 17 | minitest (>= 5.1) 18 | securerandom (>= 0.3) 19 | tzinfo (~> 2.0, >= 2.0.5) 20 | addressable (2.8.7) 21 | public_suffix (>= 2.0.2, < 7.0) 22 | algoliasearch (1.27.5) 23 | httpclient (~> 2.8, >= 2.8.3) 24 | json (>= 1.5.1) 25 | atomos (0.1.3) 26 | base64 (0.2.0) 27 | benchmark (0.4.0) 28 | bigdecimal (3.1.9) 29 | claide (1.1.0) 30 | cocoapods (1.15.2) 31 | addressable (~> 2.8) 32 | claide (>= 1.0.2, < 2.0) 33 | cocoapods-core (= 1.15.2) 34 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 35 | cocoapods-downloader (>= 2.1, < 3.0) 36 | cocoapods-plugins (>= 1.0.0, < 2.0) 37 | cocoapods-search (>= 1.0.0, < 2.0) 38 | cocoapods-trunk (>= 1.6.0, < 2.0) 39 | cocoapods-try (>= 1.1.0, < 2.0) 40 | colored2 (~> 3.1) 41 | escape (~> 0.0.4) 42 | fourflusher (>= 2.3.0, < 3.0) 43 | gh_inspector (~> 1.0) 44 | molinillo (~> 0.8.0) 45 | nap (~> 1.0) 46 | ruby-macho (>= 2.3.0, < 3.0) 47 | xcodeproj (>= 1.23.0, < 2.0) 48 | cocoapods-core (1.15.2) 49 | activesupport (>= 5.0, < 8) 50 | addressable (~> 2.8) 51 | algoliasearch (~> 1.0) 52 | concurrent-ruby (~> 1.1) 53 | fuzzy_match (~> 2.0.4) 54 | nap (~> 1.0) 55 | netrc (~> 0.11) 56 | public_suffix (~> 4.0) 57 | typhoeus (~> 1.0) 58 | cocoapods-deintegrate (1.0.5) 59 | cocoapods-downloader (2.1) 60 | cocoapods-plugins (1.0.0) 61 | nap 62 | cocoapods-search (1.0.1) 63 | cocoapods-trunk (1.6.0) 64 | nap (>= 0.8, < 2.0) 65 | netrc (~> 0.11) 66 | cocoapods-try (1.2.0) 67 | colored2 (3.1.2) 68 | concurrent-ruby (1.3.3) 69 | connection_pool (2.5.0) 70 | drb (2.2.1) 71 | escape (0.0.4) 72 | ethon (0.16.0) 73 | ffi (>= 1.15.0) 74 | ffi (1.17.1) 75 | fourflusher (2.3.1) 76 | fuzzy_match (2.0.4) 77 | gh_inspector (1.1.3) 78 | httpclient (2.8.3) 79 | i18n (1.14.7) 80 | concurrent-ruby (~> 1.0) 81 | json (2.9.1) 82 | logger (1.6.5) 83 | minitest (5.25.4) 84 | molinillo (0.8.0) 85 | nanaimo (0.3.0) 86 | nap (1.1.0) 87 | netrc (0.11.0) 88 | nkf (0.2.0) 89 | public_suffix (4.0.7) 90 | rexml (3.4.0) 91 | ruby-macho (2.5.1) 92 | securerandom (0.4.1) 93 | typhoeus (1.4.1) 94 | ethon (>= 0.9.0) 95 | tzinfo (2.0.6) 96 | concurrent-ruby (~> 1.0) 97 | xcodeproj (1.25.1) 98 | CFPropertyList (>= 2.3.3, < 4.0) 99 | atomos (~> 0.1.3) 100 | claide (>= 1.0.2, < 2.0) 101 | colored2 (~> 3.1) 102 | nanaimo (~> 0.3.0) 103 | rexml (>= 3.3.6, < 4.0) 104 | 105 | PLATFORMS 106 | ruby 107 | 108 | DEPENDENCIES 109 | activesupport (>= 6.1.7.5, != 7.1.0) 110 | cocoapods (>= 1.13, != 1.15.1, != 1.15.0) 111 | concurrent-ruby (< 1.3.4) 112 | xcodeproj (< 1.26.0) 113 | 114 | RUBY VERSION 115 | ruby 3.3.6p108 116 | 117 | BUNDLED WITH 118 | 2.5.22 119 | -------------------------------------------------------------------------------- /apps/example/README.md: -------------------------------------------------------------------------------- 1 | This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). 2 | 3 | # Getting Started 4 | 5 | > **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding. 6 | 7 | ## Step 1: Start Metro 8 | 9 | First, you will need to run **Metro**, the JavaScript build tool for React Native. 10 | 11 | To start the Metro dev server, run the following command from the root of your React Native project: 12 | 13 | ```sh 14 | # Using npm 15 | npm start 16 | 17 | # OR using Yarn 18 | yarn start 19 | ``` 20 | 21 | ## Step 2: Build and run your app 22 | 23 | With Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app: 24 | 25 | ### Android 26 | 27 | ```sh 28 | # Using npm 29 | npm run android 30 | 31 | # OR using Yarn 32 | yarn android 33 | ``` 34 | 35 | ### iOS 36 | 37 | For iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps). 38 | 39 | The first time you create a new project, run the Ruby bundler to install CocoaPods itself: 40 | 41 | ```sh 42 | bundle install 43 | ``` 44 | 45 | Then, and every time you update your native dependencies, run: 46 | 47 | ```sh 48 | bundle exec pod install 49 | ``` 50 | 51 | For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html). 52 | 53 | ```sh 54 | # Using npm 55 | npm run ios 56 | 57 | # OR using Yarn 58 | yarn ios 59 | ``` 60 | 61 | If everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device. 62 | 63 | This is one way to run your app — you can also build it directly from Android Studio or Xcode. 64 | 65 | ## Step 3: Modify your app 66 | 67 | Now that you have successfully run the app, let's make changes! 68 | 69 | Open `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh). 70 | 71 | When you want to forcefully reload, for example to reset the state of your app, you can perform a full reload: 72 | 73 | - **Android**: Press the R key twice or select **"Reload"** from the **Dev Menu**, accessed via Ctrl + M (Windows/Linux) or Cmd ⌘ + M (macOS). 74 | - **iOS**: Press R in iOS Simulator. 75 | 76 | ## Congratulations! :tada: 77 | 78 | You've successfully run and modified your React Native App. :partying_face: 79 | 80 | ### Now what? 81 | 82 | - If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps). 83 | - If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started). 84 | 85 | # Troubleshooting 86 | 87 | If you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page. 88 | 89 | # Learn More 90 | 91 | To learn more about React Native, take a look at the following resources: 92 | 93 | - [React Native Website](https://reactnative.dev) - learn more about React Native. 94 | - [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment. 95 | - [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**. 96 | - [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts. 97 | - [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native. 98 | -------------------------------------------------------------------------------- /apps/example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/debug.keystore -------------------------------------------------------------------------------- /apps/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 | -------------------------------------------------------------------------------- /apps/example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /apps/example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 14 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /apps/example/android/app/src/main/java/com/exampleapp/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.exampleapp 2 | 3 | import com.facebook.react.ReactActivity 4 | import com.facebook.react.ReactActivityDelegate 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate 7 | import android.os.Bundle; 8 | 9 | class MainActivity : ReactActivity() { 10 | 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(null) 13 | } 14 | 15 | /** 16 | * Returns the name of the main component registered from JavaScript. This is used to schedule 17 | * rendering of the component. 18 | */ 19 | override fun getMainComponentName(): String = "ExampleApp" 20 | 21 | /** 22 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 23 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 24 | */ 25 | override fun createReactActivityDelegate(): ReactActivityDelegate = 26 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 27 | } 28 | -------------------------------------------------------------------------------- /apps/example/android/app/src/main/java/com/exampleapp/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.exampleapp 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.react.soloader.OpenSourceMergedSoMapping 13 | import com.facebook.soloader.SoLoader 14 | 15 | class MainApplication : Application(), ReactApplication { 16 | 17 | override val reactNativeHost: ReactNativeHost = 18 | object : DefaultReactNativeHost(this) { 19 | override fun getPackages(): List = 20 | PackageList(this).packages.apply { 21 | // Packages that cannot be autolinked yet can be added manually here, for example: 22 | // add(MyReactNativePackage()) 23 | } 24 | 25 | override fun getJSMainModuleName(): String = "index" 26 | 27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 28 | 29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 31 | } 32 | 33 | override val reactHost: ReactHost 34 | get() = getDefaultReactHost(applicationContext, reactNativeHost) 35 | 36 | override fun onCreate() { 37 | super.onCreate() 38 | SoLoader.init(this, OpenSourceMergedSoMapping) 39 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 40 | // If you opted-in for the New Architecture, we load the native entry point for this app. 41 | load() 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ExampleApp 3 | 4 | -------------------------------------------------------------------------------- /apps/example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /apps/example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "35.0.0" 4 | minSdkVersion = 24 5 | compileSdkVersion = 35 6 | targetSdkVersion = 34 7 | ndkVersion = "27.1.12297006" 8 | kotlinVersion = "2.0.21" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | } 19 | } 20 | 21 | apply plugin: "com.facebook.react.rootproject" 22 | -------------------------------------------------------------------------------- /apps/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: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 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 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | 25 | # Use this property to specify which architecture you want to build. 26 | # You can also override it from the CLI using 27 | # ./gradlew -PreactNativeArchitectures=x86_64 28 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 29 | 30 | # Use this property to enable support to the new architecture. 31 | # This will allow you to use TurboModules and the Fabric render in 32 | # your application. You should enable this flag either if you want 33 | # to write custom TurboModules/Fabric components OR use libraries that 34 | # are providing them. 35 | newArchEnabled=true 36 | 37 | # Use this property to enable or disable the Hermes JS engine. 38 | # If set to false, you will be using JSC instead. 39 | hermesEnabled=true 40 | -------------------------------------------------------------------------------- /apps/example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patlux/react-native-bluetooth-state-manager/4c8c472a8e2649f4571d192339e53dd9d0288708/apps/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /apps/example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /apps/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 https://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 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /apps/example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { includeBuild("../../node_modules/@react-native/gradle-plugin") } 2 | plugins { id("com.facebook.react.settings") } 3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } 4 | rootProject.name = 'ExampleApp' 5 | include ':app' 6 | includeBuild('../../node_modules/@react-native/gradle-plugin') -------------------------------------------------------------------------------- /apps/example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ExampleApp", 3 | "displayName": "ExampleApp" 4 | } 5 | -------------------------------------------------------------------------------- /apps/example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | } 4 | -------------------------------------------------------------------------------- /apps/example/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native' 2 | import App from './src/App' 3 | import { name as appName } from './app.json' 4 | 5 | AppRegistry.registerComponent(appName, () => App) 6 | -------------------------------------------------------------------------------- /apps/example/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /apps/example/ios/ExampleApp.xcodeproj/xcshareddata/xcschemes/ExampleApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /apps/example/ios/ExampleApp.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /apps/example/ios/ExampleApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import React 3 | import React_RCTAppDelegate 4 | import ReactAppDependencyProvider 5 | 6 | @main 7 | class AppDelegate: RCTAppDelegate { 8 | override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 9 | self.moduleName = "ExampleApp" 10 | self.dependencyProvider = RCTAppDependencyProvider() 11 | 12 | // You can add your custom initial props in the dictionary below. 13 | // They will be passed down to the ViewController used by React Native. 14 | self.initialProps = [:] 15 | 16 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 17 | } 18 | 19 | override func sourceURL(for bridge: RCTBridge) -> URL? { 20 | self.bundleURL() 21 | } 22 | 23 | override func bundleURL() -> URL? { 24 | #if DEBUG 25 | RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") 26 | #else 27 | Bundle.main.url(forResource: "main", withExtension: "jsbundle") 28 | #endif 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apps/example/ios/ExampleApp/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "iphone", 5 | "scale": "2x", 6 | "size": "20x20" 7 | }, 8 | { 9 | "idiom": "iphone", 10 | "scale": "3x", 11 | "size": "20x20" 12 | }, 13 | { 14 | "idiom": "iphone", 15 | "scale": "2x", 16 | "size": "29x29" 17 | }, 18 | { 19 | "idiom": "iphone", 20 | "scale": "3x", 21 | "size": "29x29" 22 | }, 23 | { 24 | "idiom": "iphone", 25 | "scale": "2x", 26 | "size": "40x40" 27 | }, 28 | { 29 | "idiom": "iphone", 30 | "scale": "3x", 31 | "size": "40x40" 32 | }, 33 | { 34 | "idiom": "iphone", 35 | "scale": "2x", 36 | "size": "60x60" 37 | }, 38 | { 39 | "idiom": "iphone", 40 | "scale": "3x", 41 | "size": "60x60" 42 | }, 43 | { 44 | "idiom": "ios-marketing", 45 | "scale": "1x", 46 | "size": "1024x1024" 47 | } 48 | ], 49 | "info": { 50 | "author": "xcode", 51 | "version": 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /apps/example/ios/ExampleApp/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "version": 1, 4 | "author": "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /apps/example/ios/ExampleApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ExampleApp 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 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSAllowsLocalNetworking 32 | 33 | 34 | NSLocationWhenInUseUsageDescription 35 | 36 | NSBluetoothAlwaysUsageDescription 37 | Because 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | arm64 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /apps/example/ios/ExampleApp/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /apps/example/ios/ExampleApp/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryUserDefaults 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | CA92.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryFileTimestamp 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | C617.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategorySystemBootTime 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | 35F9.1 29 | 30 | 31 | 32 | NSPrivacyCollectedDataTypes 33 | 34 | NSPrivacyTracking 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /apps/example/ios/Podfile: -------------------------------------------------------------------------------- 1 | j# Resolve react_native_pods.rb with node to allow for hoisting 2 | require Pod::Executable.execute_command('node', ['-p', 3 | 'require.resolve( 4 | "react-native/scripts/react_native_pods.rb", 5 | {paths: [process.argv[1]]}, 6 | )', __dir__]).strip 7 | 8 | platform :ios, min_ios_version_supported 9 | prepare_react_native_project! 10 | 11 | linkage = ENV['USE_FRAMEWORKS'] 12 | if linkage != nil 13 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 14 | use_frameworks! :linkage => linkage.to_sym 15 | end 16 | 17 | target 'ExampleApp' do 18 | config = use_native_modules! 19 | 20 | use_react_native!( 21 | :path => config[:reactNativePath], 22 | # An absolute path to your application root. 23 | :app_path => "#{Pod::Config.instance.installation_root}/.." 24 | ) 25 | 26 | post_install do |installer| 27 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 28 | react_native_post_install( 29 | installer, 30 | config[:reactNativePath], 31 | :mac_catalyst_enabled => false, 32 | # :ccache_enabled => true 33 | ) 34 | 35 | installer.pods_project.targets.each do |target| 36 | target.build_configurations.each do |config| 37 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.6' 38 | end 39 | end 40 | 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /apps/example/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config') 2 | const path = require('path') 3 | const root = path.resolve(__dirname, '..', '..') 4 | 5 | /** 6 | * Metro configuration 7 | * https://facebook.github.io/metro/docs/configuration 8 | * 9 | * @type {import('metro-config').MetroConfig} 10 | */ 11 | const config = { 12 | watchFolders: [root], 13 | } 14 | 15 | module.exports = mergeConfig(getDefaultConfig(__dirname), config) 16 | -------------------------------------------------------------------------------- /apps/example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-app", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios --simulator='iPhone 16'", 8 | "start": "react-native start --reset-cache", 9 | "pod": "pod install --project-directory=ios && cd ..", 10 | "lint": "TIMING=1 eslint .", 11 | "typecheck": "tsc --noEmit", 12 | "check-format": "prettier --check .", 13 | "format": "prettier --write ." 14 | }, 15 | "dependencies": { 16 | "@react-navigation/native": "^7.0.18", 17 | "@react-navigation/native-stack": "^7.3.2", 18 | "@tanstack/react-query": "^5.69.0", 19 | "react": "18.3.1", 20 | "react-native": "0.77.0", 21 | "react-native-nitro-modules": "0.25.2", 22 | "react-native-permissions": "^5.3.0", 23 | "react-native-safe-area-context": "^5.3.0", 24 | "react-native-screens": "^4.9.2", 25 | "react-native-bluetooth-state-manager": "*" 26 | }, 27 | "devDependencies": { 28 | "@babel/core": "^7.25.2", 29 | "@babel/preset-env": "^7.25.3", 30 | "@react-native-community/cli": "15.0.1", 31 | "@react-native-community/cli-platform-android": "15.0.1", 32 | "@react-native-community/cli-platform-ios": "15.0.1", 33 | "@react-native/babel-preset": "0.77.0", 34 | "@react-native/eslint-config": "0.77.0", 35 | "@react-native/metro-config": "0.77.0", 36 | "@react-native/typescript-config": "0.77.0", 37 | "@types/react": "^18.2.6", 38 | "eslint": "^8.19.0", 39 | "typescript": "*" 40 | }, 41 | "engines": { 42 | "node": ">=18" 43 | }, 44 | "prettier": { 45 | "singleQuote": true, 46 | "trailingComma": "all", 47 | "semi": false 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /apps/example/react-native.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const pkg = require('../../packages/react-native-bluetooth-state-manager/package.json') 3 | 4 | /** 5 | * @type {import('@react-native-community/cli-types').Config} 6 | */ 7 | module.exports = { 8 | dependencies: { 9 | [pkg.name]: { 10 | root: path.join( 11 | __dirname, 12 | '..', 13 | '..', 14 | 'packages', 15 | 'react-native-bluetooth-state-manager', 16 | ), 17 | }, 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /apps/example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { QueryClientProvider } from '@tanstack/react-query' 2 | import React from 'react' 3 | 4 | import { createStaticNavigation, DarkTheme } from '@react-navigation/native' 5 | import { createNativeStackNavigator } from '@react-navigation/native-stack' 6 | import { HomeScreen } from './HomeScreen' 7 | import { queryClient } from './queryClient' 8 | 9 | const RootStack = createNativeStackNavigator({ 10 | screens: { 11 | Home: HomeScreen, 12 | }, 13 | }) 14 | 15 | const Navigation = createStaticNavigation(RootStack) 16 | 17 | const App = () => { 18 | return ( 19 | 20 | 21 | 22 | ) 23 | } 24 | 25 | export default App 26 | -------------------------------------------------------------------------------- /apps/example/src/HomeScreen.tsx: -------------------------------------------------------------------------------- 1 | import { SafeAreaView } from 'react-native' 2 | import { useMutation } from '@tanstack/react-query' 3 | import React, { useEffect, useState } from 'react' 4 | import { Alert, Button, Platform, Text, View } from 'react-native' 5 | import { 6 | BluetoothStateManager, 7 | useBluetoothState, 8 | } from 'react-native-bluetooth-state-manager' 9 | import { useTheme } from '@react-navigation/native' 10 | import { Permissions } from './Permissions' 11 | 12 | export const HomeScreen = () => { 13 | return ( 14 | 21 | 22 | 23 | 24 | 25 | 26 | {Platform.OS === 'android' && ( 27 | 28 | 29 | 30 | 31 | 32 | )} 33 | 34 | ) 35 | } 36 | 37 | const Divider = () => { 38 | const { colors } = useTheme() 39 | return ( 40 | 49 | ) 50 | } 51 | 52 | const CurrentState = () => { 53 | const state = useBluetoothState() 54 | return State: {state} 55 | } 56 | 57 | const RequestToEnableBluetooth = () => { 58 | console.log('RequestToEnable()') 59 | const requestToEnableMutation = useMutation({ 60 | mutationFn: async () => { 61 | console.log('Start...') 62 | const result = await BluetoothStateManager.requestToEnable() 63 | console.log(`...end. Result = "${result}".`) 64 | return result 65 | }, 66 | onError: (error) => { 67 | console.error(error) 68 | Alert.alert('Error', `${error}`) 69 | }, 70 | onSuccess: () => { 71 | Alert.alert('Bluetooth enabled') 72 | }, 73 | }) 74 | 75 | return ( 76 |