├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .jscodeshiftignore ├── .travis.yml ├── .watchmanconfig ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── babel.config.js ├── build.gradle ├── gradle.properties ├── gradlew ├── index.js ├── lib └── android │ ├── android-react-native-scan-bluetooth.iml │ ├── android.iml │ ├── build.gradle │ ├── gradlew │ ├── gradlew.bat │ ├── local.properties │ └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── ula.kml │ ├── java │ └── com │ │ └── scan │ │ ├── AppConfig.java │ │ ├── AppConstants.java │ │ ├── AppScheduler.java │ │ ├── AppUtils.java │ │ ├── MapsPackage.java │ │ ├── ServiceTraceCovid.java │ │ ├── TraceCovidModule.java │ │ ├── TraceCovidModuleManager.java │ │ ├── TraceCovidPackage.java │ │ ├── apis │ │ └── AsyncStorageApi.java │ │ ├── bluezoneid │ │ ├── BluezoneDailyId.java │ │ ├── BluezoneDailyKey.java │ │ ├── BluezoneDate.java │ │ ├── BluezoneDateSubKey.java │ │ ├── BluezoneId.java │ │ ├── BluezoneIdConstants.java │ │ ├── BluezoneIdGenerator.java │ │ ├── BluezoneIdTrace.java │ │ └── BluezoneIdUtils.java │ │ ├── database │ │ ├── AppDatabaseHelper.java │ │ └── CacheDatabaseHelper.java │ │ ├── gatt │ │ └── GattConnectSession.java │ │ ├── model │ │ ├── CacheBleScan.java │ │ └── ScanConfig.java │ │ ├── notification │ │ └── NotificationReceiver.java │ │ └── preference │ │ ├── AbstractPreferenceManager.java │ │ └── AppPreferenceManager.java │ └── res │ ├── mipmap-hdpi │ └── icon_bluezone_service.png │ ├── mipmap-mdpi │ └── icon_bluezone_service.png │ ├── mipmap-xhdpi │ └── icon_bluezone_service.png │ ├── mipmap-xxhdpi │ └── icon_bluezone_service.png │ ├── mipmap-xxxhdpi │ └── icon_bluezone_service.png │ └── values │ ├── strings.xml │ └── styles.xml ├── local.properties ├── metro.config.js └── package.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "airbnb", 4 | "plugins": [ 5 | "prefer-object-spread" 6 | ], 7 | "rules": { 8 | "prefer-object-spread/prefer-object-spread": 2, 9 | "react/jsx-filename-extension": 0, 10 | "react/prefer-stateless-function": 0, 11 | "react/sort-comp": 0, 12 | "no-use-before-define": 0, 13 | "no-underscore-dangle": 0, 14 | "import/no-extraneous-dependencies": 0, 15 | "import/no-unresolved": [2, { "ignore": ["^react-native-maps"] }] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore unexpected extra "@providesModule" 9 | .*/node_modules/.*/node_modules/fbjs/.* 10 | 11 | ; Ignore duplicate module providers 12 | ; For RN Apps installed via npm, "Libraries" folder is inside 13 | ; "node_modules/react-native" but in the source repo it is in the root 14 | .*/Libraries/react-native/React.js 15 | 16 | ; Ignore polyfills 17 | .*/Libraries/polyfills/.* 18 | 19 | ; Ignore metro 20 | .*/node_modules/metro/.* 21 | 22 | [include] 23 | 24 | [libs] 25 | node_modules/react-native/Libraries/react-native/react-native-interface.js 26 | node_modules/react-native/flow/ 27 | 28 | [options] 29 | emoji=true 30 | 31 | esproposal.optional_chaining=enable 32 | esproposal.nullish_coalescing=enable 33 | 34 | module.system=haste 35 | module.system.haste.use_name_reducers=true 36 | # get basename 37 | module.system.haste.name_reducers='^.*/\([a-zA-Z0-9$_.-]+\.js\(\.flow\)?\)$' -> '\1' 38 | # strip .js or .js.flow suffix 39 | module.system.haste.name_reducers='^\(.*\)\.js\(\.flow\)?$' -> '\1' 40 | # strip .ios suffix 41 | module.system.haste.name_reducers='^\(.*\)\.ios$' -> '\1' 42 | module.system.haste.name_reducers='^\(.*\)\.android$' -> '\1' 43 | module.system.haste.name_reducers='^\(.*\)\.native$' -> '\1' 44 | module.system.haste.paths.blacklist=.*/__tests__/.* 45 | module.system.haste.paths.blacklist=.*/__mocks__/.* 46 | module.system.haste.paths.blacklist=/node_modules/react-native/Libraries/Animated/src/polyfills/.* 47 | module.system.haste.paths.whitelist=/node_modules/react-native/Libraries/.* 48 | 49 | munge_underscores=true 50 | 51 | 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' 52 | 53 | module.file_ext=.js 54 | module.file_ext=.jsx 55 | module.file_ext=.json 56 | module.file_ext=.native.js 57 | 58 | suppress_type=$FlowIssue 59 | suppress_type=$FlowFixMe 60 | suppress_type=$FlowFixMeProps 61 | suppress_type=$FlowFixMeState 62 | 63 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 64 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 65 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 66 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 67 | 68 | [version] 69 | ^0.92.0 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/xcode,linux,macos,reactnative,androidstudio 3 | # Edit at https://www.gitignore.io/?templates=xcode,linux,macos,reactnative,androidstudio 4 | 5 | ### Linux ### 6 | *~ 7 | 8 | # temporary files which can be created if a process still has a handle open of a deleted file 9 | .fuse_hidden* 10 | 11 | # KDE directory preferences 12 | .directory 13 | 14 | # Linux trash folder which might appear on any partition or disk 15 | .Trash-* 16 | 17 | # .nfs files are created when an open file is removed but is still being accessed 18 | .nfs* 19 | 20 | ### macOS ### 21 | # General 22 | .DS_Store 23 | .AppleDouble 24 | .LSOverride 25 | 26 | # Icon must end with two \r 27 | Icon 28 | 29 | # Thumbnails 30 | ._* 31 | 32 | # Files that might appear in the root of a volume 33 | .DocumentRevisions-V100 34 | .fseventsd 35 | .Spotlight-V100 36 | .TemporaryItems 37 | .Trashes 38 | .VolumeIcon.icns 39 | .com.apple.timemachine.donotpresent 40 | 41 | # Directories potentially created on remote AFP share 42 | .AppleDB 43 | .AppleDesktop 44 | Network Trash Folder 45 | Temporary Items 46 | .apdisk 47 | 48 | ### ReactNative ### 49 | # React Native Stack Base 50 | 51 | .expo 52 | __generated__ 53 | 54 | ### ReactNative.Android Stack ### 55 | # Built application files 56 | *.apk 57 | *.ap_ 58 | *.aab 59 | 60 | # Files for the ART/Dalvik VM 61 | *.dex 62 | 63 | # Java class files 64 | *.class 65 | 66 | # Generated files 67 | bin/ 68 | gen/ 69 | out/ 70 | release/ 71 | 72 | # Gradle files 73 | lib/android/gradle/ 74 | .gradle/ 75 | build/ 76 | 77 | # Local configuration file (sdk path, etc) 78 | local.properties 79 | 80 | # Proguard folder generated by Eclipse 81 | proguard/ 82 | 83 | # Log Files 84 | *.log 85 | 86 | # Android Studio Navigation editor temp files 87 | .navigation/ 88 | 89 | # Android Studio captures folder 90 | captures/ 91 | 92 | # IntelliJ 93 | *.iml 94 | .idea/ 95 | .idea/workspace.xml 96 | .idea/tasks.xml 97 | .idea/gradle.xml 98 | .idea/assetWizardSettings.xml 99 | .idea/dictionaries 100 | .idea/libraries 101 | # Android Studio 3 in .gitignore file. 102 | .idea/caches 103 | .idea/modules.xml 104 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 105 | .idea/navEditor.xml 106 | 107 | # Keystore files 108 | # Uncomment the following lines if you do not want to check your keystore files in. 109 | #*.jks 110 | #*.keystore 111 | 112 | # External native build folder generated in Android Studio 2.2 and later 113 | .externalNativeBuild 114 | 115 | # Google Services (e.g. APIs or Firebase) 116 | # google-services.json 117 | 118 | # Freeline 119 | freeline.py 120 | freeline/ 121 | freeline_project_description.json 122 | 123 | # fastlane 124 | fastlane/report.xml 125 | fastlane/Preview.html 126 | fastlane/screenshots 127 | fastlane/test_output 128 | fastlane/readme.md 129 | 130 | # Version control 131 | vcs.xml 132 | 133 | # lint 134 | lint/intermediates/ 135 | lint/generated/ 136 | lint/outputs/ 137 | lint/tmp/ 138 | # lint/reports/ 139 | 140 | ### ReactNative.Linux Stack ### 141 | 142 | # temporary files which can be created if a process still has a handle open of a deleted file 143 | 144 | # KDE directory preferences 145 | 146 | # Linux trash folder which might appear on any partition or disk 147 | 148 | # .nfs files are created when an open file is removed but is still being accessed 149 | 150 | ### ReactNative.Gradle Stack ### 151 | .gradle 152 | 153 | # Ignore Gradle GUI config 154 | gradle-app.setting 155 | 156 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 157 | !gradle-wrapper.jar 158 | 159 | # Cache of project 160 | .gradletasknamecache 161 | 162 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 163 | # gradle/wrapper/gradle-wrapper.properties 164 | 165 | ### ReactNative.Buck Stack ### 166 | buck-out/ 167 | .buckconfig.local 168 | .buckd/ 169 | .buckversion 170 | .fakebuckversion 171 | 172 | ### ReactNative.macOS Stack ### 173 | # General 174 | 175 | # Icon must end with two \r 176 | Icon 177 | 178 | 179 | # Thumbnails 180 | 181 | # Files that might appear in the root of a volume 182 | 183 | # Directories potentially created on remote AFP share 184 | 185 | ### ReactNative.Xcode Stack ### 186 | # Xcode 187 | # 188 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 189 | 190 | ## User settings 191 | xcuserdata/ 192 | 193 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 194 | *.xcscmblueprint 195 | *.xccheckout 196 | 197 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 198 | DerivedData/ 199 | *.moved-aside 200 | *.pbxuser 201 | !default.pbxuser 202 | *.mode1v3 203 | !default.mode1v3 204 | *.mode2v3 205 | !default.mode2v3 206 | *.perspectivev3 207 | !default.perspectivev3 208 | 209 | ## Xcode Patch 210 | *.xcodeproj/* 211 | !*.xcodeproj/project.pbxproj 212 | !*.xcodeproj/xcshareddata/ 213 | !*.xcworkspace/contents.xcworkspacedata 214 | /*.gcno 215 | 216 | ### ReactNative.Node Stack ### 217 | # Logs 218 | logs 219 | npm-debug.log* 220 | yarn-debug.log* 221 | yarn-error.log* 222 | lerna-debug.log* 223 | 224 | # Diagnostic reports (https://nodejs.org/api/report.html) 225 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 226 | 227 | # Runtime data 228 | pids 229 | *.pid 230 | *.seed 231 | *.pid.lock 232 | 233 | # Directory for instrumented libs generated by jscoverage/JSCover 234 | lib-cov 235 | 236 | # Coverage directory used by tools like istanbul 237 | coverage 238 | *.lcov 239 | 240 | # nyc test coverage 241 | .nyc_output 242 | 243 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 244 | .grunt 245 | 246 | # Bower dependency directory (https://bower.io/) 247 | bower_components 248 | 249 | # node-waf configuration 250 | .lock-wscript 251 | 252 | # Compiled binary addons (https://nodejs.org/api/addons.html) 253 | build/Release 254 | 255 | # Dependency directories 256 | node_modules/ 257 | jspm_packages/ 258 | 259 | # TypeScript v1 declaration files 260 | typings/ 261 | 262 | # TypeScript cache 263 | *.tsbuildinfo 264 | 265 | # Optional npm cache directory 266 | .npm 267 | 268 | # Optional eslint cache 269 | .eslintcache 270 | 271 | # Optional REPL history 272 | .node_repl_history 273 | 274 | # Output of 'npm pack' 275 | *.tgz 276 | 277 | # Yarn Integrity file 278 | .yarn-integrity 279 | 280 | # dotenv environment variables file 281 | .env 282 | .env.test 283 | 284 | # parcel-bundler cache (https://parceljs.org/) 285 | .cache 286 | 287 | # next.js build output 288 | .next 289 | 290 | # nuxt.js build output 291 | .nuxt 292 | 293 | # rollup.js default build output 294 | dist/ 295 | 296 | # Uncomment the public line if your project uses Gatsby 297 | # https://nextjs.org/blog/next-9-1#public-directory-support 298 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 299 | # public 300 | 301 | # Storybook build outputs 302 | .out 303 | .storybook-out 304 | 305 | # vuepress build output 306 | .vuepress/dist 307 | 308 | # Serverless directories 309 | .serverless/ 310 | 311 | # FuseBox cache 312 | .fusebox/ 313 | 314 | # DynamoDB Local files 315 | .dynamodb/ 316 | 317 | # Temporary folders 318 | tmp/ 319 | temp/ 320 | 321 | ### Xcode ### 322 | # Xcode 323 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 324 | 325 | 326 | 327 | 328 | 329 | ### Xcode Patch ### 330 | **/xcshareddata/WorkspaceSettings.xcsettings 331 | 332 | ### AndroidStudio ### 333 | # Covers files to be ignored for android development using Android Studio. 334 | 335 | # Built application files 336 | 337 | # Files for the ART/Dalvik VM 338 | 339 | # Java class files 340 | 341 | # Generated files 342 | 343 | # Gradle files 344 | 345 | # Signing files 346 | .signing/ 347 | 348 | # Local configuration file (sdk path, etc) 349 | 350 | # Proguard folder generated by Eclipse 351 | 352 | # Log Files 353 | 354 | # Android Studio 355 | /*/build/ 356 | /*/local.properties 357 | /*/out 358 | /*/*/build 359 | /*/*/production 360 | *.ipr 361 | *.swp 362 | 363 | # Android Patch 364 | gen-external-apklibs 365 | 366 | # External native build folder generated in Android Studio 2.2 and later 367 | 368 | # NDK 369 | obj/ 370 | 371 | # IntelliJ IDEA 372 | *.iws 373 | /out/ 374 | 375 | # User-specific configurations 376 | .idea/caches/ 377 | .idea/libraries/ 378 | .idea/shelf/ 379 | .idea/.name 380 | .idea/compiler.xml 381 | .idea/copyright/profiles_settings.xml 382 | .idea/encodings.xml 383 | .idea/misc.xml 384 | .idea/scopes/scope_settings.xml 385 | .idea/vcs.xml 386 | .idea/jsLibraryMappings.xml 387 | .idea/datasources.xml 388 | .idea/dataSources.ids 389 | .idea/sqlDataSources.xml 390 | .idea/dynamic.xml 391 | .idea/uiDesigner.xml 392 | 393 | # OS-specific files 394 | .DS_Store? 395 | ehthumbs.db 396 | Thumbs.db 397 | 398 | # Legacy Eclipse project files 399 | .classpath 400 | .project 401 | .cproject 402 | .settings/ 403 | 404 | # Mobile Tools for Java (J2ME) 405 | .mtj.tmp/ 406 | 407 | # Package Files # 408 | *.war 409 | *.ear 410 | 411 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) 412 | hs_err_pid* 413 | 414 | ## Plugin-specific files: 415 | 416 | # mpeltonen/sbt-idea plugin 417 | .idea_modules/ 418 | 419 | # JIRA plugin 420 | atlassian-ide-plugin.xml 421 | 422 | # Mongo Explorer plugin 423 | .idea/mongoSettings.xml 424 | 425 | # Crashlytics plugin (for Android Studio and IntelliJ) 426 | com_crashlytics_export_strings.xml 427 | crashlytics.properties 428 | crashlytics-build.properties 429 | fabric.properties 430 | 431 | ### AndroidStudio Patch ### 432 | 433 | !/gradle/wrapper/gradle-wrapper.jar 434 | 435 | # End of https://www.gitignore.io/api/xcode,linux,macos,reactnative,androidstudio 436 | -------------------------------------------------------------------------------- /.jscodeshiftignore: -------------------------------------------------------------------------------- 1 | # To run a codeshift on the react-native-maps library, cd to the root dir and run: 2 | # jscodeshift -t PATH_TO_TRANSFORM . --ignore-config .jscodeshiftignore 3 | .idea 4 | android 5 | docs 6 | example 7 | gradle 8 | node_modules 9 | scripts -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "lts/*" 5 | 6 | cache: 7 | directories: 8 | - node_modules 9 | 10 | script: npm run ci 11 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'cocoapods' 3 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.0) 5 | activesupport (4.2.11.1) 6 | i18n (~> 0.7) 7 | minitest (~> 5.1) 8 | thread_safe (~> 0.3, >= 0.3.4) 9 | tzinfo (~> 1.1) 10 | atomos (0.1.3) 11 | claide (1.0.2) 12 | cocoapods (1.6.1) 13 | activesupport (>= 4.0.2, < 5) 14 | claide (>= 1.0.2, < 2.0) 15 | cocoapods-core (= 1.6.1) 16 | cocoapods-deintegrate (>= 1.0.2, < 2.0) 17 | cocoapods-downloader (>= 1.2.2, < 2.0) 18 | cocoapods-plugins (>= 1.0.0, < 2.0) 19 | cocoapods-search (>= 1.0.0, < 2.0) 20 | cocoapods-stats (>= 1.0.0, < 2.0) 21 | cocoapods-trunk (>= 1.3.1, < 2.0) 22 | cocoapods-try (>= 1.1.0, < 2.0) 23 | colored2 (~> 3.1) 24 | escape (~> 0.0.4) 25 | fourflusher (>= 2.2.0, < 3.0) 26 | gh_inspector (~> 1.0) 27 | molinillo (~> 0.6.6) 28 | nap (~> 1.0) 29 | ruby-macho (~> 1.4) 30 | xcodeproj (>= 1.8.1, < 2.0) 31 | cocoapods-core (1.6.1) 32 | activesupport (>= 4.0.2, < 6) 33 | fuzzy_match (~> 2.0.4) 34 | nap (~> 1.0) 35 | cocoapods-deintegrate (1.0.4) 36 | cocoapods-downloader (1.2.2) 37 | cocoapods-plugins (1.0.0) 38 | nap 39 | cocoapods-search (1.0.0) 40 | cocoapods-stats (1.1.0) 41 | cocoapods-trunk (1.3.1) 42 | nap (>= 0.8, < 2.0) 43 | netrc (~> 0.11) 44 | cocoapods-try (1.1.0) 45 | colored2 (3.1.2) 46 | concurrent-ruby (1.1.5) 47 | escape (0.0.4) 48 | fourflusher (2.2.0) 49 | fuzzy_match (2.0.4) 50 | gh_inspector (1.1.3) 51 | i18n (0.9.5) 52 | concurrent-ruby (~> 1.0) 53 | minitest (5.11.3) 54 | molinillo (0.6.6) 55 | nanaimo (0.2.6) 56 | nap (1.1.0) 57 | netrc (0.11.0) 58 | ruby-macho (1.4.0) 59 | thread_safe (0.3.6) 60 | tzinfo (1.2.5) 61 | thread_safe (~> 0.1) 62 | xcodeproj (1.8.2) 63 | CFPropertyList (>= 2.3.3, < 4.0) 64 | atomos (~> 0.1.3) 65 | claide (>= 1.0.2, < 2.0) 66 | colored2 (~> 3.1) 67 | nanaimo (~> 0.2.6) 68 | 69 | PLATFORMS 70 | ruby 71 | 72 | DEPENDENCIES 73 | cocoapods 74 | 75 | BUNDLED WITH 76 | 1.17.2 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-bluetooth-scan 2 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | plugins: [ 4 | [ 5 | 'module-resolver', 6 | { 7 | alias: { 8 | 'react-native-maps': './', 9 | }, 10 | cwd: 'babelrc', 11 | }, 12 | ], 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | minSdkVersion = 16 4 | compileSdkVersion = 28 5 | targetSdkVersion = 28 6 | supportLibVersion = '28.0.0' 7 | playServicesVersion = '16.1.0' 8 | } 9 | repositories { 10 | google() 11 | jcenter() 12 | } 13 | dependencies { 14 | classpath 'com.android.tools.build:gradle:3.3.1' 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | mavenLocal() 21 | google() 22 | jcenter() 23 | maven { 24 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 25 | url "$rootDir/node_modules/react-native/android" 26 | } 27 | } 28 | } 29 | 30 | task clean(type: Delete) { 31 | delete rootProject.buildDir 32 | } 33 | -------------------------------------------------------------------------------- /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 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | VERSION_CODE=4 20 | VERSION_NAME=0.24.2 21 | GROUP=com.airbnb.android 22 | 23 | POM_DESCRIPTION=React Native Map view component for Android 24 | POM_URL=https://github.com/airbnb/react-native-maps/tree/new-scv 25 | POM_SCM_URL=https://github.com/airbnb/react-native-maps/tree/new-scv 26 | POM_SCM_CONNECTION=scm:git@github.com:airbnb/react-native-maps.git 27 | POM_SCM_DEV_CONNECTION=scm:git@github.com:airbnb/react-native-maps.git 28 | POM_LICENSE_NAME=MIT 29 | POM_LICENSE_URL=https://github.com/airbnb/react-native-maps/blob/master/LICENSE 30 | POM_LICENSE_DIST=repo 31 | POM_DEVELOPER_ID=airbnb 32 | POM_DEVELOPER_NAME=Leland Richardson 33 | 34 | POM_NAME=ReactNative Maps library 35 | POM_ARTIFACT_ID=react-native-maps 36 | POM_PACKAGING=aar 37 | -------------------------------------------------------------------------------- /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='"-Xmx64m"' 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 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // import MapView, { Animated, MAP_TYPES, ProviderPropType } from './lib/components/MapView'; 2 | // import Marker from './lib/components/MapMarker.js'; 3 | // import Overlay from './lib/components/MapOverlay.js'; 4 | import MapView, {MAP_TYPES} from './lib/components/VBDMapView.js'; 5 | import Marker from './lib/components/VBDMapMarker.js'; 6 | 7 | // export { default as Polyline } from './lib/components/MapPolyline.js'; 8 | // export { default as Polygon } from './lib/components/MapPolygon.js'; 9 | // export { default as Circle } from './lib/components/MapCircle.js'; 10 | // export { default as UrlTile } from './lib/components/MapUrlTile.js'; 11 | // export { default as LocalTile } from './lib/components/MapLocalTile.js'; 12 | // export { default as Callout } from './lib/components/MapCallout.js'; 13 | // export { default as CalloutSubview } from './lib/components/MapCalloutSubview.js'; 14 | // export { default as AnimatedRegion } from './lib/components/AnimatedRegion.js'; 15 | 16 | // import {NativeModules, requireNativeComponent} from 'react-native'; 17 | 18 | // export { Marker, Overlay }; 19 | // export { Animated, MAP_TYPES, ProviderPropType }; 20 | 21 | // export const PROVIDER_GOOGLE = MapView.PROVIDER_GOOGLE; 22 | // export const PROVIDER_DEFAULT = MapView.PROVIDER_DEFAULT; 23 | 24 | // export const MarkerAnimated = Marker.Animated; 25 | // export const OverlayAnimated = Overlay.Animated; 26 | 27 | export { 28 | Marker, 29 | MAP_TYPES, 30 | }; 31 | 32 | export default MapView; 33 | -------------------------------------------------------------------------------- /lib/android/android-react-native-scan-bluetooth.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /lib/android/android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | if (project.hasProperty('POM_ARTIFACT_ID')) { 3 | apply from: 'gradle-maven-push.gradle' 4 | } 5 | 6 | def safeExtGet(prop, fallback) { 7 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 8 | } 9 | 10 | android { 11 | compileSdkVersion safeExtGet('compileSdkVersion', 28) 12 | 13 | defaultConfig { 14 | minSdkVersion safeExtGet('minSdkVersion', 21) 15 | targetSdkVersion safeExtGet('targetSdkVersion', 27) 16 | } 17 | } 18 | 19 | dependencies { 20 | compileOnly('com.facebook.react:react-native:+') { 21 | exclude group: 'com.android.support' 22 | } 23 | implementation "androidx.appcompat:appcompat:1.0.0" 24 | implementation 'com.android.support:multidex:1.0.1' 25 | implementation 'com.jakewharton.timber:timber:4.5.1' 26 | implementation 'com.squareup.okhttp3:okhttp:3.12.1' 27 | implementation 'com.google.code.gson:gson:2.7' 28 | } 29 | -------------------------------------------------------------------------------- /lib/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 | -------------------------------------------------------------------------------- /lib/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 | -------------------------------------------------------------------------------- /lib/android/local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Tue Apr 21 16:49:13 ICT 2020 8 | sdk.dir=/home/cuongnt/Android/Sdk 9 | -------------------------------------------------------------------------------- /lib/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.scan; 2 | 3 | import android.content.Context; 4 | 5 | import com.scan.bluezoneid.BluezoneIdGenerator; 6 | import com.scan.preference.AppPreferenceManager; 7 | 8 | public class AppConfig { 9 | public static void setConfigs( 10 | Context context, 11 | long timeScanBle, 12 | long timeSleepScanBle, 13 | long timeBroadcast, 14 | long timeSleepBroadcast, 15 | long timeScanDevices, 16 | long timeSleepScanDevices, 17 | long timeSaveLog, 18 | long dbMaxRow, 19 | long dbMaxDay, 20 | long timeBackup, 21 | long timeIntervalEnableBluetooth, 22 | int batteryLevelEnableBluetooth, 23 | long intervalRequestPermisson, 24 | int maxNumberSubKey 25 | ) { 26 | AppPreferenceManager preferenceManager = AppPreferenceManager.getInstance(context); 27 | 28 | if (timeBroadcast > -1) { 29 | preferenceManager.setConfigBroadcastBleDuration(timeBroadcast); 30 | } 31 | 32 | if (timeSleepBroadcast > -1) { 33 | preferenceManager.setConfigBroadcastBleInterval(timeSleepBroadcast); 34 | } 35 | 36 | if (timeScanBle > -1) { 37 | preferenceManager.setConfigScanBleDuration(timeScanBle); 38 | } 39 | 40 | if (timeSleepScanBle > -1) { 41 | preferenceManager.setConfigScanBleInterval(timeSleepScanBle); 42 | } 43 | 44 | if (timeScanDevices > -1) { 45 | preferenceManager.setConfigScanDevicesDuration(timeScanDevices); 46 | } 47 | 48 | if (timeSleepScanDevices > -1) { 49 | preferenceManager.setConfigScanDevicesInterval(timeSleepScanDevices); 50 | } 51 | 52 | if (timeSaveLog > -1) { 53 | preferenceManager.setConfigInsertDb(timeSaveLog); 54 | } 55 | 56 | if (dbMaxRow > -1) { 57 | AppConstants.Config.DATABASE_MAX_ROW = dbMaxRow; 58 | } 59 | 60 | if (dbMaxDay > -1) { 61 | AppConstants.Config.DATABASE_MAX_DAY = dbMaxDay; 62 | } 63 | 64 | if (timeBackup > 60 * 1000) { 65 | preferenceManager.setConfigBackupDb(timeBackup); 66 | } 67 | 68 | if (timeIntervalEnableBluetooth > -1) { 69 | preferenceManager.setConfigEnableBluetoothInterval(timeIntervalEnableBluetooth); 70 | } 71 | 72 | // Auto anable bluetooth 73 | if (batteryLevelEnableBluetooth > -1) { 74 | preferenceManager.setConfigEnableBluetoothBatteryLevel(batteryLevelEnableBluetooth); 75 | } 76 | 77 | if (batteryLevelEnableBluetooth > 10 * 1000) { 78 | preferenceManager.setConfigCheckIntervalRequestPermission(intervalRequestPermisson); 79 | } 80 | 81 | if(maxNumberSubKey > 0) { 82 | BluezoneIdGenerator.getInstance(context).setMaxNumberSubKey(maxNumberSubKey); 83 | } 84 | } 85 | 86 | public static void setNotifyRequestBluContent( 87 | Context context, 88 | String itemRepeat, 89 | String bigTextVi, 90 | String bigTextEn, 91 | String subTextVi, 92 | String subTextEn, 93 | String titleVi, 94 | String titleEn, 95 | String messageVi, 96 | String messageEn 97 | ) { 98 | AppPreferenceManager preferenceManager = AppPreferenceManager.getInstance(context); 99 | preferenceManager.setNotifyRequestBlu( 100 | bigTextVi, 101 | bigTextEn, 102 | subTextVi, 103 | subTextEn, 104 | titleVi, 105 | titleEn, 106 | messageVi, 107 | messageEn, 108 | itemRepeat 109 | ); 110 | } 111 | 112 | public static void setNotifyRequestLocationContent( 113 | Context context, 114 | String itemRepeat, 115 | String bigTextVi, 116 | String bigTextEn, 117 | String subTextVi, 118 | String subTextEn, 119 | String titleVi, 120 | String titleEn, 121 | String messageVi, 122 | String messageEn 123 | ) { 124 | AppPreferenceManager preferenceManager = AppPreferenceManager.getInstance(context); 125 | preferenceManager.setNotifyRequestLocation( 126 | bigTextVi, 127 | bigTextEn, 128 | subTextVi, 129 | subTextEn, 130 | titleVi, 131 | titleEn, 132 | messageVi, 133 | messageEn, 134 | itemRepeat 135 | ); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/AppConstants.java: -------------------------------------------------------------------------------- 1 | package com.scan; 2 | 3 | /** 4 | * @author khanhxu 5 | */ 6 | public class AppConstants { 7 | // Constant pre 8 | public static class Config { 9 | 10 | // File name config 11 | public static final String CONFIG_FILE_NAME = "bluezone_config.txt"; 12 | 13 | // Index key, duration, interval 14 | public static final int CONFIG_FILE_INDEX_KEY = 0; 15 | public static final int CONFIG_FILE_INDEX_VALUE = 1; 16 | public static final int CONFIG_FILE_INDEX_DURATION = 1; 17 | public static final int CONFIG_FILE_INDEX_INTERVAL = 2; 18 | 19 | // Count 20 | public static final int CONFIG_FILE_DEFAULT_COUNT = 2; 21 | public static final int CONFIG_FILE_SCAN_COUNT = 3; 22 | 23 | // Value config 24 | public static final String CONFIG_FILE_VALUE_NOT = "0"; 25 | public static final String CONFIG_FILE_VALUE_OK = "1"; 26 | 27 | // Config log file 28 | public static final boolean IS_CONFIG_LOG_FILE = false; 29 | 30 | // Config log battery 31 | public static final boolean IS_CONFIG_LOG_BATTERY = false; 32 | 33 | // Config Scan Devices 34 | public static final boolean IS_CONFIG_SCAN_DEVICES = false; 35 | 36 | // Default 37 | public static final long DEFAULT_BROADCAST_BLE_DURATION = 15 * 1000; 38 | public static final long DEFAULT_BROADCAST_BLE_INTERVAL = 15 * 1000; 39 | public static final long DEFAULT_SCAN_BLE_DURATION = 40 * 1000; 40 | public static final long DEFAULT_SCAN_BLE_INTERVAL = 260 * 1000; 41 | public static final long DEFAULT_SCAN_DEVICES_DURATION = 40 * 1000; 42 | public static final long DEFAULT_SCAN_DEVICES_INTERVAL = 260 * 1000; 43 | public static final long DEFAULT_FULL_DURATION = (2 * 60 + 30) * 1000; 44 | public static final long DEFAULT_FULL_INTERVAL = 5 * 1000; 45 | public static final long DEFAULT_RESCAN_INTERVAL = 5 * 1000; 46 | 47 | // Enable Bluetooth level 48 | public static final int DEFAULT_ENABLE_BLUETTOOTH_BATTERY_LEVEL = 15; 49 | 50 | // Time interval enable bluetooth 51 | public static final long DEFAULT_ENABLE_BLUETTOOTH_INTERVAL = 5 * 60 * 1000; 52 | 53 | // Time insert 54 | public static final long TIME_DELAY_INSERT = 5 * 1000; 55 | // Time backup 56 | public static final long BACKUP_INTERVAL = 1 * 60 * 60 * 1000; 57 | 58 | // Timmer check permisson to create notification 59 | public static final long DEFAULT_INTERVAL_CHECK_PERMISSON = 2 * 60 * 1000; 60 | 61 | // Timeout connect 62 | public static final long TIMEOUT_CONNECT = 10 * 1000; 63 | 64 | // Time delay report scan 65 | public static final long TIME_SCAN_BLE_REPORT_DELAY = 10 * 1000; 66 | 67 | // ?? 68 | public static long DATABASE_MAX_ROW = 100000; 69 | public static long DATABASE_MAX_DAY = 100000; 70 | 71 | } 72 | 73 | // UUID Cần phát và bắt 74 | public static final String BLUEZONE_UUID = "4E56"; // VN 75 | public static final int BLE_ID = 8885; // XU 76 | public static final String BLE_UUID_IOS = "0000" + BLUEZONE_UUID + "-73F5-4BC4-A12F-17D1AD07A667"; 77 | public static final String BLE_UUID_ANDROID = "0000" + BLUEZONE_UUID + "-0000-1000-8000-00805F9B34FB"; 78 | public static final String BLE_UUID_CHARECTIC = "0000" + BLUEZONE_UUID + "-73F5-4BC4-A12F-17D1AD07A689"; 79 | public static final int DEFAUT_MANUFACTOR_IOS = 0x004c; 80 | public static final byte[] DEFAUT_MANUFACTOR_BYTE_IOS_X = new byte[] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0}; 81 | public static final byte[] DEFAUT_MANUFACTOR_BYTE_IOS = new byte[] {1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 82 | public static final byte[] BLUEZONE_BYTE_NONE = new byte[] {0}; 83 | 84 | // Notification 85 | public static final String NOTIFICATION_CHANNEL_ID = "BluezoneChannel"; 86 | public static final String NOTIFICATION_CHANNEL_NAME = "Bluezone channel"; 87 | public static final int NOTIFICATION_CHANNEL_ID_CODE = 42020; 88 | public static final int NOTIFICATION_SERVICE_BLUE_ZONE_ID = 2020; 89 | 90 | // File 91 | public static final String PATH_APP = "/Bluezone/"; 92 | public static final String LOG_FILE_NAME = "log.txt"; 93 | public static final String LOG_FILE_NAME_BATTERY = "log_battery.txt"; 94 | 95 | // UerID length 96 | public static final int USERID_LENGTH = 6; 97 | 98 | // PlatfromName 99 | public static final String PLATFORM_ANDROID = "Android"; 100 | public static final String PLATFORM_IOS = "iOS"; 101 | 102 | // Backup 103 | public static class Backup { 104 | public static final String ROOT_FOLDER = "backup"; 105 | public static final String DATABASE_NAME = "app_db.db"; // File name DB trong điện thoại 106 | public static final String FILE_NAME_DB = ".app_backup.db"; // File name DB ngoài thẻ nhớ 107 | public static final String FILE_NAME_USER_ID = ".userid.txt"; // File name backup UserID 108 | public static final String FILE_NAME_DATA = "data_trace.txt"; // Data trace put server 109 | public static final String KEY_USER_ID = "user_id"; // Key backup UserID 110 | public static final int DATA_USER_ID_COUNT = 2; 111 | public static final int DATA_USER_ID_INDEX_KEY = 0; 112 | public static final int DATA_USER_ID_INDEX_VALUE = 1; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/AppScheduler.java: -------------------------------------------------------------------------------- 1 | package com.scan; 2 | 3 | import android.app.AlarmManager; 4 | import android.app.PendingIntent; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.os.Build; 8 | 9 | public class AppScheduler { 10 | 11 | /** 12 | * Dat lich 13 | * @param context 14 | * @param intentAlarm 15 | * @param requestCode 16 | * @param intervalMillis 17 | */ 18 | public static void schedule(Context context, Intent intentAlarm, int requestCode, long intervalMillis) { 19 | 20 | // Pending 21 | PendingIntent pendingIntent = PendingIntent.getService(context, requestCode, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT); 22 | 23 | // Tao Alarm 24 | AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 25 | 26 | // Time 27 | long time = System.currentTimeMillis() + intervalMillis; 28 | 29 | if (Build.VERSION.SDK_INT >= 23) { 30 | // Schedule 31 | alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pendingIntent); 32 | } else if (Build.VERSION.SDK_INT >= 19) { 33 | // Schedule 34 | alarmManager.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent); 35 | } else { 36 | // Schedule 37 | alarmManager.set(AlarmManager.RTC_WAKEUP, time, pendingIntent); 38 | } 39 | } 40 | 41 | /** 42 | * Dat lich vong lap, min cua moi vong lap la 60s 43 | * @param context 44 | * @param intentAlarm 45 | * @param requestCode 46 | * @param intervalMillis 47 | */ 48 | public static void scheduleRepeating(Context context, Intent intentAlarm, int requestCode, long intervalMillis) { 49 | // Pending 50 | PendingIntent pendingIntent = PendingIntent.getService(context, requestCode, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT); 51 | 52 | // Tao Alarm 53 | AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 54 | alarmManager.cancel(pendingIntent); 55 | 56 | // Time 57 | long time = System.currentTimeMillis(); 58 | 59 | // Schedule 60 | alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time, intervalMillis, pendingIntent); 61 | } 62 | 63 | /** 64 | * Huy dat lich 65 | * @param context 66 | * @param intentAlarm 67 | * @param requestCode 68 | */ 69 | public static void cancelScheduler(Context context, Intent intentAlarm, int requestCode) { 70 | PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT); 71 | 72 | // Tao va cancel lich 73 | AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 74 | alarmManager.cancel(pendingIntent); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/MapsPackage.java: -------------------------------------------------------------------------------- 1 | package com.scan; 2 | 3 | import android.app.Activity; 4 | 5 | import com.facebook.react.ReactPackage; 6 | import com.facebook.react.bridge.JavaScriptModule; 7 | import com.facebook.react.bridge.NativeModule; 8 | import com.facebook.react.bridge.ReactApplicationContext; 9 | import com.facebook.react.uimanager.ViewManager; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | public class MapsPackage implements ReactPackage { 17 | public MapsPackage(Activity activity) { 18 | } // backwards compatibility 19 | 20 | public MapsPackage() { 21 | } 22 | 23 | @Override 24 | public List createNativeModules(ReactApplicationContext reactContext) { 25 | return Arrays.asList(); 26 | } 27 | 28 | // Deprecated RN 0.47 29 | public List> createJSModules() { 30 | return Collections.emptyList(); 31 | } 32 | 33 | @Override 34 | public List createViewManagers(ReactApplicationContext reactContext) { 35 | return Arrays.asList(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/TraceCovidModule.java: -------------------------------------------------------------------------------- 1 | package com.scan; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | 6 | import com.facebook.react.bridge.Callback; 7 | import com.facebook.react.bridge.Promise; 8 | import com.facebook.react.bridge.ReactApplicationContext; 9 | import com.facebook.react.bridge.ReactContext; 10 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 11 | import com.facebook.react.bridge.ReactMethod; 12 | import com.facebook.react.bridge.ReadableMap; 13 | import com.facebook.react.modules.core.DeviceEventManagerModule; 14 | import com.facebook.react.uimanager.IllegalViewOperationException; 15 | import com.scan.bluezoneid.BluezoneIdTrace; 16 | import com.scan.bluezoneid.BluezoneIdUtils; 17 | import com.scan.preference.AppPreferenceManager; 18 | 19 | import org.json.JSONException; 20 | 21 | public class TraceCovidModule extends ReactContextBaseJavaModule { 22 | private static ReactApplicationContext reactContext; 23 | private Callback onScanResult; 24 | private TraceCovidModuleManager manager; 25 | @NonNull 26 | @Override 27 | public String getName() { 28 | return "TraceCovid"; 29 | } 30 | 31 | public TraceCovidModule(ReactApplicationContext context) { 32 | super(context); 33 | reactContext = context; 34 | ServiceTraceCovid.reactContext = context; 35 | this.manager = new TraceCovidModuleManager(context, this); 36 | } 37 | 38 | @ReactMethod 39 | public void startService(boolean scanFull) throws JSONException { 40 | this.manager.startService(scanFull); 41 | } 42 | 43 | // @ReactMethod 44 | // public void setConfig(ReadableMap configs, Callback callback) { 45 | // try { 46 | // this.manager.setConfig(configs); 47 | // callback.invoke(true); 48 | // } catch (Exception e) { 49 | // callback.invoke(false); 50 | // } 51 | // } 52 | 53 | @ReactMethod 54 | public void setConfig(ReadableMap configs) { 55 | this.manager.setConfig(configs); 56 | } 57 | 58 | // @ReactMethod 59 | // public void getConfig(Promise promise) { 60 | // promise.resolve(this.manager.getConfig()); 61 | // } 62 | 63 | // @ReactMethod 64 | // public void stopService() { 65 | // this.manager.stopService(); 66 | // } 67 | 68 | // @ReactMethod 69 | // public void setId(String id, Callback callback) { 70 | // try { 71 | // AppPreferenceManager.getInstance(reactContext).setPhoneNumber(id); 72 | // callback.invoke(true); 73 | // } catch (Exception e) { 74 | // callback.invoke(false); 75 | // } 76 | // } 77 | @ReactMethod 78 | public void setLanguage(String language) { 79 | this.manager.setLanguage(language); 80 | } 81 | 82 | @ReactMethod 83 | public void setId(String id) { 84 | AppPreferenceManager.getInstance(reactContext).setBlid(id); 85 | } 86 | 87 | @ReactMethod 88 | public void checkContactF(String data, Promise promise) { 89 | try { 90 | promise.resolve(BluezoneIdTrace.isContactF(reactContext, data)); 91 | } catch (IllegalViewOperationException e) { 92 | promise.reject("Error", "An error occurred"); 93 | } 94 | } 95 | 96 | @ReactMethod 97 | public void getBluezoneIdInfo(int dayStartTrace, Promise promise) { 98 | try { 99 | String uri = BluezoneIdTrace.getBluezoneIdInfo(reactContext, dayStartTrace); 100 | promise.resolve(uri); 101 | } catch (IllegalViewOperationException e) { 102 | promise.reject("Error", "An error occurred"); 103 | } 104 | } 105 | 106 | @ReactMethod 107 | public void writeHistoryContact(int dayStartTrace, Promise promise) { 108 | try { 109 | String uri = BluezoneIdTrace.exportTraceData(reactContext, dayStartTrace); 110 | promise.resolve(uri); 111 | } catch (IllegalViewOperationException e) { 112 | promise.reject("Error", "An error occurred"); 113 | } 114 | } 115 | 116 | @ReactMethod 117 | public void getBluezoneId(Promise promise) { 118 | String bzId = BluezoneIdUtils.getHexBluezoneId(reactContext); 119 | promise.resolve(bzId); 120 | } 121 | 122 | @ReactMethod 123 | public void setContentNotify(String title, String content) { 124 | this.manager.setContentNotify(title, content); 125 | } 126 | 127 | public void emitEvent(String eventName, @Nullable Object data) { 128 | sendEvent(reactContext, eventName, data); 129 | } 130 | 131 | private void sendEvent(ReactContext reactContext, String eventName, @Nullable Object data) { 132 | reactContext 133 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) 134 | .emit(eventName, data); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/TraceCovidModuleManager.java: -------------------------------------------------------------------------------- 1 | package com.scan; 2 | 3 | import android.content.Intent; 4 | import android.os.Build; 5 | import android.util.Log; 6 | 7 | import com.facebook.react.bridge.Arguments; 8 | import com.facebook.react.bridge.ReactApplicationContext; 9 | import com.facebook.react.bridge.ReadableMap; 10 | import com.facebook.react.bridge.WritableMap; 11 | import com.scan.apis.AsyncStorageApi; 12 | import com.scan.preference.AppPreferenceManager; 13 | 14 | import org.json.JSONException; 15 | import org.json.JSONObject; 16 | 17 | import java.io.File; 18 | 19 | public class TraceCovidModuleManager { 20 | public ReactApplicationContext reactContext; 21 | public TraceCovidModule traceCovidModule; 22 | public AsyncStorageApi storageApi; 23 | 24 | public TraceCovidModuleManager(ReactApplicationContext reactContext, TraceCovidModule traceCovidModule) { 25 | this.reactContext = reactContext; 26 | this.traceCovidModule = traceCovidModule; 27 | ServiceTraceCovid.moduleManager = this; 28 | storageApi = new AsyncStorageApi(reactContext); 29 | } 30 | 31 | public void startService(boolean scanFull) throws JSONException { 32 | Intent intent = new Intent(reactContext, ServiceTraceCovid.class); 33 | Log.e("Scan Full: ", scanFull ? "true" : "false"); 34 | 35 | intent.putExtra(ServiceTraceCovid.EXTRA_SCHEDULER_TYPE, scanFull ? ServiceTraceCovid.TYPE_SCAN_FULL : ServiceTraceCovid.TYPE_APP_EXIT); 36 | // intent.putExtra("language", language); 37 | 38 | // File dir = reactContext.getDatabasePath("app_db.db"); 39 | 40 | // Đọc Config trong asyncConfig 41 | this.setConfigFromAsyncStorege(); 42 | 43 | // Start service 44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ 45 | reactContext.startForegroundService(intent); 46 | } else { 47 | reactContext.startService(intent); 48 | } 49 | } 50 | 51 | public void setConfigFromAsyncStorege() throws JSONException { 52 | String strConfig = storageApi.getItem("Configuration"); 53 | 54 | if(strConfig == null) { 55 | return; 56 | } 57 | 58 | try { 59 | JSONObject json = new JSONObject(strConfig); 60 | int timeScanBleRun = json.has("ScanBleRun") ? json.getInt("ScanBleRun") : -1; 61 | int timeScanBleSleep = json.has("ScanBleSleep") ? json.getInt("ScanBleSleep") : -1; 62 | int timeBroadcastBleRun = json.has("BroadcastBleRun") ? json.getInt("BroadcastBleRun") : -1; 63 | int timeBroadcastBleSleep = json.has("BroadcastBleSleep") ? json.getInt("BroadcastBleSleep") : -1; 64 | int timeScanDeviceRun = json.has("ScanDevicesRun") ? json.getInt("ScanDevicesRun") : -1; 65 | int timeScanDeviceSleep = json.has("ScanDevicesSleep") ? json.getInt("ScanDevicesSleep") : -1; 66 | int timeSaveLog = json.has("TimeSaveLog") ? json.getInt("TimeSaveLog") : -1; 67 | int dbMaxRow = json.has("DbMaxRow") ? json.getInt("DbMaxRow") : -1; 68 | int dbMaxDay = json.has("DbMaxDay") ? json.getInt("DbMaxDay") : -1; 69 | int timeBackup = json.has("TimeBackup") ? json.getInt("TimeBackup") : -1; 70 | 71 | int timeIntervalEnableBluetooth = json.has("TimeEnableBluetooth") ? json.getInt("TimeEnableBluetooth") : -1; 72 | int batteryLevelEnableBluetooth = json.has("BatteryEnableBluetooth") ? json.getInt("BatteryEnableBluetooth") : -1; 73 | int intervalRequestPermisson = json.has("IntervalRequestPermisson") ? json.getInt("IntervalRequestPermisson") : -1; 74 | int maxNumberSubKey = json.has("MaxNumberSubKeyPerDay") ? json.getInt("MaxNumberSubKeyPerDay") : -1; 75 | 76 | AppConfig.setConfigs( 77 | reactContext, 78 | timeScanBleRun, 79 | timeScanBleSleep, 80 | timeBroadcastBleRun, 81 | timeBroadcastBleSleep, 82 | timeScanDeviceRun, 83 | timeScanDeviceSleep, 84 | timeSaveLog, 85 | dbMaxRow, 86 | dbMaxDay, 87 | timeBackup, 88 | timeIntervalEnableBluetooth, 89 | batteryLevelEnableBluetooth, 90 | intervalRequestPermisson, 91 | maxNumberSubKey 92 | ); 93 | } 94 | catch (Exception e) { 95 | 96 | } 97 | } 98 | 99 | public void setConfig (ReadableMap configs) { 100 | int timeScanBleRun = configs.hasKey("ScanBleRun") ? configs.getInt("ScanBleRun") : -1; 101 | int timeScanBleSleep = configs.hasKey("ScanBleSleep") ? configs.getInt("ScanBleSleep") : -1; 102 | int timeBroadcastBleRun = configs.hasKey("BroadcastBleRun") ? configs.getInt("BroadcastBleRun") : -1; 103 | int timeBroadcastBleSleep = configs.hasKey("BroadcastBleSleep") ? configs.getInt("BroadcastBleSleep") : -1; 104 | int timeScanDeviceRun = configs.hasKey("ScanDevicesRun") ? configs.getInt("ScanDevicesRun") : -1; 105 | int timeScanDeviceSleep = configs.hasKey("ScanDevicesSleep") ? configs.getInt("ScanDevicesSleep") : -1; 106 | int timeSaveLog = configs.hasKey("TimeSaveLog") ? configs.getInt("TimeSaveLog") : -1; 107 | int dbMaxRow = configs.hasKey("DbMaxRow") ? configs.getInt("DbMaxRow") : -1; 108 | int dbMaxDay = configs.hasKey("DbMaxDay") ? configs.getInt("DbMaxDay") : -1; 109 | int timeBackup = configs.hasKey("TimeBackup") ? configs.getInt("TimeBackup") : -1; 110 | int timeIntervalEnableBluetooth = configs.hasKey("TimeEnableBluetooth") ? configs.getInt("TimeEnableBluetooth") : -1; 111 | int batteryLevelEnableBluetooth = configs.hasKey("BatteryEnableBluetooth") ? configs.getInt("BatteryEnableBluetooth") : -1; 112 | int intervalRequestPermisson = configs.hasKey("IntervalRequestPermisson") ? configs.getInt("IntervalRequestPermisson") : -1; 113 | int maxNumberSubKey = configs.hasKey("MaxNumberSubKeyPerDay") ? configs.getInt("MaxNumberSubKeyPerDay") : -1; 114 | AppConfig.setConfigs( 115 | reactContext, 116 | timeScanBleRun, 117 | timeScanBleSleep, 118 | timeBroadcastBleRun, 119 | timeBroadcastBleSleep, 120 | timeScanDeviceRun, 121 | timeScanDeviceSleep, 122 | timeSaveLog, 123 | dbMaxRow, 124 | dbMaxDay, 125 | timeBackup, 126 | timeIntervalEnableBluetooth, 127 | batteryLevelEnableBluetooth, 128 | intervalRequestPermisson, 129 | maxNumberSubKey 130 | ); 131 | 132 | ReadableMap notifyRequestBluetooth = configs.hasKey("NotificationRequestBluetooth") ? configs.getMap("NotificationRequestBluetooth") : null; 133 | if(notifyRequestBluetooth != null) { 134 | String itemRepeat = notifyRequestBluetooth.hasKey("itemRepeat") ? notifyRequestBluetooth.getArray("itemRepeat").toString() : ""; 135 | String bigTextVi = notifyRequestBluetooth.hasKey("bigText") ? notifyRequestBluetooth.getString("bigText") : ""; 136 | String bigTextEn = notifyRequestBluetooth.hasKey("bigText_en") ? notifyRequestBluetooth.getString("bigText_en") : ""; 137 | String subTextVi = notifyRequestBluetooth.hasKey("subText") ? notifyRequestBluetooth.getString("subText") : ""; 138 | String subTextEn = notifyRequestBluetooth.hasKey("subText_en") ? notifyRequestBluetooth.getString("subText_en") : ""; 139 | String titleVi = notifyRequestBluetooth.hasKey("title") ? notifyRequestBluetooth.getString("title") : ""; 140 | String titleEn = notifyRequestBluetooth.hasKey("title_en") ? notifyRequestBluetooth.getString("title_en") : ""; 141 | String messageVi = notifyRequestBluetooth.hasKey("message") ? notifyRequestBluetooth.getString("message") : ""; 142 | String messageEn = notifyRequestBluetooth.hasKey("message_en") ? notifyRequestBluetooth.getString("message_en") : ""; 143 | AppConfig.setNotifyRequestBluContent(reactContext, itemRepeat, bigTextVi, bigTextEn, subTextVi, subTextEn, titleVi, titleEn, messageVi, messageEn); 144 | } 145 | 146 | ReadableMap notifyRequestLocation = configs.hasKey("NotificationRequestLocation") ? configs.getMap("NotificationRequestLocation") : null; 147 | if(notifyRequestLocation != null) { 148 | String itemRepeat = notifyRequestLocation.hasKey("itemRepeat") ? notifyRequestLocation.getArray("itemRepeat").toString() : ""; 149 | String bigTextVi = notifyRequestLocation.hasKey("bigText") ? notifyRequestLocation.getString("bigText") : ""; 150 | String bigTextEn = notifyRequestLocation.hasKey("bigText_en") ? notifyRequestLocation.getString("bigText_en") : ""; 151 | String subTextVi = notifyRequestLocation.hasKey("subText") ? notifyRequestLocation.getString("subText") : ""; 152 | String subTextEn = notifyRequestLocation.hasKey("subText_en") ? notifyRequestLocation.getString("subText_en") : ""; 153 | String titleVi = notifyRequestLocation.hasKey("title") ? notifyRequestLocation.getString("title") : ""; 154 | String titleEn = notifyRequestLocation.hasKey("title_en") ? notifyRequestLocation.getString("title_en") : ""; 155 | String messageVi = notifyRequestLocation.hasKey("message") ? notifyRequestLocation.getString("message") : ""; 156 | String messageEn = notifyRequestLocation.hasKey("message_en") ? notifyRequestLocation.getString("message_en") : ""; 157 | AppConfig.setNotifyRequestLocationContent(reactContext, itemRepeat, bigTextVi, bigTextEn, subTextVi, subTextEn, titleVi, titleEn, messageVi, messageEn); 158 | } 159 | 160 | ReadableMap notifyRequestPermisson = configs.hasKey("NotificationRequestPermissonAndroid") ? configs.getMap("NotificationRequestPermissonAndroid") : null; 161 | if(notifyRequestLocation != null) { 162 | String itemRepeat = notifyRequestPermisson.hasKey("itemRepeat") ? notifyRequestPermisson.getArray("itemRepeat").toString() : ""; 163 | String bigTextVi = notifyRequestPermisson.hasKey("bigText") ? notifyRequestPermisson.getString("bigText") : ""; 164 | String bigTextEn = notifyRequestPermisson.hasKey("bigText_en") ? notifyRequestPermisson.getString("bigText_en") : ""; 165 | String subTextVi = notifyRequestPermisson.hasKey("subText") ? notifyRequestPermisson.getString("subText") : ""; 166 | String subTextEn = notifyRequestPermisson.hasKey("subText_en") ? notifyRequestPermisson.getString("subText_en") : ""; 167 | String titleVi = notifyRequestPermisson.hasKey("title") ? notifyRequestPermisson.getString("title") : ""; 168 | String titleEn = notifyRequestPermisson.hasKey("title_en") ? notifyRequestPermisson.getString("title_en") : ""; 169 | String messageVi = notifyRequestPermisson.hasKey("message") ? notifyRequestPermisson.getString("message") : ""; 170 | String messageEn = notifyRequestPermisson.hasKey("message_en") ? notifyRequestPermisson.getString("message_en") : ""; 171 | 172 | AppPreferenceManager preferenceManager = AppPreferenceManager.getInstance(reactContext); 173 | preferenceManager.setNotifyRequestPermisson( 174 | bigTextVi, 175 | bigTextEn, 176 | subTextVi, 177 | subTextEn, 178 | titleVi, 179 | titleEn, 180 | messageVi, 181 | messageEn, 182 | itemRepeat 183 | ); 184 | } 185 | } 186 | 187 | // public WritableMap getConfig () { 188 | // WritableMap config = new WritableNativeMap(); 189 | // config.putInt("timeScanBleRun", (int)AppConfig.TIME_SCAN_BLE); 190 | // config.putInt("timeScanBleSleep", (int)AppConfig.TIME_SLEEP_SCAN_BLE); 191 | // config.putInt("timeBroadcastBleRun", (int)AppConfig.TIME_BROADCAST_BLE); 192 | // config.putInt("timeBroadcastBleSleep", (int)AppConfig.TIME_SLEEP_BROADCAST_BLE); 193 | // config.putInt("timeScanDevicesRun", (int)AppConfig.TIME_SCAN_DEVICES); 194 | // config.putInt("timeScanDevicesSleep", (int)AppConfig.TIME_SLEEP_SCAN_DEVICES); 195 | // config.putInt("timeSaveLog", (int)AppConfig.TIME_SAVE_LOG); 196 | // return config; 197 | // } 198 | 199 | // public void stopService() { 200 | // // Start broadcast tắt service 201 | // try { 202 | // Intent broadCastIntent = new Intent(); 203 | // broadCastIntent.setAction(ServiceTraceCovid.ACTION_RECEIVER_STOP); 204 | // reactContext.sendBroadcast(broadCastIntent); 205 | // Toast.makeText(reactContext, "Stop Service Success", Toast.LENGTH_LONG).show(); 206 | // } catch (Exception e) { 207 | // e.printStackTrace(); 208 | // } 209 | // } 210 | 211 | public void emit(String id, String name, String address, int rssi, String platform, int type) { 212 | WritableMap params = Arguments.createMap(); 213 | params.putString("id", id); 214 | params.putString("name", name); 215 | params.putString("address", address); 216 | params.putInt("rssi", rssi); 217 | params.putString("platform", platform); 218 | params.putInt("typeScan", type); 219 | traceCovidModule.emitEvent("onScanResult", params); 220 | } 221 | 222 | public void emitBlueTooth(String id, String name, String address, int rssi, String platform, int type) { 223 | WritableMap params = Arguments.createMap(); 224 | params.putString("id", id); 225 | params.putString("name", name); 226 | params.putString("address", address); 227 | params.putInt("rssi", rssi); 228 | params.putString("platform", platform); 229 | params.putInt("typeScan", type); 230 | traceCovidModule.emitEvent("onScanBlueToothResult", params); 231 | } 232 | 233 | public void emitBluezoneIdChange(String bluezoneId) { 234 | traceCovidModule.emitEvent("onBluezoneIdChange", bluezoneId); 235 | } 236 | 237 | public void setLanguage(String language) { 238 | AppPreferenceManager.getInstance(reactContext).setLanguage(language); 239 | AppUtils.changeLanguageNotification(reactContext, language); 240 | } 241 | 242 | public void setContentNotify(String title, String content) { 243 | AppUtils.changeNotification(reactContext, title, content); 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/TraceCovidPackage.java: -------------------------------------------------------------------------------- 1 | package com.scan; 2 | 3 | import android.app.Activity; 4 | import android.os.Build; 5 | 6 | import com.facebook.react.ReactPackage; 7 | import com.facebook.react.bridge.JavaScriptModule; 8 | import com.facebook.react.bridge.NativeModule; 9 | import com.facebook.react.bridge.ReactApplicationContext; 10 | import com.facebook.react.uimanager.ViewManager; 11 | 12 | import java.util.Arrays; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | import androidx.annotation.NonNull; 17 | 18 | public class TraceCovidPackage implements ReactPackage { 19 | public TraceCovidPackage(Activity activity) {} 20 | 21 | public TraceCovidPackage() { 22 | } 23 | 24 | @Override 25 | public List createNativeModules(ReactApplicationContext reactContext) { 26 | return Arrays.asList(new TraceCovidModule(reactContext)); 27 | } 28 | 29 | @NonNull 30 | @Override 31 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) { 32 | return Arrays.asList(); 33 | } 34 | 35 | // Deprecated RN 0.47 36 | public List> createJSModules() { 37 | return Collections.emptyList(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/apis/AsyncStorageApi.java: -------------------------------------------------------------------------------- 1 | package com.scan.apis; 2 | 3 | import android.content.ContentValues; 4 | import android.database.sqlite.SQLiteDatabase; 5 | 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.bridge.WritableArray; 8 | import com.facebook.react.bridge.WritableMap; 9 | import com.facebook.react.bridge.WritableNativeArray; 10 | import com.facebook.react.bridge.WritableNativeMap; 11 | import com.facebook.react.modules.storage.AsyncLocalStorageUtil; 12 | import com.facebook.react.modules.storage.ReactDatabaseSupplier; 13 | 14 | import org.json.JSONArray; 15 | import org.json.JSONException; 16 | import org.json.JSONObject; 17 | 18 | import java.util.Iterator; 19 | 20 | public class AsyncStorageApi { 21 | private ReactApplicationContext mContext; 22 | private final String TABLE_CATALYST = "catalystLocalStorage"; 23 | private final String KEY_COLUMN = "key"; 24 | private final String VALUE_COLUMN = "value"; 25 | 26 | public static JSONObject convertStringToJsonObject(String str) { 27 | if(str != null && str instanceof String) { 28 | try { 29 | return new JSONObject(str); 30 | } catch (Exception e) { 31 | return null; 32 | } 33 | } 34 | // TODO by Me: Exception? 35 | return null; 36 | } 37 | 38 | public static WritableArray convertJsonToArray(JSONArray jsonArray) throws JSONException { 39 | WritableArray array = new WritableNativeArray(); 40 | 41 | for (int i = 0; i < jsonArray.length(); i++) { 42 | Object value = jsonArray.get(i); 43 | if (value instanceof JSONObject) { 44 | array.pushMap(convertJsonToMap((JSONObject) value)); 45 | } else if (value instanceof JSONArray) { 46 | array.pushArray(convertJsonToArray((JSONArray) value)); 47 | } else if (value instanceof Boolean) { 48 | array.pushBoolean((Boolean) value); 49 | } else if (value instanceof Integer) { 50 | array.pushInt((Integer) value); 51 | } else if (value instanceof Double) { 52 | array.pushDouble((Double) value); 53 | } else if (value instanceof String) { 54 | array.pushString((String) value); 55 | } else { 56 | array.pushString(value.toString()); 57 | } 58 | } 59 | return array; 60 | } 61 | 62 | public static WritableMap convertJsonToMap(JSONObject jsonObject) throws JSONException { 63 | WritableMap map = new WritableNativeMap(); 64 | 65 | Iterator iterator = jsonObject.keys(); 66 | while (iterator.hasNext()) { 67 | String key = iterator.next(); 68 | Object value = jsonObject.get(key); 69 | if (value instanceof JSONObject) { 70 | map.putMap(key, convertJsonToMap((JSONObject) value)); 71 | } else if (value instanceof JSONArray) { 72 | map.putArray(key, convertJsonToArray((JSONArray) value)); 73 | } else if (value instanceof Boolean) { 74 | map.putBoolean(key, (Boolean) value); 75 | } else if (value instanceof Integer) { 76 | map.putInt(key, (Integer) value); 77 | } else if (value instanceof Double) { 78 | map.putDouble(key, (Double) value); 79 | } else if (value instanceof String) { 80 | map.putString(key, (String) value); 81 | } else { 82 | map.putString(key, value.toString()); 83 | } 84 | } 85 | return map; 86 | } 87 | 88 | public AsyncStorageApi(ReactApplicationContext _mContext) { 89 | mContext = _mContext; 90 | } 91 | 92 | public String getItem(String keyValue) throws JSONException { 93 | SQLiteDatabase db = ReactDatabaseSupplier.getInstance(mContext).getReadableDatabase(); 94 | if (db == null) { 95 | return null; 96 | } 97 | return AsyncLocalStorageUtil.getItemImpl(db, keyValue); 98 | } 99 | 100 | public void setItem(String key, String value) throws JSONException { 101 | SQLiteDatabase db = ReactDatabaseSupplier.getInstance(mContext).getReadableDatabase(); 102 | if (db == null) { 103 | return; 104 | } 105 | 106 | ContentValues contentValues = new ContentValues(); 107 | contentValues.put(KEY_COLUMN, key); 108 | contentValues.put(VALUE_COLUMN, value); 109 | 110 | db.insertWithOnConflict( 111 | TABLE_CATALYST, 112 | null, 113 | contentValues, 114 | SQLiteDatabase.CONFLICT_REPLACE 115 | ); 116 | } 117 | 118 | public void saveObject(JSONObject jsonObject, String stateKey) throws JSONException { 119 | String states = getItem(stateKey); 120 | JSONObject data = convertStringToJsonObject(states); 121 | if (data != null) { 122 | Iterator keys = jsonObject.keys(); 123 | while (keys.hasNext()) { 124 | String key = keys.next(); 125 | JSONObject jsonNew = jsonObject.getJSONObject(key); 126 | 127 | data.put(key, jsonNew); 128 | } 129 | setItem(stateKey, data.toString()); 130 | } 131 | 132 | } 133 | 134 | public void saveEdges(JSONObject jsonObject, String stateKey) throws JSONException { 135 | String states = getItem(stateKey); 136 | JSONObject data = convertStringToJsonObject(states); 137 | System.out.println(data); 138 | if(data != null) { 139 | Iterator keys = jsonObject.keys(); 140 | while (keys.hasNext()) { 141 | String key = (String) keys.next(); 142 | JSONObject jsonNew = data.getJSONObject(key); 143 | JSONArray jsonArrayNew = jsonObject.getJSONObject(key).getJSONArray("itemIds"); 144 | String maxScore = jsonObject.getJSONObject(key).getString("maxScore"); 145 | JSONArray jsonArrayOld = data.getJSONObject(key).getJSONArray("itemIds"); 146 | for (int i = jsonArrayNew.length() - 1; i >=0; i--) { 147 | jsonArrayOld.put(0, jsonArrayNew.get(i)); 148 | } 149 | data.getJSONObject(key).put("minScore", maxScore); 150 | } 151 | setItem(stateKey, data.toString()); 152 | } 153 | 154 | System.out.println(data); 155 | } 156 | 157 | public void saveEdges(JSONObject jsonObject, String stateKey, String key1) throws JSONException { 158 | String states = getItem(stateKey); 159 | JSONObject data = convertStringToJsonObject(states); 160 | System.out.println(data); 161 | if(data != null) { 162 | Iterator keys = data.keys(); 163 | JSONArray jsonArrayNew = jsonObject.getJSONObject(key1).getJSONArray("itemIds"); 164 | String maxScore = jsonObject.getJSONObject(key1).getString("maxScore"); 165 | while (keys.hasNext()) { 166 | String key = (String) keys.next(); 167 | JSONArray jsonArrayOld = data.getJSONObject(key).getJSONArray("itemIds"); 168 | for (int i = jsonArrayNew.length() - 1; i >=0; i--) { 169 | jsonArrayOld.put(0, jsonArrayNew.get(i)); 170 | } 171 | data.getJSONObject(key).put("minScore", maxScore); 172 | } 173 | setItem(stateKey, data.toString()); 174 | } 175 | 176 | System.out.println(data); 177 | } 178 | } 179 | 180 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneDailyId.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | import android.util.Pair; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * @author khanhxu 9 | */ 10 | class BluezoneDailyId extends Pair, BluezoneDate> { 11 | 12 | /** 13 | * Constructor for a Pair. 14 | * 15 | * @param first the first object in the Pair 16 | * @param second the second object in the pair 17 | */ 18 | BluezoneDailyId(ArrayList first, BluezoneDate second) { 19 | super(first, second); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneDailyKey.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | import android.util.Pair; 4 | 5 | /** 6 | * @author khanhxu 7 | */ 8 | class BluezoneDailyKey extends Pair { 9 | 10 | /** 11 | * Constructor for a Pair. 12 | * 13 | * @param first the first object in the Pair 14 | * @param second the second object in the pair 15 | */ 16 | BluezoneDailyKey(byte[] first, BluezoneDate second) { 17 | super(first, second); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneDate.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | import java.util.Calendar; 4 | import java.util.GregorianCalendar; 5 | import java.util.TimeZone; 6 | 7 | /** 8 | * Convert time to UTC 9 | * @author khanhxu 10 | */ 11 | class BluezoneDate { 12 | 13 | private long mTime; 14 | 15 | /** 16 | * Init 17 | * @param time 18 | */ 19 | BluezoneDate(long time) { 20 | mTime = convertTimeZoneUtc(time); 21 | } 22 | 23 | /** 24 | * Convert Time Zone UTC 25 | * @param time 26 | * @return 27 | */ 28 | private long convertTimeZoneUtc(long time) { 29 | Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); 30 | calendar.setTimeInMillis(time); 31 | calendar.set(Calendar.HOUR_OF_DAY, 0); 32 | calendar.set(Calendar.MINUTE, 0); 33 | calendar.set(Calendar.SECOND, 0); 34 | calendar.set(Calendar.MILLISECOND, 0); 35 | return calendar.getTimeInMillis(); 36 | } 37 | 38 | /** 39 | * Get time start day 40 | * @return 41 | */ 42 | long getTimeStart() { 43 | return mTime; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneDateSubKey.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | /** 4 | * Create times init BluezoneID 5 | * @author khanhxu 6 | */ 7 | public class BluezoneDateSubKey extends BluezoneDate { 8 | 9 | private int mNextSubKey = 0; 10 | private long mDetal = 0; 11 | private long mTimeNext = 0; 12 | private long mTimeCurrent; 13 | private int mMaxSubKey; 14 | 15 | /** 16 | * Init 17 | * 18 | * @param time 19 | */ 20 | BluezoneDateSubKey(long time, int maxSubKey) throws Exception { 21 | super(time); 22 | mTimeCurrent = time; 23 | if (maxSubKey > 1) { 24 | mNextSubKey = 0; 25 | mMaxSubKey = maxSubKey; 26 | mDetal = BluezoneIdConstants.DAY_MILLISECONDS / maxSubKey; 27 | } else { 28 | throw new Exception("maxSubKey > 0"); 29 | } 30 | } 31 | 32 | /** 33 | * Init max sub key 34 | * @param maxSubKey 35 | */ 36 | public void setMaxSubKey(int maxSubKey) { 37 | if (maxSubKey > 1) { 38 | mNextSubKey = 0; 39 | mMaxSubKey = maxSubKey; 40 | mDetal = BluezoneIdConstants.DAY_MILLISECONDS / maxSubKey; 41 | } else { 42 | throw new IllegalArgumentException("maxSubKey > 0"); 43 | } 44 | } 45 | 46 | /** 47 | * Reset getnext subkey 48 | */ 49 | public void ressetNextSubKey() { 50 | mNextSubKey = 0; 51 | } 52 | 53 | /** 54 | * Call next subtime 55 | * @return 56 | */ 57 | long nextTimeSubKey() { 58 | mTimeNext = getTimeStart() + (mNextSubKey * mDetal); 59 | mNextSubKey++; 60 | return mTimeNext; 61 | } 62 | 63 | /** 64 | * Check bluezone id 65 | * @return 66 | */ 67 | boolean isBluezoneNow() { 68 | if (mTimeCurrent <= mTimeNext && (mTimeNext >= mTimeNext - mDetal)) { 69 | return true; 70 | } 71 | 72 | return false; 73 | } 74 | 75 | /** 76 | * Get Index Sub Key 77 | * @return 78 | */ 79 | int getIndexSubKey() { 80 | return (int) ((mTimeCurrent - getTimeStart()) / (BluezoneIdConstants.DAY_MILLISECONDS / mMaxSubKey)); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneId.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | import android.util.Pair; 4 | 5 | /** 6 | * @author khanhxu 7 | */ 8 | class BluezoneId extends Pair { 9 | 10 | /** 11 | * Constructor for a Pair. 12 | * 13 | * @param first the first object in the Pair 14 | * @param second the second object in the pair 15 | */ 16 | BluezoneId(byte[] first, Long second) { 17 | super(first, second); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneIdConstants.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | /** 4 | * @author khanhxu 5 | */ 6 | public class BluezoneIdConstants { 7 | 8 | static final long DAY_MILLISECONDS = 24 * 60 * 60 * 1000; 9 | 10 | // Constant config 11 | public static class Config { 12 | // Rolling ID 13 | static final boolean IS_ROLLING_ID = true; 14 | 15 | // Length Blid 16 | static final int LENGTH_BLID = 6; 17 | 18 | // Length Byte 19 | public static final int LENGTH_BYTE = 12; 20 | 21 | // Length daily key 22 | public static final int LENGTH_DAILY_KEY = 32; 23 | 24 | // Char random 25 | static final String CHAR_RANDOM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 26 | 27 | // Salt Subkey 28 | static final byte[] SALT_SUB_KEY_DAILY = "bluzonesubkey".getBytes(); 29 | 30 | // Max number subkey daily 31 | static final int MAX_NUMBER_SUB_KEY_PER_DAY = 24 * 4; 32 | } 33 | 34 | // Constant Preference 35 | static class Preference { 36 | // Save bluezone base id 37 | static final String BLUEZONE_BASE_ID = "pre_bluezone_base_id"; 38 | 39 | // Save bluezone daily id 40 | static final String BLUEZONE_DAILY_ID = "pre_bluezone_daily_id"; 41 | 42 | // Save max number subkey per day 43 | static final String MAX_NUMBER_SUB_KEY_PER_DAY = "pre_max_number_sub_key_per_day"; 44 | } 45 | 46 | static class TraceInfo { 47 | public static final String JSON_BLUEZONE_BASE_ID = "base_id"; // BluzoneBaseID 48 | public static final String JSON_BLUEZONE_BASE_ID_TIME = "time"; // Time create Bluezone base ID 49 | public static final String JSON_F0_DATA = "data"; // Data array F0 50 | public static final String JSON_F0_DAILY_KEY = "daily_key"; // F0 Bluezone base ID 51 | public static final String JSON_F0_TIME_DK = "time_start"; // F0 Time Create F0 52 | public static final String JSON_F0_MAX_ROLL = "max"; // Max Rolling 53 | public static final String JSON_F0_TIME_END = "time_end"; // Max Rolling 54 | 55 | public static final String FILE_NAME_TRACE_DATA = "data_trace.txt"; // File save Data trace 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | import android.util.Log; 6 | 7 | import com.scan.AppUtils; 8 | import com.scan.preference.AppPreferenceManager; 9 | 10 | import java.security.NoSuchAlgorithmException; 11 | import java.security.SecureRandom; 12 | import java.util.ArrayList; 13 | 14 | import javax.crypto.KeyGenerator; 15 | import javax.crypto.SecretKey; 16 | 17 | /** 18 | * Class Create BluezoneId 19 | * @author khanhxu 20 | */ 21 | public class BluezoneIdGenerator { 22 | 23 | private static BluezoneIdGenerator sInstance; 24 | private AppPreferenceManager mPreferenceManager; 25 | 26 | /** 27 | * init 28 | * @param context 29 | * @return 30 | */ 31 | public static BluezoneIdGenerator getInstance(Context context) { 32 | if (sInstance == null) { 33 | sInstance = new BluezoneIdGenerator(); 34 | sInstance.mPreferenceManager = AppPreferenceManager.getInstance(context); 35 | } 36 | 37 | return sInstance; 38 | } 39 | 40 | /** 41 | * Get Bluezone Id 42 | * @return 43 | */ 44 | public byte[] getBluezoneId() { 45 | if (BluezoneIdConstants.Config.IS_ROLLING_ID) { 46 | return rollingBluezoneId(); 47 | } 48 | 49 | return randomBluezoneId().getBytes(); 50 | } 51 | 52 | /** 53 | * Get bluezone id with time 54 | * @return 55 | */ 56 | private byte[] rollingBluezoneId() { 57 | byte[] bluezoneId = null; 58 | 59 | // Current 60 | long now = System.currentTimeMillis(); 61 | BluezoneDate bluezoneDateNow = new BluezoneDate(now); 62 | 63 | // Get list BluezoneDailyId 64 | BluezoneDailyId bluezoneDailyId = getBluezoneDailyId(); 65 | if (bluezoneDailyId != null && bluezoneDailyId.second.getTimeStart() >= bluezoneDateNow.getTimeStart()) { 66 | int index = getIndexSubKey(now); 67 | if (index >= 0) { 68 | BluezoneId bluezoneIdSave = bluezoneDailyId.first.get(index); 69 | if (bluezoneIdSave != null) { 70 | bluezoneId = bluezoneIdSave.first; 71 | } 72 | } 73 | } else { 74 | // Create BluezoneDailyId 75 | BluezoneDailyKey bluezoneDailyKey = getBluezoneBaseId(); 76 | if (bluezoneDailyKey != null) { 77 | // Other date 78 | bluezoneId = createListBluezoneDailyId(createBluezoneDailyKey(bluezoneDailyKey, bluezoneDateNow.getTimeStart())); 79 | } else { 80 | // New create 81 | bluezoneId = createBluezoneBaseId(); 82 | } 83 | } 84 | 85 | return bluezoneId; 86 | } 87 | 88 | /** 89 | * Create bluezoneId base Id 90 | * @return blid create 91 | */ 92 | private byte[] createBluezoneBaseId() { 93 | byte[] bluezoneDailyKeyNow = null; 94 | 95 | // Create random bluezone base id 96 | byte[] bluezoneBaseId = initRandomBluezoneBaseId(); 97 | if (bluezoneBaseId != null) { 98 | BluezoneDailyKey bluezoneBaseIdData = new BluezoneDailyKey(bluezoneBaseId, new BluezoneDate(System.currentTimeMillis())); 99 | saveBluezoneBaseId(BluezoneIdUtils.objectToJson(bluezoneBaseIdData)); 100 | 101 | // Create BluezoneId 102 | bluezoneDailyKeyNow = createListBluezoneDailyId(bluezoneBaseId); 103 | } 104 | 105 | return bluezoneDailyKeyNow; 106 | } 107 | 108 | /** 109 | * Create BluezoneBaseId 110 | * @return 111 | */ 112 | private byte[] initRandomBluezoneBaseId() { 113 | try { 114 | KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacSHA256"); 115 | SecretKey secretKey = keyGenerator.generateKey(); 116 | return secretKey.getEncoded(); 117 | } catch (NoSuchAlgorithmException e) { 118 | e.printStackTrace(); 119 | } 120 | 121 | return null; 122 | } 123 | 124 | /** 125 | * Create BluezoneDailyKey 126 | * @param bluezoneDailyKey 127 | * @param timeEnd 128 | * @return 129 | */ 130 | private byte[] createBluezoneDailyKey(BluezoneDailyKey bluezoneDailyKey, long timeEnd) { 131 | byte[] bluezoneDailyKeyNow = null; 132 | 133 | // Create hash sha256 to Dn-1 134 | if (bluezoneDailyKey != null) { 135 | // Default 136 | bluezoneDailyKeyNow = bluezoneDailyKey.first; 137 | 138 | int times = (int) ((timeEnd - bluezoneDailyKey.second.getTimeStart()) / BluezoneIdConstants.DAY_MILLISECONDS); 139 | if (times > 0) { 140 | for (int i = 0; i < times; i++) { 141 | bluezoneDailyKeyNow = BluezoneIdUtils.sha256(bluezoneDailyKeyNow); 142 | } 143 | } 144 | } 145 | 146 | return bluezoneDailyKeyNow; 147 | } 148 | 149 | /** 150 | * Create BluezoneDailyKey 151 | * @param dayStart 152 | * @return 153 | */ 154 | public BluezoneDailyKey createBluezoneDailyKey(int dayStart) { 155 | BluezoneDailyKey ret = null; 156 | 157 | BluezoneDailyKey bluezoneDailyKey = getBluezoneBaseId(); 158 | // Create hash sha256 to Dn-1 159 | if (bluezoneDailyKey != null) { 160 | // Call Time 161 | long timeEnd = System.currentTimeMillis() - (dayStart * BluezoneIdConstants.DAY_MILLISECONDS); 162 | 163 | // Default 164 | byte[] bluezoneDailyKeyDx = bluezoneDailyKey.first; 165 | 166 | int times = (int) ((timeEnd - bluezoneDailyKey.second.getTimeStart()) / BluezoneIdConstants.DAY_MILLISECONDS); 167 | long timeStart = bluezoneDailyKey.second.getTimeStart(); 168 | if (times > 0) { 169 | for (int i = 0; i < times; i++) { 170 | bluezoneDailyKeyDx = BluezoneIdUtils.sha256(bluezoneDailyKeyDx); 171 | timeStart = timeStart + BluezoneIdConstants.DAY_MILLISECONDS; 172 | } 173 | } 174 | 175 | ret = new BluezoneDailyKey(bluezoneDailyKeyDx, new BluezoneDate(timeStart)); 176 | } 177 | 178 | return ret; 179 | } 180 | 181 | /** 182 | * Create list BluezoneDailyId and save 183 | * @param bluezoneDailyKey 184 | * @return 185 | */ 186 | private byte[] createListBluezoneDailyId(byte[] bluezoneDailyKey) { 187 | byte[] bluezoneDailyKeyNow = null; 188 | 189 | try { 190 | // check 191 | if (bluezoneDailyKey != null && bluezoneDailyKey.length == BluezoneIdConstants.Config.LENGTH_DAILY_KEY) { 192 | long now = System.currentTimeMillis(); 193 | 194 | // Get max sub sub key per day 195 | int maxSubKey = getMaxNumberSubKey(); 196 | 197 | // Data for subkey = bluezoneDailyKey + salt sub key 198 | byte[] dataCreateSubKey = BluezoneIdUtils.addByteArrays(bluezoneDailyKey, BluezoneIdConstants.Config.SALT_SUB_KEY_DAILY); 199 | byte[] bluezoneSubKey = BluezoneIdUtils.sha256(dataCreateSubKey); 200 | 201 | // Date subkey 202 | BluezoneDateSubKey dateSubKey = new BluezoneDateSubKey(now, maxSubKey); 203 | 204 | int indexSubKey = dateSubKey.getIndexSubKey(); 205 | 206 | // List BluezoneId 207 | ArrayList listBluezoneId = new ArrayList<>(); 208 | 209 | // Create list 210 | for (int i = 0; i < maxSubKey; i++) { 211 | byte[] bluezoneId = convertBluezoneSubKeyToBluezoneId(bluezoneSubKey); 212 | if (bluezoneId.length == BluezoneIdConstants.Config.LENGTH_BYTE) { 213 | long timeBluezone = dateSubKey.nextTimeSubKey(); 214 | listBluezoneId.add(new BluezoneId(bluezoneId, timeBluezone)); 215 | 216 | // Check index subkey 217 | if (indexSubKey == i) { 218 | bluezoneDailyKeyNow = bluezoneId; 219 | } 220 | } 221 | 222 | bluezoneSubKey = BluezoneIdUtils.sha256(bluezoneSubKey); 223 | } 224 | 225 | // Save list daily id 226 | saveBluezoneDailyId(BluezoneIdUtils.objectToJson(new BluezoneDailyId(listBluezoneId, new BluezoneDate(now)))); 227 | } 228 | } catch (Exception e) { 229 | e.printStackTrace(); 230 | } 231 | 232 | return bluezoneDailyKeyNow; 233 | } 234 | 235 | /** 236 | * Convert BluezoneSubKey to BluezoneId 237 | * @param bluezoneSubKey 238 | * @return 239 | */ 240 | public static byte[] convertBluezoneSubKeyToBluezoneId(byte[] bluezoneSubKey) { 241 | byte[] bluezoneDailyId = new byte[BluezoneIdConstants.Config.LENGTH_BYTE]; 242 | 243 | if (bluezoneSubKey != null && bluezoneSubKey.length == BluezoneIdConstants.Config.LENGTH_DAILY_KEY) { 244 | // 12 Byte: 4 x 4 bytes + 2 x 8 bytes 245 | for (int i = 0; i < BluezoneIdConstants.Config.LENGTH_BYTE; i++) { 246 | int start = i * 4; 247 | 248 | // Check 2 end 249 | if (i > 3) { 250 | start = (i - 4) * 2 + 16; 251 | } 252 | 253 | bluezoneDailyId[i] = bluezoneSubKey[start]; 254 | } 255 | } 256 | 257 | return bluezoneDailyId; 258 | } 259 | 260 | /** 261 | * Get Index Sub Key 262 | * @return 263 | */ 264 | private int getIndexSubKey(long time) { 265 | // Get max sub sub key per day 266 | int maxSubKey = getMaxNumberSubKey(); 267 | 268 | // Index 269 | return (int) ((time - (new BluezoneDate(time)).getTimeStart()) / (BluezoneIdConstants.DAY_MILLISECONDS / maxSubKey)); 270 | } 271 | 272 | /** 273 | * Create random bluezoneId 274 | * @return 275 | */ 276 | private String randomBluezoneId() { 277 | String randomBluezoneId = getRadomBluezoneId(); 278 | if (TextUtils.isEmpty(randomBluezoneId)) { 279 | StringBuilder blidBuilder = new StringBuilder(); 280 | 281 | // SecureRandom 282 | SecureRandom secureRandom = new SecureRandom(); 283 | 284 | // Create id 285 | for (int i = 0; i < BluezoneIdConstants.Config.LENGTH_BLID; i++) { 286 | // Index Random 287 | int index = secureRandom.nextInt(BluezoneIdConstants.Config.CHAR_RANDOM.length()); 288 | 289 | // Add 290 | blidBuilder.append(BluezoneIdConstants.Config.CHAR_RANDOM.charAt(index)); 291 | } 292 | 293 | randomBluezoneId = blidBuilder.toString(); 294 | saveBluezoneDailyId(randomBluezoneId); 295 | } 296 | 297 | return randomBluezoneId; 298 | } 299 | 300 | /** 301 | * Save Bluezone base Id 302 | * @param bluezoneBaseId 303 | */ 304 | private void saveBluezoneBaseId(String bluezoneBaseId) { 305 | mPreferenceManager.putString(BluezoneIdConstants.Preference.BLUEZONE_BASE_ID, bluezoneBaseId); 306 | } 307 | 308 | /** 309 | * Get Bluezone base Id 310 | * @return 311 | */ 312 | public BluezoneDailyKey getBluezoneBaseId() { 313 | String jsonBluezoneBaseId = mPreferenceManager.getString(BluezoneIdConstants.Preference.BLUEZONE_BASE_ID, ""); 314 | if (!TextUtils.isEmpty(jsonBluezoneBaseId)) { 315 | return BluezoneIdUtils.jsonToObject(jsonBluezoneBaseId, BluezoneDailyKey.class); 316 | } 317 | 318 | return null; 319 | } 320 | 321 | /** 322 | * Save Bluezone Daily Id 323 | * @param bluezoneDailyId 324 | */ 325 | private void saveBluezoneDailyId(String bluezoneDailyId) { 326 | mPreferenceManager.putString(BluezoneIdConstants.Preference.BLUEZONE_DAILY_ID, bluezoneDailyId); 327 | } 328 | 329 | /** 330 | * Get Bluezone Daily Id 331 | * @return 332 | */ 333 | private BluezoneDailyId getBluezoneDailyId() { 334 | String jsonBluezoneDailyId = mPreferenceManager.getString(BluezoneIdConstants.Preference.BLUEZONE_DAILY_ID, ""); 335 | if (!TextUtils.isEmpty(jsonBluezoneDailyId)) { 336 | return BluezoneIdUtils.jsonToObject(jsonBluezoneDailyId, BluezoneDailyId.class); 337 | } 338 | 339 | return null; 340 | } 341 | 342 | /** 343 | * Get Bluezone Id if Bluezone is Random 344 | * @return 345 | */ 346 | private String getRadomBluezoneId() { 347 | return mPreferenceManager.getString(BluezoneIdConstants.Preference.BLUEZONE_DAILY_ID, ""); 348 | } 349 | 350 | /** 351 | * Set Number sub key in day 352 | * @return 353 | */ 354 | public void setMaxNumberSubKey(int maxNumber) { 355 | mPreferenceManager.putInt(BluezoneIdConstants.Preference.MAX_NUMBER_SUB_KEY_PER_DAY, maxNumber); 356 | } 357 | 358 | /** 359 | * Get Number sub key in day 360 | * @return 361 | */ 362 | private int getMaxNumberSubKey() { 363 | int maxSubKey = mPreferenceManager.getInt(BluezoneIdConstants.Preference.MAX_NUMBER_SUB_KEY_PER_DAY, BluezoneIdConstants.Config.MAX_NUMBER_SUB_KEY_PER_DAY); 364 | if (maxSubKey < 1) { 365 | maxSubKey = BluezoneIdConstants.Config.MAX_NUMBER_SUB_KEY_PER_DAY; 366 | } 367 | 368 | return maxSubKey; 369 | } 370 | } -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneIdTrace.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | import android.content.Context; 4 | import android.database.Cursor; 5 | import android.os.Environment; 6 | import android.text.TextUtils; 7 | 8 | import com.scan.AppUtils; 9 | import com.scan.database.AppDatabaseHelper; 10 | 11 | import org.json.JSONArray; 12 | import org.json.JSONException; 13 | import org.json.JSONObject; 14 | 15 | import java.io.File; 16 | import java.io.IOException; 17 | import java.io.RandomAccessFile; 18 | import java.util.ArrayList; 19 | 20 | /** 21 | * Class Trace Fx 22 | * @author khanhxu 23 | */ 24 | public class BluezoneIdTrace { 25 | 26 | /** 27 | * Get Path Data 28 | * @param context 29 | * @return 30 | */ 31 | public static File getPathTraceData(Context context, String nameFile) { 32 | return new File(Environment.getDataDirectory() + "/data/" + 33 | context.getPackageName(), nameFile); 34 | } 35 | 36 | /** 37 | * Get Bluezoner Info 38 | * @param context 39 | * @param dayStartTrace 40 | * @return 41 | */ 42 | public static String getBluezoneIdInfo(Context context, int dayStartTrace) { 43 | String ret = ""; 44 | BluezoneDailyKey bluezoneDailyKey = BluezoneIdGenerator.getInstance(context).getBluezoneBaseId(); 45 | if (bluezoneDailyKey != null) { 46 | JSONObject jsonObject = new JSONObject(); 47 | try { 48 | jsonObject.put(BluezoneIdConstants.TraceInfo.JSON_BLUEZONE_BASE_ID, AppUtils.convertBytesToHex(bluezoneDailyKey.first)); 49 | jsonObject.put(BluezoneIdConstants.TraceInfo.JSON_BLUEZONE_BASE_ID_TIME, bluezoneDailyKey.second.getTimeStart() / 1000); 50 | 51 | // get info day trace 52 | BluezoneDailyKey bluezoneDailyKeyDx = BluezoneIdGenerator.getInstance(context).createBluezoneDailyKey(dayStartTrace); 53 | if (bluezoneDailyKeyDx != null) { 54 | jsonObject.put(BluezoneIdConstants.TraceInfo.JSON_F0_DAILY_KEY, AppUtils.convertBytesToHex(bluezoneDailyKeyDx.first)); 55 | jsonObject.put(BluezoneIdConstants.TraceInfo.JSON_F0_TIME_DK, bluezoneDailyKeyDx.second.getTimeStart() / 1000); 56 | } 57 | 58 | ret = jsonObject.toString(); 59 | } catch (JSONException e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | 64 | return ret; 65 | } 66 | 67 | /** 68 | * Export Data 69 | * @param context 70 | * @return 71 | */ 72 | public static String exportTraceData(Context context) { 73 | String ret = ""; 74 | 75 | File fileTrace = getPathTraceData(context, BluezoneIdConstants.TraceInfo.FILE_NAME_TRACE_DATA); 76 | if (fileTrace != null) { 77 | // delete old 78 | if (fileTrace.exists()) { 79 | fileTrace.delete(); 80 | } 81 | 82 | RandomAccessFile fi = null; 83 | 84 | try { 85 | // create file 86 | if (fileTrace.createNewFile()) { 87 | fi = new RandomAccessFile(fileTrace.getAbsolutePath(), "rw"); 88 | 89 | // Get all cursor 90 | Cursor cursor = AppDatabaseHelper.getInstance(context).getCursorData(); 91 | if (cursor != null) { 92 | // Read 93 | while (cursor.moveToNext()) { 94 | try { 95 | String retItem = AppUtils.convertBytesToHex(cursor.getBlob(AppDatabaseHelper.COLUMN_INDEX_BLID)) + "\t" + 96 | AppUtils.convertBytesToHex(cursor.getBlob(AppDatabaseHelper.COLUMN_INDEX_BLID_CONTACT)) + "\t" + 97 | cursor.getInt(AppDatabaseHelper.COLUMN_INDEX_RSSI) + "\t" + 98 | cursor.getLong(AppDatabaseHelper.COLUMN_INDEX_TIME) + "\n"; 99 | 100 | fi.write(retItem.getBytes()); 101 | } catch (Exception e) { 102 | e.printStackTrace(); 103 | } 104 | } 105 | ret = fileTrace.getAbsolutePath(); 106 | cursor.close(); 107 | } 108 | } 109 | } catch (Exception e) { 110 | e.printStackTrace(); 111 | } finally { 112 | if (fi != null) { 113 | try { 114 | fi.close(); 115 | } catch (IOException e) { 116 | e.printStackTrace(); 117 | } 118 | } 119 | } 120 | } 121 | 122 | return ret; 123 | } 124 | 125 | /** 126 | * Export Data 127 | * @param context 128 | * @param dayStartTrace 129 | * @return 130 | */ 131 | public static String exportTraceData(Context context, int dayStartTrace) { 132 | String ret = ""; 133 | File fileTrace = getPathTraceData(context, BluezoneIdConstants.TraceInfo.FILE_NAME_TRACE_DATA); 134 | 135 | if (fileTrace != null) { 136 | // delete old 137 | if (fileTrace.exists()) { 138 | fileTrace.delete(); 139 | } 140 | 141 | RandomAccessFile fi = null; 142 | 143 | try { 144 | // create file 145 | if (fileTrace.createNewFile()) { 146 | fi = new RandomAccessFile(fileTrace.getAbsolutePath(), "rw"); 147 | 148 | // Call Time 149 | long timeEnd = System.currentTimeMillis() - (dayStartTrace * BluezoneIdConstants.DAY_MILLISECONDS); 150 | 151 | // Get all cursor 152 | Cursor cursor = AppDatabaseHelper.getInstance(context).getCursorData(timeEnd); 153 | if (cursor != null) { 154 | while (cursor.moveToNext()) { 155 | try { 156 | String retItem = AppUtils.convertBytesToHex(cursor.getBlob(AppDatabaseHelper.COLUMN_INDEX_BLID)) + "\t" + 157 | AppUtils.convertBytesToHex(cursor.getBlob(AppDatabaseHelper.COLUMN_INDEX_BLID_CONTACT)) + "\t" + 158 | cursor.getInt(AppDatabaseHelper.COLUMN_INDEX_RSSI) + "\t" + 159 | cursor.getLong(AppDatabaseHelper.COLUMN_INDEX_TIME) + "\n"; 160 | 161 | fi.write(retItem.getBytes()); 162 | } catch (Exception e) { 163 | e.printStackTrace(); 164 | } 165 | } 166 | 167 | ret = fileTrace.getAbsolutePath(); 168 | cursor.close(); 169 | } 170 | } 171 | } catch (Exception e) { 172 | e.printStackTrace(); 173 | } finally { 174 | if (fi != null) { 175 | try { 176 | fi.close(); 177 | } catch (IOException e) { 178 | e.printStackTrace(); 179 | } 180 | } 181 | } 182 | } 183 | 184 | return ret; 185 | } 186 | 187 | /** 188 | * Check Contact F 189 | * @param context 190 | * @param dataF0 191 | * @return 192 | */ 193 | public static boolean isContactF(Context context, String dataF0) { 194 | boolean ret = false; 195 | if (!TextUtils.isEmpty(dataF0)) { 196 | try { 197 | JSONObject jsonDataF0 = new JSONObject(dataF0); 198 | JSONArray jsonArray = jsonDataF0.getJSONArray(BluezoneIdConstants.TraceInfo.JSON_F0_DATA); 199 | for (int i = 0; i < jsonArray.length(); i++) { 200 | JSONObject jsonObject = jsonArray.getJSONObject(i); 201 | String dailyKey = jsonObject.getString(BluezoneIdConstants.TraceInfo.JSON_F0_DAILY_KEY); 202 | long timeDk = jsonObject.getLong(BluezoneIdConstants.TraceInfo.JSON_F0_TIME_DK); 203 | int maxRoll = jsonObject.getInt(BluezoneIdConstants.TraceInfo.JSON_F0_MAX_ROLL); 204 | long timeTe = jsonObject.getLong(BluezoneIdConstants.TraceInfo.JSON_F0_TIME_END); 205 | 206 | // Check trace 207 | if (checkContactF(context, dailyKey, timeDk, maxRoll, timeTe)) { 208 | ret = true; 209 | break; 210 | } 211 | } 212 | } catch (JSONException e) { 213 | e.printStackTrace(); 214 | } 215 | } 216 | 217 | return ret; 218 | } 219 | 220 | /** 221 | * Get Trace list 222 | * @param context 223 | * @param dataF0 224 | * @return 225 | */ 226 | public static ArrayList getTraceF(Context context, String dataF0) { 227 | ArrayList ret = new ArrayList<>(); 228 | // Phân tích Data F0 229 | if (!TextUtils.isEmpty(dataF0)) { 230 | try { 231 | JSONObject jsonDataF0 = new JSONObject(dataF0); 232 | JSONArray jsonArray = jsonDataF0.getJSONArray(BluezoneIdConstants.TraceInfo.JSON_F0_DATA); 233 | for (int i = 0; i < jsonArray.length(); i++) { 234 | JSONObject jsonObject = jsonArray.getJSONObject(i); 235 | String dailyKey = jsonObject.getString(BluezoneIdConstants.TraceInfo.JSON_F0_DAILY_KEY); 236 | long timeDk = jsonObject.getLong(BluezoneIdConstants.TraceInfo.JSON_F0_TIME_DK); 237 | int maxRoll = jsonObject.getInt(BluezoneIdConstants.TraceInfo.JSON_F0_MAX_ROLL); 238 | long timeTe = jsonObject.getLong(BluezoneIdConstants.TraceInfo.JSON_F0_TIME_END); 239 | 240 | // Check trace 241 | if (checkContactF(context, dailyKey, timeDk, maxRoll, timeTe)) { 242 | ret.add(dailyKey); 243 | } 244 | } 245 | } catch (JSONException e) { 246 | e.printStackTrace(); 247 | } 248 | } 249 | 250 | return ret; 251 | } 252 | 253 | /** 254 | * Check Contact 255 | * @param context 256 | * @param bluezoneDailyKey DaiLy Key 257 | * @param timeDk Thời gian tạo 258 | * @param max Số lần rolling 259 | * @param timeTe Thời gian kết thúc truy vết 260 | * @return 261 | */ 262 | public static boolean checkContactF(Context context, String bluezoneDailyKey, long timeDk, int max, long timeTe) { 263 | boolean ret = false; 264 | timeDk = timeDk * 1000; 265 | timeTe = timeTe * 1000; 266 | 267 | // Convert Bytes -> hex 268 | byte[] bluezoneDailyKeyk = AppUtils.convertHexToBytes(bluezoneDailyKey); 269 | if (bluezoneDailyKeyk.length == BluezoneIdConstants.Config.LENGTH_DAILY_KEY) { 270 | // Create first SubKey 271 | byte[] dataCreateFirstSubKey = bluezoneDailyKeyk; 272 | byte[] bluezoneSubKey = BluezoneIdUtils.addByteArrays(dataCreateFirstSubKey, BluezoneIdConstants.Config.SALT_SUB_KEY_DAILY); 273 | long timeNext = timeDk; 274 | long delta = BluezoneIdConstants.DAY_MILLISECONDS / max; 275 | int i = 0; 276 | 277 | // Find Fx 278 | while (timeNext <= timeTe) { 279 | bluezoneSubKey = BluezoneIdUtils.sha256(bluezoneSubKey); 280 | byte[] bluezoneId = BluezoneIdGenerator.convertBluezoneSubKeyToBluezoneId(bluezoneSubKey); 281 | long timeStart = timeNext; 282 | timeNext = timeNext + delta; 283 | long timeEnd = timeNext; 284 | 285 | // Check 286 | if (AppDatabaseHelper.getInstance(context).isTrace(bluezoneId, timeStart, timeEnd)) { 287 | ret = true; 288 | break; 289 | } 290 | 291 | i++; 292 | 293 | // Check nextday and create Subkey 294 | if (i == max) { 295 | dataCreateFirstSubKey = BluezoneIdUtils.sha256(dataCreateFirstSubKey); 296 | bluezoneSubKey = BluezoneIdUtils.addByteArrays(dataCreateFirstSubKey, BluezoneIdConstants.Config.SALT_SUB_KEY_DAILY); 297 | i = 0; 298 | } 299 | } 300 | } 301 | 302 | return ret; 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/bluezoneid/BluezoneIdUtils.java: -------------------------------------------------------------------------------- 1 | package com.scan.bluezoneid; 2 | 3 | import android.content.Context; 4 | import android.util.Base64; 5 | 6 | import com.google.gson.Gson; 7 | import com.scan.AppUtils; 8 | import com.scan.preference.AppPreferenceManager; 9 | 10 | import java.nio.ByteBuffer; 11 | import java.security.MessageDigest; 12 | import java.security.NoSuchAlgorithmException; 13 | 14 | /** 15 | * @author khanhxu 16 | */ 17 | public class BluezoneIdUtils { 18 | 19 | /** 20 | * Get hex bluezone id 21 | * @param context 22 | * @return 23 | */ 24 | public static String getHexBluezoneId(Context context) { 25 | byte[] bluezoneId = BluezoneIdGenerator.getInstance(context).getBluezoneId(); 26 | if (isBluezoneIdValidate(bluezoneId)) { 27 | return AppUtils.convertBytesToHex(bluezoneId); 28 | } 29 | 30 | return ""; 31 | } 32 | 33 | /** 34 | * Hash SHA256 35 | * @param text 36 | * @return 37 | */ 38 | static byte[] sha256(String text) { 39 | byte[] ret = null; 40 | 41 | try { 42 | MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); 43 | messageDigest.update(text.getBytes()); 44 | ret = messageDigest.digest(); 45 | } catch (NoSuchAlgorithmException e) { 46 | e.printStackTrace(); 47 | } 48 | 49 | return ret; 50 | } 51 | 52 | /** 53 | * Hash SHA256 54 | * @param data 55 | * @return 56 | */ 57 | static byte[] sha256(byte[] data) { 58 | byte[] ret = null; 59 | 60 | try { 61 | MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); 62 | messageDigest.update(data); 63 | ret = messageDigest.digest(); 64 | } catch (NoSuchAlgorithmException e) { 65 | e.printStackTrace(); 66 | } 67 | 68 | return ret; 69 | } 70 | 71 | /** 72 | * SHA256 encode 73 | * @param text 74 | * @return 75 | */ 76 | static String sha256Encode(String text) { 77 | String ret = ""; 78 | 79 | try { 80 | byte[] digest = sha256(text); 81 | ret = Base64.encodeToString(digest, Base64.DEFAULT); 82 | } catch (Exception e) { 83 | e.printStackTrace(); 84 | } 85 | 86 | return ret; 87 | } 88 | 89 | /** 90 | * Convert bytes to long 91 | * @param bytes 92 | * @return 93 | */ 94 | static long bytesToLong(byte[] bytes) { 95 | ByteBuffer byteBuffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE); 96 | byteBuffer.put(bytes); 97 | byteBuffer.rewind(); 98 | return byteBuffer.getLong(); 99 | } 100 | 101 | /** 102 | * Add two bytes 103 | * @param bytesA 104 | * @param bytesB 105 | * @return 106 | */ 107 | static byte[] addByteArrays(byte[] bytesA, byte[] bytesB) { 108 | byte[] result = new byte[bytesA.length + bytesB.length]; 109 | System.arraycopy(bytesA, 0, result, 0, bytesA.length); 110 | System.arraycopy(bytesB, 0, result, bytesA.length, bytesB.length); 111 | return result; 112 | } 113 | 114 | /** 115 | * Convert object to json 116 | * @param object 117 | * @return 118 | */ 119 | static String objectToJson(Object object) { 120 | return new Gson().toJson(object); 121 | } 122 | 123 | /** 124 | * Convert json to Object 125 | * @return 126 | */ 127 | static T jsonToObject(String json, Class classOfT) { 128 | try { 129 | return new Gson().fromJson(json, classOfT); 130 | } catch (Exception e) { 131 | e.printStackTrace(); 132 | } 133 | 134 | return null; 135 | } 136 | 137 | /** 138 | * Validate bluezone id 139 | * @return 140 | */ 141 | public static boolean isBluezoneIdValidate(byte[] dataBytes) { 142 | if (dataBytes != null && dataBytes.length == BluezoneIdConstants.Config.LENGTH_BYTE) { 143 | return true; 144 | } 145 | 146 | return false; 147 | } 148 | 149 | /** 150 | * Check bluezone id changed between 151 | * @param timeStart 152 | * @param timeEnd 153 | * @return 154 | */ 155 | public static boolean isBluezoneIdChanged(Context context, long timeStart, long timeEnd) { 156 | // Get max sub sub key per day 157 | int maxSubKey = AppPreferenceManager.getInstance(context).getInt(BluezoneIdConstants.Preference.MAX_NUMBER_SUB_KEY_PER_DAY, 158 | BluezoneIdConstants.Config.MAX_NUMBER_SUB_KEY_PER_DAY); 159 | if (maxSubKey < 1) { 160 | maxSubKey = BluezoneIdConstants.Config.MAX_NUMBER_SUB_KEY_PER_DAY; 161 | } 162 | 163 | // Date subkey 164 | try { 165 | BluezoneDateSubKey dateSubKeyStart = new BluezoneDateSubKey(timeStart, maxSubKey); 166 | BluezoneDateSubKey dateSubKeyEnd = new BluezoneDateSubKey(timeEnd, maxSubKey); 167 | 168 | if (dateSubKeyStart.getIndexSubKey() != dateSubKeyEnd.getIndexSubKey()) { 169 | return true; 170 | } 171 | 172 | } catch (Exception e) { 173 | e.printStackTrace(); 174 | } 175 | 176 | return false; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/database/AppDatabaseHelper.java: -------------------------------------------------------------------------------- 1 | package com.scan.database; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.database.sqlite.SQLiteDatabase; 7 | import android.database.sqlite.SQLiteOpenHelper; 8 | import android.provider.BaseColumns; 9 | import android.text.TextUtils; 10 | 11 | import com.scan.AppConstants; 12 | import com.scan.AppUtils; 13 | import com.scan.bluezoneid.BluezoneIdGenerator; 14 | 15 | import java.util.HashMap; 16 | import java.util.HashSet; 17 | import java.util.Map; 18 | import java.util.Set; 19 | 20 | /** 21 | * @author khanhxu 22 | */ 23 | public class AppDatabaseHelper extends SQLiteOpenHelper { 24 | 25 | private static final String DATABASE_NAME = "app_db_2.db"; 26 | public static final int DATABASE_VERSION = 1; 27 | 28 | // Table trace 29 | public static final String TABLE_NAME = "trace_info"; 30 | public static final String COLUMN_BLID = "blid"; // User Code 31 | public static final String COLUMN_BLID_CONTACT = "blid_contact"; // Bluezone Id scan 32 | public static final String COLUMN_MAC_ID = "macid"; // MacId scan 33 | public static final String COLUMN_RSSI = "rssi"; 34 | public static final String COLUMN_TX_POWER = "tx_power"; 35 | public static final String COLUMN_STATE = "state"; 36 | public static final String COLUMN_TIME = "timestamp"; 37 | 38 | // Index 39 | public static final int COLUMN_INDEX_BLID = 1; 40 | public static final int COLUMN_INDEX_BLID_CONTACT = 2; 41 | public static final int COLUMN_INDEX_MAC_ID = 3; 42 | public static final int COLUMN_INDEX_RSSI = 4; 43 | public static final int COLUMN_INDEX_TX_POWER = 5; 44 | public static final int COLUMN_INDEX_STATE = 6; 45 | public static final int COLUMN_INDEX_TIME = 7; 46 | 47 | private static SQLiteDatabase mDatabase; 48 | private static Context mContext; 49 | 50 | // HashMap cache 51 | private static HashMap sCacheInfo = new HashMap<>(); 52 | 53 | 54 | /** 55 | * @param context 56 | */ 57 | private AppDatabaseHelper(Context context) { 58 | super(context.getApplicationContext(), DATABASE_NAME, null, DATABASE_VERSION); 59 | } 60 | 61 | private static AppDatabaseHelper sHelper; 62 | 63 | public static AppDatabaseHelper getInstance(Context context) { 64 | mContext = context; 65 | 66 | // check 67 | if (sHelper == null) { 68 | sHelper = new AppDatabaseHelper(context); 69 | } 70 | 71 | return sHelper; 72 | } 73 | 74 | /** 75 | * Khởi tạo đối tượng mDatabase 76 | */ 77 | private static void setDbInstance() { 78 | mDatabase = Holder.mInstance.getWritableDatabase(); 79 | } 80 | 81 | @Override 82 | public void onCreate(SQLiteDatabase sqLiteDatabase) { 83 | try { 84 | // Create table 85 | String createSessionTable = "create table if not exists " + 86 | TABLE_NAME + " (" + BaseColumns._ID + " integer primary key autoincrement," 87 | + COLUMN_BLID + " BLOB," 88 | + COLUMN_BLID_CONTACT + " BLOB," 89 | + COLUMN_MAC_ID + " text," 90 | + COLUMN_RSSI + " integer," 91 | + COLUMN_TX_POWER + " integer," 92 | + COLUMN_STATE + " integer," 93 | + COLUMN_TIME + " long);"; 94 | sqLiteDatabase.execSQL(createSessionTable); 95 | } catch (Exception e) { 96 | e.printStackTrace(); 97 | } 98 | } 99 | 100 | @Override 101 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 102 | 103 | } 104 | 105 | /** 106 | * Mo DB 107 | * @return 108 | */ 109 | public boolean openDatabase() { 110 | synchronized (this) { 111 | try { 112 | if ((mDatabase == null) || (!mDatabase.isOpen())) { 113 | setDbInstance(); 114 | } 115 | 116 | return true; 117 | } catch (Exception e) { 118 | 119 | return false; 120 | } 121 | } 122 | } 123 | 124 | /** 125 | * Add trace info 126 | * @param blidContact 127 | * @param rssi 128 | * @param txPower 129 | * @return 130 | */ 131 | public long insertInfoTrace(byte[] blidContact, int rssi, int txPower) { 132 | long ret = -1; 133 | 134 | // Check 135 | if (blidContact != null && isInsert(AppUtils.convertBytesToHex(blidContact))) { 136 | 137 | // Open 138 | openDatabase(); 139 | 140 | try { 141 | long time = System.currentTimeMillis(); 142 | 143 | // Data insert 144 | final ContentValues contentValues = new ContentValues(); 145 | contentValues.put(COLUMN_BLID, BluezoneIdGenerator.getInstance(mContext).getBluezoneId()); 146 | contentValues.put(COLUMN_BLID_CONTACT, blidContact); 147 | contentValues.put(COLUMN_RSSI, rssi); 148 | contentValues.put(COLUMN_TX_POWER, txPower); 149 | contentValues.put(COLUMN_TIME, time); 150 | 151 | // insert 152 | ret = mDatabase.insertOrThrow(TABLE_NAME, null, contentValues); 153 | } catch (Exception e) { 154 | e.printStackTrace(); 155 | } 156 | 157 | // Insert DB ngoai 158 | // BackupUtils.insertExternalDatabase(mContext, userId, rssi); 159 | 160 | // Check backup 161 | // BackupUtils.backupDatabase(mContext); 162 | } 163 | 164 | return ret; 165 | } 166 | 167 | /** 168 | * Them trace info 169 | * @param macId 170 | * @param rssi 171 | * @param txPower 172 | * @return 173 | */ 174 | public long insertMacIdTrace(String macId, int rssi, int txPower) { 175 | long ret = -1; 176 | 177 | // Check 178 | if (isInsert(macId)) { 179 | 180 | // Open 181 | openDatabase(); 182 | 183 | try { 184 | long time = System.currentTimeMillis(); 185 | 186 | // Data insert 187 | final ContentValues contentValues = new ContentValues(); 188 | contentValues.put(COLUMN_BLID, BluezoneIdGenerator.getInstance(mContext).getBluezoneId()); 189 | contentValues.put(COLUMN_TIME, time); 190 | contentValues.put(COLUMN_MAC_ID, macId); 191 | contentValues.put(COLUMN_RSSI, rssi); 192 | contentValues.put(COLUMN_TX_POWER, txPower); 193 | 194 | // insert 195 | ret = mDatabase.insertOrThrow(TABLE_NAME, null, contentValues); 196 | } catch (Exception e) { 197 | e.printStackTrace(); 198 | } 199 | 200 | // Insert DB ngoai 201 | // BackupUtils.insertExternalDatabase(mContext, macId, devices, rssi); 202 | 203 | // Check backup 204 | // BackupUtils.backupDatabase(mContext); 205 | } 206 | 207 | return ret; 208 | } 209 | 210 | /** 211 | * Is Expried 212 | * @param info 213 | */ 214 | private static boolean isInsert(String info) { 215 | boolean ret = true; 216 | try { 217 | // Check 218 | if (!TextUtils.isEmpty(info)) { 219 | // Get current time 220 | long time = System.currentTimeMillis(); 221 | 222 | // Check mapp 223 | Set setRemove = new HashSet<>(); 224 | 225 | // Loop 226 | for (Map.Entry entry : sCacheInfo.entrySet()) { 227 | // Check time 228 | if ((time - entry.getValue() >= AppConstants.Config.TIME_DELAY_INSERT)) { 229 | 230 | // List remove 231 | setRemove.add(entry.getKey()); 232 | } else if (info.equals(entry.getKey())) { 233 | // Kho them vao 234 | ret = false; 235 | } 236 | } 237 | 238 | // Remove time > 239 | if (setRemove.size() > 0) { 240 | sCacheInfo.keySet().removeAll(setRemove); 241 | } 242 | 243 | // check insert 244 | if (ret) { 245 | // Them vao 246 | sCacheInfo.put(info, time); 247 | } 248 | } else { 249 | ret = false; 250 | } 251 | } catch (Exception e) { 252 | e.printStackTrace(); 253 | 254 | ret = false; 255 | } 256 | 257 | return ret; 258 | } 259 | 260 | /** 261 | * Đếm số lượng bản ghi 262 | * 263 | * @return số lượng thôi ^^ 264 | */ 265 | public int countItems() { 266 | Cursor cursor = null; 267 | 268 | // Open 269 | openDatabase(); 270 | 271 | int ret = 0; 272 | try { 273 | cursor = mDatabase.rawQuery("select count(*) from " + TABLE_NAME, null); 274 | cursor.moveToFirst(); 275 | ret = cursor.getInt(0); 276 | } catch (Exception e) { 277 | e.printStackTrace(); 278 | } finally { 279 | if (cursor != null) { 280 | cursor.close(); 281 | } 282 | } 283 | 284 | return ret; 285 | } 286 | 287 | /** 288 | * Get all data 289 | * @param listBlid 290 | * @return 291 | */ 292 | public Cursor getCursorData(String[] listBlid) { 293 | // ret 294 | Cursor cursor = null; 295 | 296 | // open 297 | openDatabase(); 298 | 299 | // Check 300 | if (listBlid == null || listBlid.length == 0) { 301 | cursor = mDatabase.query(TABLE_NAME, null, null, 302 | null, null, null, null, null); 303 | } else { 304 | cursor = mDatabase.query(TABLE_NAME, null, 305 | COLUMN_BLID_CONTACT + " IN('" + TextUtils.join("', '", listBlid) + "')", 306 | null, null, null, null, null); 307 | } 308 | 309 | return cursor; 310 | } 311 | 312 | /** 313 | * is Trace 314 | * @param bluezoneId 315 | * @return 316 | */ 317 | public boolean isTrace(byte[] bluezoneId, long timeStart, long timeEnd) { 318 | 319 | boolean ret = false; 320 | 321 | // ret 322 | Cursor cursor = null; 323 | 324 | // open 325 | openDatabase(); 326 | 327 | try { 328 | cursor = mDatabase.query(TABLE_NAME, null, "hex( + " + COLUMN_BLID_CONTACT + ") = ? and " + 329 | COLUMN_TIME + " >= ? and " + COLUMN_TIME + " <= ?", 330 | new String[]{AppUtils.convertBytesToHex(bluezoneId), String.valueOf(timeStart), String.valueOf(timeEnd)}, 331 | null, null, null, null); 332 | if (cursor != null && cursor.getCount() > 0) { 333 | ret = true; 334 | } 335 | } catch (Exception e) { 336 | e.printStackTrace(); 337 | } finally { 338 | if (cursor != null) { 339 | cursor.close(); 340 | } 341 | } 342 | 343 | return ret; 344 | } 345 | 346 | /** 347 | * Get all data 348 | * @return 349 | */ 350 | public Cursor getCursorData() { 351 | // ret 352 | Cursor cursor = null; 353 | 354 | // open 355 | openDatabase(); 356 | 357 | cursor = mDatabase.query(TABLE_NAME, null, null, 358 | null, null, null, null, null); 359 | return cursor; 360 | } 361 | 362 | /** 363 | * Get all data 364 | * @return 365 | */ 366 | public Cursor getCursorData(long timeStart) { 367 | // ret 368 | Cursor cursor = null; 369 | 370 | // open 371 | openDatabase(); 372 | 373 | cursor = mDatabase.query(TABLE_NAME, null, COLUMN_TIME + " >= ? ", 374 | new String[]{String.valueOf(timeStart)}, 375 | null, null, null, null); 376 | return cursor; 377 | } 378 | 379 | @Override 380 | protected void finalize() throws Throwable { 381 | if (Holder.mInstance != null) { 382 | Holder.mInstance.close(); 383 | } 384 | 385 | super.finalize(); 386 | } 387 | 388 | private static class Holder { 389 | static final AppDatabaseHelper mInstance = new AppDatabaseHelper(mContext); 390 | } 391 | } -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/database/CacheDatabaseHelper.java: -------------------------------------------------------------------------------- 1 | package com.scan.database; 2 | 3 | import android.content.ContentValues; 4 | import android.content.Context; 5 | import android.database.Cursor; 6 | import android.database.sqlite.SQLiteDatabase; 7 | import android.database.sqlite.SQLiteOpenHelper; 8 | import android.provider.BaseColumns; 9 | 10 | import com.scan.bluezoneid.BluezoneIdUtils; 11 | import com.scan.model.CacheBleScan; 12 | 13 | /** 14 | * @author khanhxu 15 | */ 16 | public class CacheDatabaseHelper extends SQLiteOpenHelper { 17 | 18 | // Name db 19 | private static final String DATABASE_NAME = "app_cache_2.db"; 20 | private static final int DATABASE_VERSION = 1; 21 | 22 | // Table 23 | private static final String TABLE_NAME = "connect_info"; 24 | private static final String COLUMN_CONNECT_BLID_ID = "blid_id"; // user_id 25 | private static final String COLUMN_CONNECT_MAC_ID = "mac_id"; // mac 26 | private static final String COLUMN_CONNECT_TIME = "time"; // connect time 27 | 28 | // Index 29 | private static final int COLUMN_INDEX_BLID_ID = 1; 30 | private static final int COLUMN_INDEX_CONNECT_MAC_ID = 2; 31 | private static final int COLUMN_INDEX_CONNECT_TIME = 3; 32 | 33 | // Sql 34 | private static SQLiteDatabase mDatabase; 35 | private static Context mContext; 36 | 37 | /** 38 | * @param context 39 | */ 40 | private CacheDatabaseHelper(Context context) { 41 | super(context.getApplicationContext(), DATABASE_NAME, null, DATABASE_VERSION); 42 | } 43 | 44 | private static CacheDatabaseHelper sHelper; 45 | 46 | /** 47 | * init 48 | * @param context 49 | * @return 50 | */ 51 | public static CacheDatabaseHelper getInstance(Context context) { 52 | mContext = context; 53 | 54 | // check 55 | if (sHelper == null) { 56 | sHelper = new CacheDatabaseHelper(context); 57 | } 58 | 59 | return sHelper; 60 | } 61 | 62 | /** 63 | * init mDatabase 64 | */ 65 | private static void setDbInstance() { 66 | mDatabase = Holder.mInstance.getWritableDatabase(); 67 | } 68 | 69 | @Override 70 | public void onCreate(SQLiteDatabase sqLiteDatabase) { 71 | try { 72 | // Bang tin tuong 73 | String createSessionTable = "create table if not exists " + 74 | TABLE_NAME + " (" + BaseColumns._ID + " integer primary key autoincrement," 75 | + COLUMN_CONNECT_BLID_ID + " BLOB," 76 | + COLUMN_CONNECT_MAC_ID + " text," 77 | + COLUMN_CONNECT_TIME + " long);"; 78 | sqLiteDatabase.execSQL(createSessionTable); 79 | } catch (Exception e) { 80 | e.printStackTrace(); 81 | } 82 | } 83 | 84 | @Override 85 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 86 | 87 | } 88 | 89 | /** 90 | * Open DB 91 | * @return 92 | */ 93 | public boolean openDatabase() { 94 | synchronized (this) { 95 | try { 96 | if ((mDatabase == null) || (!mDatabase.isOpen())) { 97 | setDbInstance(); 98 | } 99 | 100 | return true; 101 | } catch (Exception e) { 102 | 103 | return false; 104 | } 105 | } 106 | } 107 | 108 | /** 109 | * Add conneted 110 | * @param blid 111 | * @param macId 112 | * @return 113 | */ 114 | public long insertConnected(byte[] blid, String macId) { 115 | long ret = -1; 116 | 117 | // Open 118 | openDatabase(); 119 | 120 | try { 121 | // Data insert 122 | final ContentValues contentValues = new ContentValues(); 123 | contentValues.put(COLUMN_CONNECT_BLID_ID, blid); 124 | contentValues.put(COLUMN_CONNECT_MAC_ID, macId); 125 | contentValues.put(COLUMN_CONNECT_TIME, System.currentTimeMillis()); 126 | 127 | // insert 128 | ret = mDatabase.insertOrThrow(TABLE_NAME, null, contentValues); 129 | } catch (Exception e) { 130 | e.printStackTrace(); 131 | } 132 | 133 | return ret; 134 | } 135 | 136 | /** 137 | * Get blid 138 | * @param macId 139 | * @return 140 | */ 141 | public byte[] getBluezoneId(String macId) { 142 | byte[] ret = null; 143 | 144 | // Open 145 | openDatabase(); 146 | 147 | // Cursor 148 | Cursor cursor = null; 149 | try { 150 | // Lay thong tin 151 | cursor = mDatabase.query(TABLE_NAME, null, COLUMN_CONNECT_MAC_ID + "= ?", 152 | new String[]{macId}, null, null, null, null); 153 | 154 | // Check 155 | if (cursor != null && cursor.moveToFirst()) { 156 | long time = cursor.getLong(COLUMN_INDEX_CONNECT_TIME); 157 | if (!BluezoneIdUtils.isBluezoneIdChanged(mContext, time, System.currentTimeMillis())) { 158 | ret = cursor.getBlob(COLUMN_INDEX_BLID_ID); 159 | } 160 | } 161 | } catch (Exception e) { 162 | e.printStackTrace(); 163 | } finally { 164 | // Close 165 | if (cursor != null) { 166 | cursor.close(); 167 | } 168 | } 169 | 170 | return ret; 171 | } 172 | 173 | /** 174 | * Get blid 175 | * @param macId 176 | * @return 177 | */ 178 | public CacheBleScan getCacheBleScan(String macId) { 179 | CacheBleScan ret = null; 180 | 181 | // Open 182 | openDatabase(); 183 | 184 | // Cursor 185 | Cursor cursor = null; 186 | try { 187 | // Lay thong tin 188 | cursor = mDatabase.query(TABLE_NAME, null, COLUMN_CONNECT_MAC_ID + "= ?", 189 | new String[]{macId}, null, null, null, null); 190 | 191 | // Check 192 | if (cursor != null && cursor.moveToFirst()) { 193 | ret = new CacheBleScan(cursor.getBlob(COLUMN_INDEX_BLID_ID), cursor.getLong(COLUMN_INDEX_CONNECT_TIME)); 194 | } 195 | } catch (Exception e) { 196 | e.printStackTrace(); 197 | } finally { 198 | // Close 199 | if (cursor != null) { 200 | cursor.close(); 201 | } 202 | } 203 | 204 | return ret; 205 | } 206 | 207 | @Override 208 | protected void finalize() throws Throwable { 209 | if (Holder.mInstance != null) { 210 | Holder.mInstance.close(); 211 | } 212 | 213 | super.finalize(); 214 | } 215 | 216 | private static class Holder { 217 | public static final CacheDatabaseHelper mInstance = new CacheDatabaseHelper(mContext); 218 | } 219 | } -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/gatt/GattConnectSession.java: -------------------------------------------------------------------------------- 1 | package com.scan.gatt; 2 | 3 | import android.bluetooth.BluetoothDevice; 4 | import android.bluetooth.BluetoothGatt; 5 | import android.bluetooth.BluetoothGattCallback; 6 | import android.bluetooth.BluetoothGattCharacteristic; 7 | import android.bluetooth.BluetoothGattService; 8 | import android.bluetooth.BluetoothProfile; 9 | import android.bluetooth.le.ScanResult; 10 | import android.content.Context; 11 | import android.os.Build; 12 | 13 | import com.scan.AppConstants; 14 | import com.scan.AppUtils; 15 | 16 | /** 17 | * Class connect iOS and read Characteristic 18 | * @author khanhxu 19 | */ 20 | public class GattConnectSession { 21 | private ScanResult mScanResult; 22 | private BluetoothGatt mBluetoothGatt; 23 | private long mTimeStartConnect; 24 | private ConnectDataCallback mConnectDataCallback; 25 | private Context mContext; 26 | 27 | // RSSI connect 28 | // private int mRssiConnect; 29 | 30 | /** 31 | * Callback 32 | */ 33 | public interface ConnectDataCallback { 34 | 35 | void onReadBluezoneId(byte[] bluezoneId, String macId, int rssi); 36 | } 37 | 38 | /** 39 | * Init 40 | * @param scanResult 41 | */ 42 | public GattConnectSession(Context context, ScanResult scanResult, ConnectDataCallback callback) { 43 | mScanResult = scanResult; 44 | mContext = context; 45 | mConnectDataCallback = callback; 46 | } 47 | 48 | /** 49 | * Init start connect 50 | */ 51 | public void startConnect() { 52 | final BluetoothDevice bluetoothDevice = mScanResult.getDevice(); 53 | if (bluetoothDevice != null) { 54 | final BluetoothGattCallback gattCallback = new BluetoothGattCallback() { 55 | @Override 56 | public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 57 | super.onConnectionStateChange(gatt, status, newState); 58 | // Check status 59 | if (newState == BluetoothProfile.STATE_CONNECTED) { 60 | gatt.requestMtu(512); 61 | } else if (newState == BluetoothProfile.STATE_DISCONNECTED || newState == BluetoothProfile.STATE_DISCONNECTING) { 62 | closeAndDisconnectBluetoothGatt(); 63 | } 64 | } 65 | 66 | @Override 67 | public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { 68 | gatt.discoverServices(); 69 | } 70 | 71 | @Override 72 | public void onServicesDiscovered(BluetoothGatt gatt, int status) { 73 | super.onServicesDiscovered(gatt, status); 74 | // Check status 75 | if (status == BluetoothGatt.GATT_SUCCESS) { 76 | BluetoothGattService bluetoothGattService = gatt.getService(AppUtils.BLE_UUID_IOS.getUuid()); 77 | if (bluetoothGattService != null) { 78 | // Read characteristic 79 | BluetoothGattCharacteristic gattCharacteristic = bluetoothGattService.getCharacteristic(AppUtils.BLE_UUID_CHARECTIC); 80 | if (gattCharacteristic != null) { 81 | // if (!gatt.readRemoteRssi()) { 82 | // mRssiConnect = mScanResult.getRssi(); 83 | // } 84 | 85 | if (!gatt.readCharacteristic(gattCharacteristic)) { 86 | closeAndDisconnectBluetoothGatt(); 87 | } 88 | } else { 89 | if (mConnectDataCallback != null) { 90 | mConnectDataCallback.onReadBluezoneId(AppConstants.BLUEZONE_BYTE_NONE, gatt.getDevice().getAddress(), mScanResult.getRssi()); 91 | } 92 | closeAndDisconnectBluetoothGatt(); 93 | } 94 | } else { 95 | if (mConnectDataCallback != null) { 96 | mConnectDataCallback.onReadBluezoneId(AppConstants.BLUEZONE_BYTE_NONE, gatt.getDevice().getAddress(), mScanResult.getRssi()); 97 | } 98 | closeAndDisconnectBluetoothGatt(); 99 | } 100 | } else { 101 | closeAndDisconnectBluetoothGatt(); 102 | } 103 | } 104 | 105 | @Override 106 | public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { 107 | super.onCharacteristicRead(gatt, characteristic, status); 108 | if (characteristic != null && gatt != null && gatt.getDevice() != null) { 109 | // check 110 | if (mConnectDataCallback != null) { 111 | mConnectDataCallback.onReadBluezoneId(characteristic.getValue(), gatt.getDevice().getAddress(), mScanResult.getRssi()); 112 | } 113 | } 114 | 115 | closeAndDisconnectBluetoothGatt(); 116 | } 117 | 118 | @Override 119 | public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { 120 | super.onReadRemoteRssi(gatt, rssi, status); 121 | // lay rssi 122 | // mRssiConnect = rssi; 123 | } 124 | }; 125 | 126 | mTimeStartConnect = System.currentTimeMillis(); 127 | 128 | // Start 129 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 130 | mBluetoothGatt = bluetoothDevice.connectGatt(mContext, false, gattCallback, BluetoothDevice.TRANSPORT_LE); 131 | } else { 132 | mBluetoothGatt = bluetoothDevice.connectGatt(mContext, false, gattCallback); 133 | } 134 | } else { 135 | closeAndDisconnectBluetoothGatt(); 136 | } 137 | } 138 | 139 | /** 140 | * Get session ScanResult 141 | * @return 142 | */ 143 | public ScanResult getScanResult() { 144 | return mScanResult; 145 | } 146 | 147 | /** 148 | * Check finish 149 | * @return 150 | */ 151 | public boolean isFinished() { 152 | return mBluetoothGatt == null; 153 | } 154 | 155 | /** 156 | * Check timeout disconnect 157 | */ 158 | public void checkTimeout() { 159 | if (System.currentTimeMillis() - mTimeStartConnect > AppConstants.Config.TIMEOUT_CONNECT) { 160 | closeAndDisconnectBluetoothGatt(); 161 | } 162 | } 163 | 164 | /** 165 | * Close and disconnect 166 | */ 167 | public synchronized void closeAndDisconnectBluetoothGatt() { 168 | if (mBluetoothGatt != null) { 169 | mBluetoothGatt.disconnect(); 170 | mBluetoothGatt.close(); 171 | mBluetoothGatt = null; 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/model/CacheBleScan.java: -------------------------------------------------------------------------------- 1 | package com.scan.model; 2 | 3 | /** 4 | * Model cache scan 5 | * @author khanhxu 6 | */ 7 | public class CacheBleScan { 8 | private long mTime; 9 | private byte[] mBluezoneId; 10 | 11 | public CacheBleScan(byte[] bluezoneId, long time) { 12 | mBluezoneId = bluezoneId; 13 | mTime = time; 14 | } 15 | 16 | public byte[] getBluezoneId() { 17 | return mBluezoneId; 18 | } 19 | 20 | public long getTime() { 21 | return mTime; 22 | } 23 | 24 | public void setBluezoneId(byte[] bluezoneId) { 25 | mBluezoneId = bluezoneId; 26 | } 27 | 28 | public void setTime(long time) { 29 | mTime = time; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/model/ScanConfig.java: -------------------------------------------------------------------------------- 1 | package com.scan.model; 2 | 3 | /** 4 | * Model config thực hiện việc interval and duration 5 | * @author khanhxu 6 | */ 7 | 8 | public class ScanConfig { 9 | private long mInterval; 10 | private long mDuration; 11 | 12 | public ScanConfig(long duration, long interval) { 13 | mInterval = interval; 14 | mDuration = duration; 15 | } 16 | 17 | public long getDuration() { 18 | return mDuration; 19 | } 20 | 21 | public long getInterval() { 22 | return mInterval; 23 | } 24 | 25 | public void setDuration(long timeSleep) { 26 | mDuration = timeSleep; 27 | } 28 | 29 | public void setInterval(long tineScan) { 30 | mInterval = tineScan; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/notification/NotificationReceiver.java: -------------------------------------------------------------------------------- 1 | package com.scan.notification; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationManager; 5 | import android.content.BroadcastReceiver; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | 9 | import androidx.core.app.NotificationCompat; 10 | 11 | import com.scan.AppConstants; 12 | import com.scan.R; 13 | import com.scan.preference.AppPreferenceManager; 14 | 15 | import static androidx.core.app.NotificationCompat.PRIORITY_MIN; 16 | 17 | public class NotificationReceiver extends BroadcastReceiver { 18 | @Override 19 | public void onReceive(Context context, Intent intent) { 20 | // Build notification based on Intent 21 | String language = AppPreferenceManager.getInstance(context).getLanguage(); 22 | 23 | String subText = ""; 24 | String message = ""; 25 | String title = ""; 26 | String bigText = ""; 27 | if(language.equals("vi")) { 28 | subText = intent.getStringExtra("subText"); 29 | message = intent.getStringExtra("message"); 30 | bigText = intent.getStringExtra("bigText"); 31 | title = intent.getStringExtra("title"); 32 | } else { 33 | subText = intent.getStringExtra("subText_en"); 34 | message = intent.getStringExtra("message"); 35 | bigText = intent.getStringExtra("bigText_en"); 36 | title = intent.getStringExtra("title_en"); 37 | } 38 | 39 | if (bigText == null) { 40 | bigText = message; 41 | } 42 | 43 | Notification notification = new NotificationCompat.Builder(context, AppConstants.NOTIFICATION_CHANNEL_ID) 44 | .setPriority(PRIORITY_MIN) 45 | .setSmallIcon(R.mipmap.icon_bluezone_service) 46 | .setSubText(subText) // Sub text 47 | .setContentTitle(title) // title 48 | .setContentText(message) // bigText 49 | .setStyle(new NotificationCompat.BigTextStyle().bigText(bigText)) 50 | .build(); 51 | // Show notification 52 | NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 53 | manager.notify(intent.getIntExtra("id", 1), notification); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/preference/AbstractPreferenceManager.java: -------------------------------------------------------------------------------- 1 | package com.scan.preference; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.content.SharedPreferences; 6 | import android.os.Build; 7 | import android.preference.PreferenceManager; 8 | 9 | import java.util.Set; 10 | 11 | public abstract class AbstractPreferenceManager { 12 | 13 | /** 14 | * The SharePreferences 15 | */ 16 | private final SharedPreferences mPref; 17 | 18 | /** 19 | * Ham khoi tao 20 | * 21 | * @param context 22 | */ 23 | public AbstractPreferenceManager(Context context) { 24 | mPref = PreferenceManager.getDefaultSharedPreferences(context); 25 | } 26 | 27 | // Cac ham put - luu tru du lieu theo key value 28 | public void putInt(String KEY, int value) { 29 | mPref.edit().putInt(KEY, value).commit(); 30 | } 31 | 32 | public void putLong(String KEY, long value) { 33 | mPref.edit().putLong(KEY, value).commit(); 34 | } 35 | 36 | public void putFloat(String KEY, float value) { 37 | mPref.edit().putFloat(KEY, value).commit(); 38 | } 39 | 40 | public void putBoolean(String KEY, boolean value) { 41 | mPref.edit().putBoolean(KEY, value).commit(); 42 | } 43 | 44 | public void putString(String KEY, String value) { 45 | mPref.edit().putString(KEY, value).commit(); 46 | } 47 | 48 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 49 | public void putStringSet(String KEY, Set value) { 50 | mPref.edit().putStringSet(KEY, value).commit(); 51 | } 52 | 53 | // cac ham get, lay du lieu voi gia tri mac dinh 54 | public int getInt(String KEY, int defaultVlue) { 55 | return mPref.getInt(KEY, defaultVlue); 56 | } 57 | 58 | public long getLong(String KEY, long defaultVlue) { 59 | return mPref.getLong(KEY, defaultVlue); 60 | } 61 | 62 | public float getFloat(String KEY, float defaultVlue) { 63 | return mPref.getFloat(KEY, defaultVlue); 64 | } 65 | 66 | public boolean getBoolean(String KEY, boolean defaultVlue) { 67 | return mPref.getBoolean(KEY, defaultVlue); 68 | } 69 | 70 | public String getString(String KEY, String defaultVlue) { 71 | return mPref.getString(KEY, defaultVlue); 72 | } 73 | 74 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 75 | public Set getStringSet(String KEY, Set defaultVlue) { 76 | return mPref.getStringSet(KEY, defaultVlue); 77 | } 78 | 79 | public void remove(String key) { 80 | mPref.edit().remove(key).apply(); 81 | } 82 | 83 | public boolean clear() { 84 | return mPref.edit().clear().commit(); 85 | } 86 | 87 | public boolean contain(String key) { 88 | return mPref.contains(key); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/android/src/main/java/com/scan/preference/AppPreferenceManager.java: -------------------------------------------------------------------------------- 1 | package com.scan.preference; 2 | 3 | import android.content.Context; 4 | 5 | import com.scan.AppConstants; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * class dung de luu tru cac du lieu can thiet nhat cua ung dung duoc goi chung boi ta cac module. 12 | */ 13 | public class AppPreferenceManager extends AbstractPreferenceManager { 14 | // Instance 15 | private static AppPreferenceManager sInstance; 16 | 17 | /** 18 | * Contractor 19 | * 20 | * @param context 21 | */ 22 | private AppPreferenceManager(Context context) { 23 | super(context); 24 | } 25 | 26 | /** 27 | * Use to initialization object AppPreferenceManager 28 | * 29 | * @param context app Context 30 | */ 31 | private static synchronized void initializeInstance(Context context) { 32 | if (sInstance == null) { 33 | sInstance = new AppPreferenceManager(context); 34 | } 35 | } 36 | 37 | /** 38 | * Use to initialization and get object AppPreferenceManager 39 | * 40 | * @param context app context 41 | */ 42 | public static synchronized AppPreferenceManager getInstance(Context context) { 43 | if (sInstance == null) { 44 | initializeInstance(context); 45 | } 46 | 47 | return sInstance; 48 | } 49 | 50 | /** 51 | * Set blid 52 | * @param blid 53 | */ 54 | public void setBlid(String blid) { 55 | putString(PreferenceConstants.BLID, blid); 56 | } 57 | 58 | /** 59 | * Get blid 60 | */ 61 | public String getBlid() { 62 | return getString(PreferenceConstants.BLID, "Bluezoner"); 63 | } 64 | 65 | /** 66 | * Set config scan ble 67 | * @param time 68 | */ 69 | public void setConfigScanBleDuration(long time) { 70 | putLong(PreferenceConstants.CONFIG_SEVER_SCAN_BLE_DURATION, time); 71 | } 72 | 73 | /** 74 | * Get config scan ble 75 | */ 76 | public long getConfigScanBleDuration(long timeDefault) { 77 | return getLong(PreferenceConstants.CONFIG_SEVER_SCAN_BLE_DURATION, timeDefault); 78 | } 79 | 80 | /** 81 | * Set config scan ble 82 | * @param time 83 | */ 84 | public void setConfigScanBleInterval(long time) { 85 | putLong(PreferenceConstants.CONFIG_SERVER_SCAN_BLE_INTERVAL, time); 86 | } 87 | 88 | /** 89 | * Get config scan ble 90 | */ 91 | public long getConfigScanBleInterval(long timeDefault) { 92 | return getLong(PreferenceConstants.CONFIG_SERVER_SCAN_BLE_INTERVAL, timeDefault); 93 | } 94 | 95 | /** 96 | * Set config broadcast ble 97 | * @param time 98 | */ 99 | public void setConfigBroadcastBleDuration(long time) { 100 | putLong(PreferenceConstants.CONFIG_SERVER_BROADCAST_BLE_DURATION, time); 101 | } 102 | 103 | /** 104 | * Get config broadcast ble 105 | */ 106 | public long getConfigBroadcasBleDuration(long timeDefault) { 107 | return getLong(PreferenceConstants.CONFIG_SERVER_BROADCAST_BLE_DURATION, timeDefault); 108 | } 109 | 110 | /** 111 | * Set config broadcast ble 112 | * @param time 113 | */ 114 | public void setConfigBroadcastBleInterval(long time) { 115 | putLong(PreferenceConstants.CONFIG_SERVER_BROADCAST_BLE_INTERVAL, time); 116 | } 117 | 118 | /** 119 | * Get config broadcast ble 120 | */ 121 | public long getConfigBroadcasBleInterval(long timeDefault) { 122 | return getLong(PreferenceConstants.CONFIG_SERVER_BROADCAST_BLE_INTERVAL, timeDefault); 123 | } 124 | 125 | /** 126 | * Set config scan devices 127 | * @param time 128 | */ 129 | public void setConfigScanDevicesDuration(long time) { 130 | putLong(PreferenceConstants.CONFIG_SERVER_SCAN_DEVICES_DURATION, time); 131 | } 132 | 133 | /** 134 | * Get config scan devices 135 | */ 136 | public long getConfigScanDevicesDuration(long timeDefault) { 137 | return getLong(PreferenceConstants.CONFIG_SERVER_SCAN_DEVICES_DURATION, timeDefault); 138 | } 139 | 140 | /** 141 | * Set config scan devices 142 | * @param time 143 | */ 144 | public void setConfigScanDevicesInterval(long time) { 145 | putLong(PreferenceConstants.CONFIG_SERVER_SCAN_DEVICES_INTERVAL, time); 146 | } 147 | 148 | /** 149 | * Get config scan devices 150 | */ 151 | public long getConfigScanDevicesInterval(long timeDefault) { 152 | return getLong(PreferenceConstants.CONFIG_SERVER_SCAN_DEVICES_INTERVAL, timeDefault); 153 | } 154 | 155 | /** 156 | * Set config interval insert db 157 | * @param time 158 | */ 159 | public void setConfigInsertDb(long time) { 160 | putLong(PreferenceConstants.CONFIG_SERVER_INSERT_DB, time); 161 | } 162 | 163 | /** 164 | * Get config interval insert db 165 | */ 166 | public long getConfigInsertDb(long timeDefault) { 167 | return getLong(PreferenceConstants.CONFIG_SERVER_INSERT_DB, timeDefault); 168 | } 169 | 170 | /** 171 | * Set config interval insert db 172 | * @param time 173 | */ 174 | public void setConfigBackupDb(long time) { 175 | putLong(PreferenceConstants.CONFIG_SERVER_BACKUP_DB, time); 176 | } 177 | 178 | /** 179 | * Get config interval insert db 180 | */ 181 | public long getConfigBackupDb(long timeDefault) { 182 | return getLong(PreferenceConstants.CONFIG_SERVER_BACKUP_DB, timeDefault); 183 | } 184 | 185 | /** 186 | * Set config log file from server 187 | * @param isLog 188 | */ 189 | public void setConfigLogFile(boolean isLog) { 190 | putBoolean(PreferenceConstants.CONFIG_LOG_FILE, isLog); 191 | } 192 | 193 | /** 194 | * Get config log file from server 195 | */ 196 | public boolean getConfigLogFile() { 197 | return getBoolean(PreferenceConstants.CONFIG_LOG_FILE, false); 198 | } 199 | 200 | /** 201 | * Set config log battery from server 202 | * @param isLog 203 | */ 204 | public void setConfigLogBattery(boolean isLog) { 205 | putBoolean(PreferenceConstants.CONFIG_LOG_BATTERY, isLog); 206 | } 207 | 208 | /** 209 | * Get config log battery from server 210 | */ 211 | public boolean getConfigLogBattery() { 212 | return getBoolean(PreferenceConstants.CONFIG_LOG_BATTERY, false); 213 | } 214 | 215 | /** 216 | * Set time last backup 217 | * @param time 218 | */ 219 | public void setLastBackup(long time) { 220 | putLong(PreferenceConstants.TIME_LAST_BACKUP, time); 221 | } 222 | 223 | /** 224 | * Get time last backup 225 | */ 226 | public long getLastBackup() { 227 | return getLong(PreferenceConstants.TIME_LAST_BACKUP, 0); 228 | } 229 | 230 | /** 231 | * Set config enable bluetooth interval 232 | * @param time 233 | */ 234 | public void setConfigEnableBluetoothInterval(long time) { 235 | putLong(PreferenceConstants.CONFIG_SERVER_ENABLE_BLUETOOTH_INTERVAL, time); 236 | } 237 | 238 | /** 239 | * Get config enable bluetooth interval 240 | */ 241 | public long getConfigEnableBluetoothInterval(long timeDefault) { 242 | return getLong(PreferenceConstants.CONFIG_SERVER_ENABLE_BLUETOOTH_INTERVAL, timeDefault); 243 | } 244 | 245 | public void setConfigCheckIntervalRequestPermission(long time) { 246 | putLong(PreferenceConstants.CONFIG_SERVER_CHECK_NOTIFY_REQUEST_PERMISSON, time); 247 | } 248 | 249 | public long getConfigCheckIntervalRequestPermission(long timeDefault) { 250 | return getLong(PreferenceConstants.CONFIG_SERVER_CHECK_NOTIFY_REQUEST_PERMISSON, timeDefault); 251 | } 252 | 253 | /** 254 | * Set config enable bluetooth battery level 255 | * @param time 256 | */ 257 | public void setConfigEnableBluetoothBatteryLevel(int time) { 258 | putLong(PreferenceConstants.CONFIG_SERVER_ENABLE_BLUETOOTH_BATTERY_LEVEL, time); 259 | } 260 | 261 | /** 262 | * Get config enable bluetooth battery level 263 | */ 264 | public long getConfigEnableBluetoothBatteryLevel(int levelDefault) { 265 | return getInt(PreferenceConstants.CONFIG_SERVER_ENABLE_BLUETOOTH_BATTERY_LEVEL, levelDefault); 266 | } 267 | 268 | /** 269 | * Set config scan devices 270 | * @param isScan 271 | */ 272 | public void setConfigScanDevices(boolean isScan) { 273 | putBoolean(PreferenceConstants.CONFIG_SERVER_SCAN_DEVICES, isScan); 274 | } 275 | 276 | /** 277 | * Get config scan devices 278 | */ 279 | public boolean getConfigScanDevices() { 280 | return getBoolean(PreferenceConstants.CONFIG_SERVER_SCAN_DEVICES, AppConstants.Config.IS_CONFIG_SCAN_DEVICES); 281 | } 282 | 283 | /** 284 | * Set language 285 | * @param language 286 | */ 287 | public void setLanguage(String language) { 288 | putString(PreferenceConstants.LANGUAGE, language); 289 | } 290 | 291 | /** 292 | * Set language 293 | */ 294 | public String getLanguage() { 295 | return getString(PreferenceConstants.LANGUAGE, "vi"); 296 | } 297 | 298 | public void setNotifyRequestBlu( 299 | String bigTextVi, 300 | String bigTextEn, 301 | String subTextVi, 302 | String subTextEn, 303 | String titleVi, 304 | String titleEn, 305 | String messageVi, 306 | String messageEn, 307 | String itemRepeat 308 | ) { 309 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_BIG_TEXT_VI, bigTextVi); 310 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_BIG_TEXT_EN, bigTextEn); 311 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_SUB_TEXT_VI, subTextVi); 312 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_SUB_TEXT_EN, subTextEn); 313 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_TITLE_VI, titleVi); 314 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_TITLE_EN, titleEn); 315 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_MESSAGE_VI, messageVi); 316 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_MESSAGE_EN, messageEn); 317 | putString(PreferenceConstants.NOTIFICATION_BLUETOOTH_REPEAT, itemRepeat); 318 | } 319 | 320 | public Map getNotifyRequestBlue (String language) { 321 | Map result = new HashMap<>(); 322 | result.put("itemRepeat", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_REPEAT, "")); 323 | result.put("bigText", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_BIG_TEXT_VI, "bigTextVi")); 324 | result.put("bigText_en", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_BIG_TEXT_EN, "bigTextEn")); 325 | result.put("subText", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_SUB_TEXT_VI, "subTextVi")); 326 | result.put("subText_en", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_SUB_TEXT_EN, "subTextEn")); 327 | result.put("title", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_TITLE_VI, "titleVi")); 328 | result.put("title_en", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_TITLE_EN, "titleEn")); 329 | result.put("message", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_MESSAGE_VI, "messageVi")); 330 | result.put("message_en", getString(PreferenceConstants.NOTIFICATION_BLUETOOTH_MESSAGE_EN, "messageEn")); 331 | return result; 332 | } 333 | 334 | public void setNotifyRequestLocation( 335 | String bigTextVi, 336 | String bigTextEn, 337 | String subTextVi, 338 | String subTextEn, 339 | String titleVi, 340 | String titleEn, 341 | String messageVi, 342 | String messageEn, 343 | String itemRepeat 344 | ) { 345 | putString(PreferenceConstants.NOTIFICATION_LOCATION_BIG_TEXT_VI, bigTextVi); 346 | putString(PreferenceConstants.NOTIFICATION_LOCATION_BIG_TEXT_EN, bigTextEn); 347 | putString(PreferenceConstants.NOTIFICATION_LOCATION_SUB_TEXT_VI, subTextVi); 348 | putString(PreferenceConstants.NOTIFICATION_LOCATION_SUB_TEXT_EN, subTextEn); 349 | putString(PreferenceConstants.NOTIFICATION_LOCATION_TITLE_VI, titleVi); 350 | putString(PreferenceConstants.NOTIFICATION_LOCATION_TITLE_EN, titleEn); 351 | putString(PreferenceConstants.NOTIFICATION_LOCATION_MESSAGE_VI, messageVi); 352 | putString(PreferenceConstants.NOTIFICATION_LOCATION_MESSAGE_EN, messageEn); 353 | putString(PreferenceConstants.NOTIFICATION_LOCATION_REPEAT, itemRepeat); 354 | } 355 | 356 | public Map getNotifyRequestLocation (String language) { 357 | Map result = new HashMap<>(); 358 | result.put("itemRepeat", getString(PreferenceConstants.NOTIFICATION_LOCATION_REPEAT, "")); 359 | result.put("bigText", getString(PreferenceConstants.NOTIFICATION_LOCATION_BIG_TEXT_VI, "bigTextVi")); 360 | result.put("bigText_en", getString(PreferenceConstants.NOTIFICATION_LOCATION_BIG_TEXT_EN, "bigTextEn")); 361 | result.put("subText", getString(PreferenceConstants.NOTIFICATION_LOCATION_SUB_TEXT_VI, "subTextVi")); 362 | result.put("subText_en", getString(PreferenceConstants.NOTIFICATION_LOCATION_SUB_TEXT_EN, "subTextEn")); 363 | result.put("title", getString(PreferenceConstants.NOTIFICATION_LOCATION_TITLE_VI, "titleVi")); 364 | result.put("title_en", getString(PreferenceConstants.NOTIFICATION_LOCATION_TITLE_EN, "titleEn")); 365 | result.put("message", getString(PreferenceConstants.NOTIFICATION_LOCATION_MESSAGE_VI, "messageVi")); 366 | result.put("message_en", getString(PreferenceConstants.NOTIFICATION_LOCATION_MESSAGE_EN, "messageEn")); 367 | return result; 368 | } 369 | 370 | public void setNotifyRequestPermisson( 371 | String bigTextVi, 372 | String bigTextEn, 373 | String subTextVi, 374 | String subTextEn, 375 | String titleVi, 376 | String titleEn, 377 | String messageVi, 378 | String messageEn, 379 | String itemRepeat 380 | ) { 381 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_BIG_TEXT_VI, bigTextVi); 382 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_BIG_TEXT_EN, bigTextEn); 383 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_SUB_TEXT_VI, subTextVi); 384 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_SUB_TEXT_EN, subTextEn); 385 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_TITLE_VI, titleVi); 386 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_TITLE_EN, titleEn); 387 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_MESSAGE_VI, messageVi); 388 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_MESSAGE_EN, messageEn); 389 | putString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_REPEAT, itemRepeat); 390 | } 391 | 392 | public Map getNotifyRequestPermisson (String language) { 393 | Map result = new HashMap<>(); 394 | result.put("itemRepeat", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_REPEAT, "")); 395 | result.put("bigText", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_BIG_TEXT_VI, "bigTextVi")); 396 | result.put("bigText_en", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_BIG_TEXT_EN, "bigTextEn")); 397 | result.put("subText", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_SUB_TEXT_VI, "subTextVi")); 398 | result.put("subText_en", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_SUB_TEXT_EN, "subTextEn")); 399 | result.put("title", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_TITLE_VI, "titleVi")); 400 | result.put("title_en", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_TITLE_EN, "titleEn")); 401 | result.put("message", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_MESSAGE_VI, "messageVi")); 402 | result.put("message_en", getString(PreferenceConstants.NOTIFICATION_REQUEST_PERMISSON_MESSAGE_EN, "messageEn")); 403 | return result; 404 | } 405 | 406 | // Constant pre 407 | public static class PreferenceConstants { 408 | // Name 409 | public static final String BLID = "user_id"; 410 | public static final String LANGUAGE = "app_language"; 411 | 412 | // config 413 | public static final String CONFIG_SCAN_BLE = "scan_ble"; 414 | public static final String CONFIG_BROADCAST_BLE = "broadcast_ble"; 415 | public static final String CONFIG_SCAN_DEVICES = "scan_devices"; 416 | public static final String CONFIG_SEVER_SCAN_BLE_DURATION = "server_scan_ble_duration"; 417 | public static final String CONFIG_SERVER_SCAN_BLE_INTERVAL = "server_scan_ble_interval"; 418 | public static final String CONFIG_SERVER_BROADCAST_BLE_DURATION = "server_broadcast_ble_duration"; 419 | public static final String CONFIG_SERVER_BROADCAST_BLE_INTERVAL = "server_broadcast_ble_interval"; 420 | public static final String CONFIG_SERVER_SCAN_DEVICES_DURATION = "server_scan_devices_duration"; 421 | public static final String CONFIG_SERVER_SCAN_DEVICES_INTERVAL = "server_scan_devices_interval"; 422 | public static final String CONFIG_SERVER_ENABLE_BLUETOOTH_BATTERY_LEVEL = "sever_enable_bluetooth_battery_level"; 423 | public static final String CONFIG_SERVER_ENABLE_BLUETOOTH_INTERVAL = "sever_enable_bluetooth_interval"; 424 | public static final String CONFIG_SERVER_SCAN_DEVICES = "sever_is_scan_devices"; 425 | public static final String CONFIG_SERVER_INSERT_DB = "server_insert_db"; 426 | public static final String CONFIG_SERVER_BACKUP_DB = "server_backup_db"; 427 | public static final String CONFIG_SERVER_CHECK_NOTIFY_REQUEST_PERMISSON = "server_check_notify_request_"; 428 | 429 | // config log file 430 | public static final String CONFIG_LOG_FILE = "log"; 431 | public static final String CONFIG_LOG_BATTERY= "log_battery"; 432 | 433 | // Time last backup 434 | public static final String TIME_LAST_BACKUP = "time_last_backup"; 435 | 436 | // Notify Content 437 | public static final String NOTIFICATION_BLUETOOTH_BIG_TEXT_VI = "notification_bluetooth_big_text_vi"; 438 | public static final String NOTIFICATION_BLUETOOTH_BIG_TEXT_EN = "notification_bluetooth_big_text_en"; 439 | public static final String NOTIFICATION_BLUETOOTH_SUB_TEXT_VI = "notification_bluetooth_sub_text_vi"; 440 | public static final String NOTIFICATION_BLUETOOTH_SUB_TEXT_EN = "notification_bluetooth_sub_text_en"; 441 | public static final String NOTIFICATION_BLUETOOTH_TITLE_VI = "notification_bluetooth_title_text_vi"; 442 | public static final String NOTIFICATION_BLUETOOTH_TITLE_EN = "notification_bluetooth_title_text_en"; 443 | public static final String NOTIFICATION_BLUETOOTH_MESSAGE_VI = "notification_bluetooth_message_vi"; 444 | public static final String NOTIFICATION_BLUETOOTH_MESSAGE_EN = "notification_bluetooth_message_en"; 445 | public static final String NOTIFICATION_BLUETOOTH_REPEAT = "notification_bluetooth_repeat"; 446 | 447 | public static final String NOTIFICATION_LOCATION_BIG_TEXT_VI = "notification_location_big_text_vi"; 448 | public static final String NOTIFICATION_LOCATION_BIG_TEXT_EN = "notification_location_big_text_en"; 449 | public static final String NOTIFICATION_LOCATION_SUB_TEXT_VI = "notification_location_sub_text_vi"; 450 | public static final String NOTIFICATION_LOCATION_SUB_TEXT_EN = "notification_location_sub_text_en"; 451 | public static final String NOTIFICATION_LOCATION_TITLE_VI = "notification_location_title_text_vi"; 452 | public static final String NOTIFICATION_LOCATION_TITLE_EN = "notification_location_title_text_en"; 453 | public static final String NOTIFICATION_LOCATION_MESSAGE_VI = "notification_location_message_vi"; 454 | public static final String NOTIFICATION_LOCATION_MESSAGE_EN = "notification_location_message_en"; 455 | public static final String NOTIFICATION_LOCATION_REPEAT = "notification_location_repeat"; 456 | 457 | public static final String NOTIFICATION_REQUEST_PERMISSON_BIG_TEXT_VI = "notification_request_permisson_big_text_vi"; 458 | public static final String NOTIFICATION_REQUEST_PERMISSON_BIG_TEXT_EN = "notification_request_permisson_big_text_en"; 459 | public static final String NOTIFICATION_REQUEST_PERMISSON_SUB_TEXT_VI = "notification_request_permisson_sub_text_vi"; 460 | public static final String NOTIFICATION_REQUEST_PERMISSON_SUB_TEXT_EN = "notification_request_permisson_sub_text_en"; 461 | public static final String NOTIFICATION_REQUEST_PERMISSON_TITLE_VI = "notification_request_permisson_title_text_vi"; 462 | public static final String NOTIFICATION_REQUEST_PERMISSON_TITLE_EN = "notification_request_permisson_title_text_en"; 463 | public static final String NOTIFICATION_REQUEST_PERMISSON_MESSAGE_VI = "notification_request_permisson_message_vi"; 464 | public static final String NOTIFICATION_REQUEST_PERMISSON_MESSAGE_EN = "notification_request_permisson_message_en"; 465 | public static final String NOTIFICATION_REQUEST_PERMISSON_REPEAT = "notification_request_permisson_repeat"; 466 | } 467 | } 468 | -------------------------------------------------------------------------------- /lib/android/src/main/res/mipmap-hdpi/icon_bluezone_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BluezoneGlobal/react-native-bluetooth-scan/4a5ce99e34efa4b68f56fae57e087dd94f624d10/lib/android/src/main/res/mipmap-hdpi/icon_bluezone_service.png -------------------------------------------------------------------------------- /lib/android/src/main/res/mipmap-mdpi/icon_bluezone_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BluezoneGlobal/react-native-bluetooth-scan/4a5ce99e34efa4b68f56fae57e087dd94f624d10/lib/android/src/main/res/mipmap-mdpi/icon_bluezone_service.png -------------------------------------------------------------------------------- /lib/android/src/main/res/mipmap-xhdpi/icon_bluezone_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BluezoneGlobal/react-native-bluetooth-scan/4a5ce99e34efa4b68f56fae57e087dd94f624d10/lib/android/src/main/res/mipmap-xhdpi/icon_bluezone_service.png -------------------------------------------------------------------------------- /lib/android/src/main/res/mipmap-xxhdpi/icon_bluezone_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BluezoneGlobal/react-native-bluetooth-scan/4a5ce99e34efa4b68f56fae57e087dd94f624d10/lib/android/src/main/res/mipmap-xxhdpi/icon_bluezone_service.png -------------------------------------------------------------------------------- /lib/android/src/main/res/mipmap-xxxhdpi/icon_bluezone_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BluezoneGlobal/react-native-bluetooth-scan/4a5ce99e34efa4b68f56fae57e087dd94f624d10/lib/android/src/main/res/mipmap-xxxhdpi/icon_bluezone_service.png -------------------------------------------------------------------------------- /lib/android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Bluezone 3 | Bluezone - Khẩu trang điện tử 4 | Bluezone - Electronic mask 5 | Chưa phát hiện F0 nào tiếp xúc gần với bạn ! 6 | Not detected any F0 that is in close contact with you ! 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /lib/android/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /local.properties: -------------------------------------------------------------------------------- 1 | ## This file must *NOT* be checked into Version Control Systems, 2 | # as it contains information specific to your local configuration. 3 | # 4 | # Location of the SDK. This is only used by Gradle. 5 | # For customization when using a Version Control System, please read the 6 | # header note. 7 | #Sun Apr 26 19:23:41 ICT 2020 8 | sdk.dir=/home/cuongnt/Android/Sdk 9 | 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-bluetooth-scan", 3 | "description": "React Native Bluetooth Scan for iOS + Android", 4 | "main": "index.js", 5 | "author": "Bluezone Developer", 6 | "version": "0.0.1", 7 | "scripts": {}, 8 | "keywords": [ 9 | "react", 10 | "react-native", 11 | "react-component" 12 | ], 13 | "peerDependencies": { 14 | "prop-types": "^15.0 || ^16.0", 15 | "react": ">= 16.0 || < 17.0", 16 | "react-native": ">= 0.51" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.4.3", 20 | "@babel/runtime": "^7.4.3", 21 | "@react-native-community/eslint-config": "0.0.5", 22 | "babel-eslint": "^10.0.1", 23 | "babel-plugin-module-resolver": "^3.2.0", 24 | "eslint": "^5.16.0", 25 | "eslint-plugin-import": "^2.17.2", 26 | "eslint-plugin-jsx-a11y": "^6.2.1", 27 | "eslint-plugin-prefer-object-spread": "^1.2.1", 28 | "eslint-plugin-react": "^7.13.0", 29 | "gitbook-cli": "^2.3.0", 30 | "lodash": "^4.17.2", 31 | "metro-react-native-babel-preset": "^0.53.1", 32 | "react": "16.8.3", 33 | "react-native": "0.59.3" 34 | } 35 | } 36 | --------------------------------------------------------------------------------