From 801fd8987352eb3a4996393a66e657aefb7595d2 Mon Sep 17 00:00:00 2001 From: Roshan Rajaratnam Date: Thu, 14 Apr 2016 17:45:44 +0200 Subject: [PATCH] Initial commit Initial commit --- .gitignore | 8 + .idea/.name | 1 + .idea/compiler.xml | 22 + .idea/copyright/profiles_settings.xml | 3 + .idea/encodings.xml | 6 + .idea/gradle.xml | 29 + .idea/misc.xml | 46 + .idea/modules.xml | 11 + .idea/runConfigurations.xml | 12 + .idea/vcs.xml | 6 + README.md | 38 + app/.gitignore | 1 + app/app.iml | 132 ++ app/build.gradle | 38 + app/libs/nrf-beacon-lib-v2.0.aar | Bin 0 -> 37250 bytes app/lint.xml | 26 + app/sources/nrf-beacon-lib-v2.0.jar | Bin 0 -> 26455 bytes app/src/main/AndroidManifest.xml | 88 + app/src/main/assets/fonts/trebuc.ttf | Bin 0 -> 136172 bytes app/src/main/assets/fonts/trebucbd.ttf | Bin 0 -> 126376 bytes app/src/main/java/eidr/Curve25519.java | 798 +++++++++ .../java/eidr/EddystoneEidrGenerator.java | 149 ++ .../nearby/AuthorizedServiceTask.java | 113 ++ .../nearby/EddystoneBeaconsAdapter.java | 107 ++ .../nrfbeacon/nearby/LaunchActivity.java | 48 + .../nrfbeacon/nearby/MainActivity.java | 211 +++ .../nearby/NearbyBackgroundService.java | 102 ++ .../nearby/SplashscreenActivity.java | 56 + .../nrfbeacon/nearby/UpdateService.java | 1145 ++++++++++++ .../nearby/beacon/BeaconsFragment.java | 632 +++++++ .../nrfbeacon/nearby/common/BaseFragment.java | 118 ++ .../nearby/common/BoardHelpFragment.java | 69 + .../PermissionRationaleDialogFragment.java | 81 + .../nearby/scanner/DeviceListAdapter.java | 175 ++ .../scanner/ExtendedBluetoothDevice.java | 51 + .../nearby/scanner/ScannerFragment.java | 240 +++ .../scanner/ScannerFragmentListener.java | 35 + .../settings/NearbySettingsActivity.java | 81 + .../settings/NearbySettingsFragment.java | 59 + .../AdvertisingIntervalDialogFragment.java | 135 ++ .../update/AllSlotInfoDialogFragment.java | 117 ++ .../BroadcastCapabilitesDialogFragment.java | 160 ++ .../update/ClearSlotDialogFragment.java | 85 + .../CreateAttachmentDialogFragment.java | 115 ++ .../update/EcdhKeyInfoDialogFragment.java | 138 ++ .../nearby/update/ErrorDialogFragment.java | 80 + .../update/LockStateDialogFragment.java | 244 +++ .../ProximityApiErrorDialogFragment.java | 94 + .../update/RadioTxPowerDialogFragment.java | 144 ++ ...dWriteAdvertisementSlotDialogFragment.java | 587 ++++++ .../update/RegisterBeaconDialogFragment.java | 197 ++ .../RemainConnectableDialogFragment.java | 109 ++ .../update/UnlockBeaconDialogFragment.java | 149 ++ .../nearby/update/UpdateFragment.java | 1592 +++++++++++++++++ .../nearby/util/AuthTaskUrlShortener.java | 124 ++ .../nrfbeacon/nearby/util/DebugLogger.java | 58 + .../nrfbeacon/nearby/util/HttpCallback.java | 61 + .../nrfbeacon/nearby/util/NetworkUtils.java | 40 + .../nrfbeacon/nearby/util/ParserUtils.java | 755 ++++++++ .../nearby/widget/TrebuchetBoldTextView.java | 57 + .../nearby/widget/TrebuchetSwitch.java | 57 + .../nearby/widget/TrebuchetTextView.java | 57 + .../main/res/animator/connect_animator.xml | 43 + app/src/main/res/color/tab_text_color.xml | 27 + app/src/main/res/color/text.xml | 26 + app/src/main/res/color/text_color_primary.xml | 27 + app/src/main/res/color/text_secondary.xml | 26 + .../main/res/drawable-hdpi/ic_eddystone.png | Bin 0 -> 712 bytes app/src/main/res/drawable-hdpi/ic_feature.png | Bin 0 -> 2424 bytes app/src/main/res/drawable-hdpi/ic_help.png | Bin 0 -> 1544 bytes .../main/res/drawable-hdpi/ic_menu_about.png | Bin 0 -> 646 bytes .../res/drawable-hdpi/ic_menu_discard.png | Bin 0 -> 450 bytes .../res/drawable-hdpi/ic_menu_settings.png | Bin 0 -> 460 bytes .../main/res/drawable-hdpi/nordic_logo.png | Bin 0 -> 29716 bytes .../res/drawable-hdpi/stat_sys_beacon.png | Bin 0 -> 1185 bytes .../res/drawable-hdpi/stat_sys_nrf_beacon.png | Bin 0 -> 842 bytes .../drawable-land-xhdpi/background_image.jpg | Bin 0 -> 27426 bytes .../res/drawable-land-xhdpi/nordic_logo.png | Bin 0 -> 55949 bytes .../drawable-sw600dp-xhdpi/nordic_logo.png | Bin 0 -> 51335 bytes app/src/main/res/drawable-v21/button.xml | 34 + app/src/main/res/drawable-xhdpi/app_drive.png | Bin 0 -> 2573 bytes .../res/drawable-xhdpi/app_file_manager.png | Bin 0 -> 3463 bytes .../res/drawable-xhdpi/app_google_play.png | Bin 0 -> 2247 bytes .../drawable-xhdpi/app_total_commander.png | Bin 0 -> 1596 bytes .../res/drawable-xhdpi/background_image.jpg | Bin 0 -> 22961 bytes .../main/res/drawable-xhdpi/beacon_sample.png | Bin 0 -> 182055 bytes .../main/res/drawable-xhdpi/beacon_sw1.png | Bin 0 -> 74909 bytes .../main/res/drawable-xhdpi/beacon_sw2.png | Bin 0 -> 76536 bytes .../res/drawable-xhdpi/ic_action_alarms.png | Bin 0 -> 1807 bytes .../res/drawable-xhdpi/ic_action_monalisa.png | Bin 0 -> 17241 bytes .../res/drawable-xhdpi/ic_action_phone.png | Bin 0 -> 559 bytes .../drawable-xhdpi/ic_action_small_alarms.png | Bin 0 -> 1249 bytes .../ic_action_small_monalisa.png | Bin 0 -> 3542 bytes .../drawable-xhdpi/ic_action_small_phone.png | Bin 0 -> 409 bytes .../drawable-xhdpi/ic_action_small_tasker.png | Bin 0 -> 3274 bytes .../ic_action_small_volume_muted.png | Bin 0 -> 1150 bytes .../ic_action_small_web_site.png | Bin 0 -> 1603 bytes .../res/drawable-xhdpi/ic_action_tasker.png | Bin 0 -> 8601 bytes .../drawable-xhdpi/ic_action_volume_muted.png | Bin 0 -> 1493 bytes .../res/drawable-xhdpi/ic_action_web_site.png | Bin 0 -> 2666 bytes .../main/res/drawable-xhdpi/ic_eddystone.png | Bin 0 -> 885 bytes .../res/drawable-xhdpi/ic_event_immediate.png | Bin 0 -> 1279 bytes .../res/drawable-xhdpi/ic_event_in_range.png | Bin 0 -> 2082 bytes .../main/res/drawable-xhdpi/ic_event_near.png | Bin 0 -> 1184 bytes .../drawable-xhdpi/ic_event_not_in_range.png | Bin 0 -> 1999 bytes .../ic_event_small_immediate.png | Bin 0 -> 909 bytes .../ic_event_small_in_range.png | Bin 0 -> 1458 bytes .../drawable-xhdpi/ic_event_small_near.png | Bin 0 -> 733 bytes .../ic_event_small_not_in_range.png | Bin 0 -> 1400 bytes .../main/res/drawable-xhdpi/ic_feature.png | Bin 0 -> 3306 bytes app/src/main/res/drawable-xhdpi/ic_help.png | Bin 0 -> 1796 bytes .../main/res/drawable-xhdpi/ic_menu_about.png | Bin 0 -> 787 bytes .../res/drawable-xhdpi/ic_menu_discard.png | Bin 0 -> 543 bytes .../res/drawable-xhdpi/ic_menu_settings.png | Bin 0 -> 562 bytes .../main/res/drawable-xhdpi/ic_rssi_0_bar.png | Bin 0 -> 1038 bytes .../main/res/drawable-xhdpi/ic_rssi_1_bar.png | Bin 0 -> 1125 bytes .../res/drawable-xhdpi/ic_rssi_2_bars.png | Bin 0 -> 1318 bytes .../res/drawable-xhdpi/ic_rssi_3_bars.png | Bin 0 -> 1356 bytes app/src/main/res/drawable-xhdpi/monalisa.png | Bin 0 -> 604141 bytes .../main/res/drawable-xhdpi/nordic_logo.png | Bin 0 -> 66984 bytes .../drawable-xhdpi/stat_sys_nrf_beacon.png | Bin 0 -> 1193 bytes app/src/main/res/drawable-xhdpi/zip.png | Bin 0 -> 86140 bytes .../drawable-xxhdpi/action_bar_shadow.9.png | Bin 0 -> 139 bytes .../res/drawable-xxhdpi/background_title.png | Bin 0 -> 13468 bytes .../main/res/drawable-xxhdpi/beacon_anim1.png | Bin 0 -> 7796 bytes .../main/res/drawable-xxhdpi/beacon_anim2.png | Bin 0 -> 6726 bytes .../main/res/drawable-xxhdpi/beacon_anim3.png | Bin 0 -> 5272 bytes .../main/res/drawable-xxhdpi/beacon_anim4.png | Bin 0 -> 3186 bytes .../res/drawable-xxhdpi/bottom_shadow.9.png | Bin 0 -> 219 bytes .../main/res/drawable-xxhdpi/fab_ic_add.png | Bin 0 -> 139 bytes app/src/main/res/drawable-xxhdpi/ic_add.png | Bin 0 -> 1343 bytes .../main/res/drawable-xxhdpi/ic_delete.png | Bin 0 -> 393 bytes .../drawable-xxhdpi/ic_device_eddystone.png | Bin 0 -> 858 bytes .../main/res/drawable-xxhdpi/ic_eddystone.png | Bin 0 -> 1332 bytes app/src/main/res/drawable-xxhdpi/ic_edit.png | Bin 0 -> 572 bytes app/src/main/res/drawable-xxhdpi/ic_lock.png | Bin 0 -> 755 bytes .../res/drawable-xxhdpi/ic_menu_settings.png | Bin 0 -> 843 bytes .../drawable-xxhdpi/ic_nearby_googblue.png | Bin 0 -> 2161 bytes .../res/drawable-xxhdpi/ic_nearby_grey.png | Bin 0 -> 7411 bytes .../main/res/drawable-xxhdpi/ic_refresh.png | Bin 0 -> 939 bytes app/src/main/res/drawable-xxhdpi/ic_show.png | Bin 0 -> 1271 bytes .../main/res/drawable-xxhdpi/ic_unlock.png | Bin 0 -> 756 bytes .../main/res/drawable-xxhdpi/no_beacons.png | Bin 0 -> 8387 bytes .../main/res/drawable/app_file_browser.xml | 28 + app/src/main/res/drawable/background.xml | 34 + app/src/main/res/drawable/button.xml | 28 + app/src/main/res/drawable/button_n.xml | 34 + app/src/main/res/drawable/button_p.xml | 34 + app/src/main/res/drawable/edit_text_bg.xml | 27 + .../main/res/drawable/header_background.xml | 35 + app/src/main/res/drawable/ic_action.xml | 30 + app/src/main/res/drawable/ic_action_small.xml | 30 + app/src/main/res/drawable/ic_device_bg.xml | 28 + app/src/main/res/drawable/ic_event.xml | 28 + app/src/main/res/drawable/ic_event_small.xml | 28 + app/src/main/res/drawable/ic_rssi_bar.xml | 28 + .../main/res/layout-land/activity_main.xml | 68 + .../main/res/layout-land/fragment_update.xml | 607 +++++++ .../layout-sw600dp-land/fragment_update.xml | 622 +++++++ .../main/res/layout-sw600dp/activity_main.xml | 68 + .../fragment_scanner_device_selection.xml | 46 + .../fragment_scanner_device_selection.xml | 56 + app/src/main/res/layout/activity_main.xml | 68 + .../res/layout/activity_nearby_settings.xml | 39 + app/src/main/res/layout/activity_settings.xml | 49 + .../main/res/layout/activity_splashscreen.xml | 43 + app/src/main/res/layout/device_list_empty.xml | 27 + app/src/main/res/layout/device_list_row.xml | 55 + app/src/main/res/layout/device_list_title.xml | 26 + .../res/layout/fragment_all_slot_info.xml | 33 + .../main/res/layout/fragment_beacons_list.xml | 54 + .../fragment_broadcast_capabilities.xml | 171 ++ .../fragment_create_beacon_attachment.xml | 63 + .../layout/fragment_dialog_adv_interval.xml | 43 + .../fragment_dialog_advertising_interval.xml | 72 + .../main/res/layout/fragment_dialog_ecdh.xml | 79 + .../main/res/layout/fragment_dialog_error.xml | 45 + .../main/res/layout/fragment_dialog_help.xml | 29 + .../res/layout/fragment_dialog_lock_state.xml | 110 ++ .../layout/fragment_dialog_radio_tx_power.xml | 89 + .../layout/fragment_dialog_rw_adv_slot.xml | 251 +++ .../res/layout/fragment_dialog_unlock.xml | 64 + .../res/layout/fragment_register_beacon.xml | 99 + .../layout/fragment_remain_connectable.xml | 42 + app/src/main/res/layout/fragment_scan.xml | 51 + .../fragment_scanner_device_selection.xml | 45 + app/src/main/res/layout/fragment_update.xml | 631 +++++++ app/src/main/res/layout/listitem_device.xml | 83 + app/src/main/res/layout/toolbar.xml | 32 + app/src/main/res/menu/about.xml | 31 + app/src/main/res/menu/menu_nearby_about.xml | 15 + app/src/main/res/menu/menu_update.xml | 53 + app/src/main/res/menu/region_details.xml | 32 + app/src/main/res/menu/settings.xml | 31 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2311 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1387 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3368 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 5717 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 8074 bytes .../raw/ble_app_beacon_v1_0_1_s110_v6_0_0.hex | 957 ++++++++++ .../raw/ble_app_beacon_v1_1_0_s110_v7_1_0.zip | Bin 0 -> 14534 bytes app/src/main/res/values-land-v21/dimens.xml | 29 + app/src/main/res/values-land/dimens.xml | 36 + app/src/main/res/values-land/strings.xml | 26 + app/src/main/res/values-sw600dp/dimens.xml | 41 + app/src/main/res/values-sw600dp/strings.xml | 26 + .../main/res/values-sw720dp-land/dimens.xml | 35 + app/src/main/res/values-v21/dimens.xml | 32 + app/src/main/res/values-v21/refs.xml | 26 + app/src/main/res/values-v21/styles.xml | 75 + app/src/main/res/values-w820dp/dimens.xml | 6 + app/src/main/res/values/attrs.xml | 33 + app/src/main/res/values/color.xml | 38 + app/src/main/res/values/dimens.xml | 64 + app/src/main/res/values/refs.xml | 26 + app/src/main/res/values/strings.xml | 454 +++++ .../main/res/values/strings_beacon_lib.xml | 28 + .../main/res/values/strings_permission.xml | 32 + app/src/main/res/values/styles.xml | 164 ++ app/src/main/res/xml/settings_nearby.xml | 33 + build.gradle | 15 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 ++ gradlew.bat | 90 + libeddystoneeidr/.gitignore | 1 + libeddystoneeidr/build.gradle | 23 + libeddystoneeidr/libeddystoneeidr.iml | 97 + libeddystoneeidr/proguard-rules.pro | 17 + .../EddystoneEidrGeneratorTest | 213 +++ libeddystoneeidr/src/main/AndroidManifest.xml | 10 + .../sample/libeddystoneeidr/Curve25519.java | 798 +++++++++ .../EddystoneEidrGenerator.java | 315 ++++ .../src/main/res/values/strings.xml | 3 + libproximitybeacon/.gitignore | 1 + libproximitybeacon/build.gradle | 25 + libproximitybeacon/libproximitybeacon.iml | 157 ++ libproximitybeacon/proguard-rules.pro | 17 + .../libproximitybeacon/ApplicationTest.java | 14 + .../src/main/AndroidManifest.xml | 8 + .../libproximitybeacon/HttpCallback.java | 61 + .../libproximitybeacon/ProximityBeacon.java | 101 ++ .../ProximityBeaconImpl.java | 223 +++ .../src/main/res/values/strings.xml | 3 + nrf-beacon-nearby.iml | 19 + settings.gradle | 2 + 246 files changed, 19033 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.name create mode 100644 .idea/compiler.xml create mode 100644 .idea/copyright/profiles_settings.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 .idea/vcs.xml create mode 100644 README.md create mode 100644 app/.gitignore create mode 100644 app/app.iml create mode 100644 app/build.gradle create mode 100644 app/libs/nrf-beacon-lib-v2.0.aar create mode 100644 app/lint.xml create mode 100644 app/sources/nrf-beacon-lib-v2.0.jar create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/assets/fonts/trebuc.ttf create mode 100644 app/src/main/assets/fonts/trebucbd.ttf create mode 100644 app/src/main/java/eidr/Curve25519.java create mode 100644 app/src/main/java/eidr/EddystoneEidrGenerator.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/AuthorizedServiceTask.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/EddystoneBeaconsAdapter.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/LaunchActivity.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/MainActivity.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/NearbyBackgroundService.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/SplashscreenActivity.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/UpdateService.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/beacon/BeaconsFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/BaseFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/BoardHelpFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/PermissionRationaleDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/DeviceListAdapter.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ExtendedBluetoothDevice.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ScannerFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ScannerFragmentListener.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/settings/NearbySettingsActivity.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/settings/NearbySettingsFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/AdvertisingIntervalDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/AllSlotInfoDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/BroadcastCapabilitesDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ClearSlotDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/CreateAttachmentDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/EcdhKeyInfoDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ErrorDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/LockStateDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ProximityApiErrorDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RadioTxPowerDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ReadWriteAdvertisementSlotDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RegisterBeaconDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RemainConnectableDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/UnlockBeaconDialogFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/UpdateFragment.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/AuthTaskUrlShortener.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/DebugLogger.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/HttpCallback.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/NetworkUtils.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/ParserUtils.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetBoldTextView.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetSwitch.java create mode 100644 app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetTextView.java create mode 100644 app/src/main/res/animator/connect_animator.xml create mode 100644 app/src/main/res/color/tab_text_color.xml create mode 100644 app/src/main/res/color/text.xml create mode 100644 app/src/main/res/color/text_color_primary.xml create mode 100644 app/src/main/res/color/text_secondary.xml create mode 100644 app/src/main/res/drawable-hdpi/ic_eddystone.png create mode 100644 app/src/main/res/drawable-hdpi/ic_feature.png create mode 100644 app/src/main/res/drawable-hdpi/ic_help.png create mode 100644 app/src/main/res/drawable-hdpi/ic_menu_about.png create mode 100644 app/src/main/res/drawable-hdpi/ic_menu_discard.png create mode 100644 app/src/main/res/drawable-hdpi/ic_menu_settings.png create mode 100644 app/src/main/res/drawable-hdpi/nordic_logo.png create mode 100644 app/src/main/res/drawable-hdpi/stat_sys_beacon.png create mode 100644 app/src/main/res/drawable-hdpi/stat_sys_nrf_beacon.png create mode 100644 app/src/main/res/drawable-land-xhdpi/background_image.jpg create mode 100644 app/src/main/res/drawable-land-xhdpi/nordic_logo.png create mode 100644 app/src/main/res/drawable-sw600dp-xhdpi/nordic_logo.png create mode 100644 app/src/main/res/drawable-v21/button.xml create mode 100644 app/src/main/res/drawable-xhdpi/app_drive.png create mode 100644 app/src/main/res/drawable-xhdpi/app_file_manager.png create mode 100644 app/src/main/res/drawable-xhdpi/app_google_play.png create mode 100644 app/src/main/res/drawable-xhdpi/app_total_commander.png create mode 100644 app/src/main/res/drawable-xhdpi/background_image.jpg create mode 100644 app/src/main/res/drawable-xhdpi/beacon_sample.png create mode 100644 app/src/main/res/drawable-xhdpi/beacon_sw1.png create mode 100644 app/src/main/res/drawable-xhdpi/beacon_sw2.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_alarms.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_monalisa.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_phone.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_small_alarms.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_small_monalisa.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_small_phone.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_small_tasker.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_small_volume_muted.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_small_web_site.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_tasker.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_volume_muted.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_web_site.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_eddystone.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_event_immediate.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_event_in_range.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_event_near.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_event_not_in_range.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_event_small_immediate.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_event_small_in_range.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_event_small_near.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_event_small_not_in_range.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_feature.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_help.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_menu_about.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_menu_discard.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_menu_settings.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_rssi_0_bar.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_rssi_1_bar.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_rssi_2_bars.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_rssi_3_bars.png create mode 100644 app/src/main/res/drawable-xhdpi/monalisa.png create mode 100644 app/src/main/res/drawable-xhdpi/nordic_logo.png create mode 100644 app/src/main/res/drawable-xhdpi/stat_sys_nrf_beacon.png create mode 100644 app/src/main/res/drawable-xhdpi/zip.png create mode 100644 app/src/main/res/drawable-xxhdpi/action_bar_shadow.9.png create mode 100644 app/src/main/res/drawable-xxhdpi/background_title.png create mode 100644 app/src/main/res/drawable-xxhdpi/beacon_anim1.png create mode 100644 app/src/main/res/drawable-xxhdpi/beacon_anim2.png create mode 100644 app/src/main/res/drawable-xxhdpi/beacon_anim3.png create mode 100644 app/src/main/res/drawable-xxhdpi/beacon_anim4.png create mode 100644 app/src/main/res/drawable-xxhdpi/bottom_shadow.9.png create mode 100644 app/src/main/res/drawable-xxhdpi/fab_ic_add.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_add.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_delete.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_device_eddystone.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_eddystone.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_edit.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_lock.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_menu_settings.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_nearby_googblue.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_nearby_grey.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_refresh.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_show.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_unlock.png create mode 100644 app/src/main/res/drawable-xxhdpi/no_beacons.png create mode 100644 app/src/main/res/drawable/app_file_browser.xml create mode 100644 app/src/main/res/drawable/background.xml create mode 100644 app/src/main/res/drawable/button.xml create mode 100644 app/src/main/res/drawable/button_n.xml create mode 100644 app/src/main/res/drawable/button_p.xml create mode 100644 app/src/main/res/drawable/edit_text_bg.xml create mode 100644 app/src/main/res/drawable/header_background.xml create mode 100644 app/src/main/res/drawable/ic_action.xml create mode 100644 app/src/main/res/drawable/ic_action_small.xml create mode 100644 app/src/main/res/drawable/ic_device_bg.xml create mode 100644 app/src/main/res/drawable/ic_event.xml create mode 100644 app/src/main/res/drawable/ic_event_small.xml create mode 100644 app/src/main/res/drawable/ic_rssi_bar.xml create mode 100644 app/src/main/res/layout-land/activity_main.xml create mode 100644 app/src/main/res/layout-land/fragment_update.xml create mode 100644 app/src/main/res/layout-sw600dp-land/fragment_update.xml create mode 100644 app/src/main/res/layout-sw600dp/activity_main.xml create mode 100644 app/src/main/res/layout-v21/fragment_scanner_device_selection.xml create mode 100644 app/src/main/res/layout-v23/fragment_scanner_device_selection.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/activity_nearby_settings.xml create mode 100644 app/src/main/res/layout/activity_settings.xml create mode 100644 app/src/main/res/layout/activity_splashscreen.xml create mode 100644 app/src/main/res/layout/device_list_empty.xml create mode 100644 app/src/main/res/layout/device_list_row.xml create mode 100644 app/src/main/res/layout/device_list_title.xml create mode 100644 app/src/main/res/layout/fragment_all_slot_info.xml create mode 100644 app/src/main/res/layout/fragment_beacons_list.xml create mode 100644 app/src/main/res/layout/fragment_broadcast_capabilities.xml create mode 100644 app/src/main/res/layout/fragment_create_beacon_attachment.xml create mode 100644 app/src/main/res/layout/fragment_dialog_adv_interval.xml create mode 100644 app/src/main/res/layout/fragment_dialog_advertising_interval.xml create mode 100644 app/src/main/res/layout/fragment_dialog_ecdh.xml create mode 100644 app/src/main/res/layout/fragment_dialog_error.xml create mode 100644 app/src/main/res/layout/fragment_dialog_help.xml create mode 100644 app/src/main/res/layout/fragment_dialog_lock_state.xml create mode 100644 app/src/main/res/layout/fragment_dialog_radio_tx_power.xml create mode 100644 app/src/main/res/layout/fragment_dialog_rw_adv_slot.xml create mode 100644 app/src/main/res/layout/fragment_dialog_unlock.xml create mode 100644 app/src/main/res/layout/fragment_register_beacon.xml create mode 100644 app/src/main/res/layout/fragment_remain_connectable.xml create mode 100644 app/src/main/res/layout/fragment_scan.xml create mode 100644 app/src/main/res/layout/fragment_scanner_device_selection.xml create mode 100644 app/src/main/res/layout/fragment_update.xml create mode 100644 app/src/main/res/layout/listitem_device.xml create mode 100644 app/src/main/res/layout/toolbar.xml create mode 100644 app/src/main/res/menu/about.xml create mode 100644 app/src/main/res/menu/menu_nearby_about.xml create mode 100644 app/src/main/res/menu/menu_update.xml create mode 100644 app/src/main/res/menu/region_details.xml create mode 100644 app/src/main/res/menu/settings.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/raw/ble_app_beacon_v1_0_1_s110_v6_0_0.hex create mode 100644 app/src/main/res/raw/ble_app_beacon_v1_1_0_s110_v7_1_0.zip create mode 100644 app/src/main/res/values-land-v21/dimens.xml create mode 100644 app/src/main/res/values-land/dimens.xml create mode 100644 app/src/main/res/values-land/strings.xml create mode 100644 app/src/main/res/values-sw600dp/dimens.xml create mode 100644 app/src/main/res/values-sw600dp/strings.xml create mode 100644 app/src/main/res/values-sw720dp-land/dimens.xml create mode 100644 app/src/main/res/values-v21/dimens.xml create mode 100644 app/src/main/res/values-v21/refs.xml create mode 100644 app/src/main/res/values-v21/styles.xml create mode 100644 app/src/main/res/values-w820dp/dimens.xml create mode 100644 app/src/main/res/values/attrs.xml create mode 100644 app/src/main/res/values/color.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/refs.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/strings_beacon_lib.xml create mode 100644 app/src/main/res/values/strings_permission.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 app/src/main/res/xml/settings_nearby.xml create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 libeddystoneeidr/.gitignore create mode 100644 libeddystoneeidr/build.gradle create mode 100644 libeddystoneeidr/libeddystoneeidr.iml create mode 100644 libeddystoneeidr/proguard-rules.pro create mode 100644 libeddystoneeidr/src/androidTest/java/com/google/sample/libeddystoneeidr/EddystoneEidrGeneratorTest create mode 100644 libeddystoneeidr/src/main/AndroidManifest.xml create mode 100644 libeddystoneeidr/src/main/java/com/google/sample/libeddystoneeidr/Curve25519.java create mode 100644 libeddystoneeidr/src/main/java/com/google/sample/libeddystoneeidr/EddystoneEidrGenerator.java create mode 100644 libeddystoneeidr/src/main/res/values/strings.xml create mode 100644 libproximitybeacon/.gitignore create mode 100644 libproximitybeacon/build.gradle create mode 100644 libproximitybeacon/libproximitybeacon.iml create mode 100644 libproximitybeacon/proguard-rules.pro create mode 100644 libproximitybeacon/src/androidTest/java/com/google/sample/libproximitybeacon/ApplicationTest.java create mode 100644 libproximitybeacon/src/main/AndroidManifest.xml create mode 100644 libproximitybeacon/src/main/java/com/google/sample/libproximitybeacon/HttpCallback.java create mode 100644 libproximitybeacon/src/main/java/com/google/sample/libproximitybeacon/ProximityBeacon.java create mode 100644 libproximitybeacon/src/main/java/com/google/sample/libproximitybeacon/ProximityBeaconImpl.java create mode 100644 libproximitybeacon/src/main/res/values/strings.xml create mode 100644 nrf-beacon-nearby.iml create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db1555f --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.gradle +/local.properties +/.idea/workspace.xml +/.idea/dictionaries/*.xml +/.idea/libraries +.DS_Store +/build +/key* \ No newline at end of file diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..9f676f0 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +nrf-beacon-nearby \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..96cc43e --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..0c7e4a6 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,29 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..1a3eaff --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..ffeca08 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ef2d27 --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Android-nRF-Beacon-for-Eddystone +nRF Beacon for Eddystone is an application that supports the new Eddystone GATT configuration service allowing users to configure your beacon to advertise all types of Eddystone frame types from UID, URL, TLM and the newest EID and eTLM frame types. In addition the application uses Nearby API for scanning Eddystone beacons in close proximity and Google Proximity API to register UID, EID beacons and create attachments for them on the Proximity API cloud. + +## Features +The basic features of the application includes + +-Foreground and background scanning of beacons using Nearby API which are registered on the Proximity API. Once an EID beacon is registered to the cloud with an attachment, the Nearby API will send the beacon EID packet to the proximity API, resolves the EID packet and retrieves the data attached to it. + Please note only UID and EID beacon types can be registered on the proximity API + +-Registering beacons and creating attachments to proximity API + +-Configuration of Eddystone beacons using the new Eddystone GATT configuration service. + +-URL shortener for configuring URL beacons + +## How to Guide +1. First press the button 1 on the nRF52 Devkit which turns the devkit/beacon in to connectable mode for 60 seconds +2. Press the connect button on the update tab on the application and the list of devices will be prompted. +3. Select the device and you will be challenged with the beacon manufacturer lock code. the lock code used for this application is 16 F's and the application will have the lock code hard coded +4. After entering the correct lock code the application will read through all slots and display the information for each slot. + +This application goes hand in hand with the nRF5 SDK for Eddystone posted on Github on the following link. This link also contain a complete how to guide and the new Eddystone GATT configuration specs. Please note that some of the advanced characteristics are not supported on the firmware application and will be implemented in the near future. + +https://github.com/NordicSemiconductor/nrf5-sdk-for-eddystone + +The nRF Beacon for Eddystone application is available on Playstore on the following link. + +https://play.google.com/store/apps/details?id=no.nordicsemi.android.nrfbeacon.nearby + +Note: + +-Android 4.3 or newer is required. + +-Tested on Samsung S3 with Android 4.3, on Nexus 5, 6 and 9 with lollipop & Marshmallow and Samsung Galaxy S6, S7 with Marshmallow. + +-Location Services need to be enabled for scanning on android 6.0 Marshmallow requesting a runtime persmission ACCESS_COARSE_LOCATION + +-GET_ACCOUNTS permission is required in order to select the account to register and allow access to the Google Proximity API and URL Shortener API. diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/app.iml b/app/app.iml new file mode 100644 index 0000000..4fedb83 --- /dev/null +++ b/app/app.iml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..b68e8b1 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,38 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 23 + buildToolsVersion "23.0.3" + defaultConfig { + applicationId "no.nordicsemi.android.nrfbeacon.nearby" + minSdkVersion 18 + targetSdkVersion 23 + versionCode 1 + versionName '1.0' + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } + productFlavors { + } +} + +repositories { + flatDir { + dirs 'libs' + } +} + +dependencies { + compile 'com.android.support:appcompat-v7:23.3.0' + compile 'com.android.support:design:23.3.0' + compile 'no.nordicsemi.android.support.v18:scanner:0.1.1' + compile 'com.google.android.gms:play-services-nearby:8.4.0' + compile 'com.google.android.gms:play-services-location:8.4.0' + compile 'com.squareup.okhttp:okhttp:2.4.0' + compile project(':libproximitybeacon') + compile project(':libeddystoneeidr') +} diff --git a/app/libs/nrf-beacon-lib-v2.0.aar b/app/libs/nrf-beacon-lib-v2.0.aar new file mode 100644 index 0000000000000000000000000000000000000000..c38b2314c9661cf7183384f271bdc9c41bdb0255 GIT binary patch literal 37250 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

U&NTh#N2RFs`dBuGJ; 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 literal 0 HcmV?d00001 diff --git a/app/lint.xml b/app/lint.xml new file mode 100644 index 0000000..0ce66c0 --- /dev/null +++ b/app/lint.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/app/sources/nrf-beacon-lib-v2.0.jar b/app/sources/nrf-beacon-lib-v2.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..e0d24e9eef8f9adac673a1205de91237553b45d1 GIT binary patch literal 26455 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 G1^f>oU<~X4 literal 0 HcmV?d00001 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..cf8aa9a --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/assets/fonts/trebuc.ttf b/app/src/main/assets/fonts/trebuc.ttf new file mode 100644 index 0000000000000000000000000000000000000000..84891986b0c8eb556779e4f9f839b05cf67b9348 GIT binary patch literal 136172 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 z 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 to generate a public key from a secret key. + */ + public static byte[] scalarMultBase(byte[] n) { + toPrivateKey(n); + return scalarMult(n, BASE_POINT); + } + + /** + * Returns the x coordinates of the point nQ, where Q is a point with x coordinate equal to q. + * + *

Used to generate a shared secret between the owner of the (secret) n and the owner of the + * secret paired with q. + */ + public static byte[] scalarMult(byte[] n, byte[] q) { + if (n.length != 32 || q.length != 32) { + throw new IllegalArgumentException("All keys must be exactly 32 bytes long."); + } + toPrivateKey(n); + Polynomial25519 qPolynomial = new Polynomial25519(q); + Polynomial25519.Montgomery m = Polynomial25519.multiple(n, qPolynomial); + Polynomial25519 reciprocal = m.z.reciprocal(); + reciprocal.mult(m.x); + return reciprocal.toBytes(); + } + + /** + * An element of F_{2^255 - 19} in its polynomial form: given an object defined by an array c, the + * corresponding polynomial is sum(2^(ceil(25.5 * i) * c[i] * x^i), and the element is the + * valuation of the polynomial at 1. + * + *

The "reduced degree" form has degree less than 10; the extended form has degree less than + * 19, and is used to handle the output of the multiplication of these elements. Some operations + * assume to act on reduced degree polynomials. + * + *

The "reduced coefficients" form has coefficients less than 2^26 in absolute value. The + * extended coefficient form has coefficient less than 2^62 in absolute value. Some operations + * assume to act on reduced coefficients polynomials. + * + *

It is a responsibility of the caller to make sure to use the correct form whenever + * necessary. + * + *

See the paper [1] Curve25519: new Diffie-Hellman speed records at + * http://cr.yp.to/ecdh/curve25519-20060209.pdf for more information + */ + /* @VisibleForTesting */ static class Polynomial25519 { + private long[] c = new long[19]; + + /** + * An element of F_{2^255-19} in the "Montgomery" form, i.e. the element corresponding to (x, z) + * is x/z = x * z^{-1}. + */ + private static class Montgomery { + public Polynomial25519 x; + public Polynomial25519 z; + + public Montgomery(Polynomial25519 x, Polynomial25519 z) { + this.x = new Polynomial25519(x); + this.z = new Polynomial25519(z); + } + + public Montgomery(Montgomery m) { + this(m.x, m.z); + } + } + + public Polynomial25519() {} + + /** + * After, "this" is of reduced degree and of reduced coefficients. + * @param x An integer less than 2^26 in absolute value. + */ + public Polynomial25519(long x) { + c[0] = x; + } + + /** + * Copy constructor. + * After, "this" is of reduced degree. + * @param other A reduced degree polynomial. + */ + public Polynomial25519(Polynomial25519 other) { + for (int i = 0; i < 10; i++) { + c[i] = other.c[i]; + } + } + + /** + * Only used for testing. + */ + public Polynomial25519(long[] other) { + for (int i = 0; i < other.length && i < 19; i++) { + c[i] = other[i]; + } + } + + /** + * Constructs a polynomial from a 32-bytes representation. + */ + public Polynomial25519(byte[] bytes) { + if (bytes.length != 32) { + throw new IllegalArgumentException("bytes must have length 32"); + } + c[0] = coefficientFromBytes(bytes, 0, 0, 0x3ffffff); + c[1] = coefficientFromBytes(bytes, 3, 2, 0x1ffffff); + c[2] = coefficientFromBytes(bytes, 6, 3, 0x3ffffff); + c[3] = coefficientFromBytes(bytes, 9, 5, 0x1ffffff); + c[4] = coefficientFromBytes(bytes, 12, 6, 0x3ffffff); + c[5] = coefficientFromBytes(bytes, 16, 0, 0x1ffffff); + c[6] = coefficientFromBytes(bytes, 19, 1, 0x3ffffff); + c[7] = coefficientFromBytes(bytes, 22, 3, 0x1ffffff); + c[8] = coefficientFromBytes(bytes, 25, 4, 0x3ffffff); + c[9] = coefficientFromBytes(bytes, 28, 6, 0x1ffffff); + } + + /** + * Returns a single byte of the 32-bytes representation. + */ + private static long coefficientFromBytes(byte[] input, int start, int shift, int mask) { + return ((((input[start + 0] & 0xff) << 0) + | ((input[start + 1] & 0xff) << 8) + | ((input[start + 2] & 0xff) << 16) + | ((input[start + 3] & 0xff) << 24)) >> shift) & mask; + } + + /** + * Returns a 32-bytes representation of the element + */ + public byte[] toBytes() { + byte[] output = new byte[32]; + do { + for (int i = 0; i < 9; i++) { + if ((i & 1) == 1) { + while (c[i] < 0) { + c[i] += 0x2000000; + c[i + 1]--; + } + } else { + while (c[i] < 0) { + c[i] += 0x4000000; + c[i + 1]--; + } + } + } + while (c[9] < 0) { + c[9] += 0x2000000; + c[0] -= 19; + } + } while (c[0] < 0); + c[1] <<= 2; + c[2] <<= 3; + c[3] <<= 5; + c[4] <<= 6; + c[6] <<= 1; + c[7] <<= 3; + c[8] <<= 4; + c[9] <<= 6; + output[0] = 0; + output[16] = 0; + bytesFromCoefficients(output, 0, 0); + bytesFromCoefficients(output, 1, 3); + bytesFromCoefficients(output, 2, 6); + bytesFromCoefficients(output, 3, 9); + bytesFromCoefficients(output, 4, 12); + bytesFromCoefficients(output, 5, 16); + bytesFromCoefficients(output, 6, 19); + bytesFromCoefficients(output, 7, 22); + bytesFromCoefficients(output, 8, 25); + bytesFromCoefficients(output, 9, 28); + return output; + } + + private void bytesFromCoefficients(byte[] output, int idx, int start) { + output[start + 0] |= c[idx] & 0xff; + output[start + 1] = (byte) ((c[idx] >> 8) & 0xff); + output[start + 2] = (byte) ((c[idx] >> 16) & 0xff); + output[start + 3] = (byte) ((c[idx] >> 24) & 0xff); + } + + /** + * Clears the high-degree part of the polynomial, trusting the caller that that part is not + * used. + */ + public void clean() { + Arrays.fill(c, 10, 19, 0); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Polynomial25519 other = (Polynomial25519) obj; + for (int i = 0; i < 19; i++) { + if (other.c[i] != c[i]) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + return Arrays.hashCode(c); + } + + public String toString() { + String s = ""; + for (int i = 0; i < 10; i++) { + s += c[i] + " "; + } + s += " "; + for (int i = 10; i < 19; i++) { + s += c[i] + " "; + } + return s; + } + + /** + * Computes the x coordinate of a point nQ, where Q is one of the preimages of q = q/1 in the + * elliptic curve. It is proven that any preimage Q gives the same result. + * @param n A number in the 32-bytes little endian format. + * @param q The x-coordinates of a point in the curve. + * @return The x coordinate of nQ, in the Montgomery form (first/second). Both polynomials are + * in the reduced degree form. + */ + public static Montgomery multiple(byte[] n, Polynomial25519 q) { + Montgomery nqpq[] = new Montgomery[] { + new Montgomery(new Polynomial25519(q), new Polynomial25519(1)), + new Montgomery(new Polynomial25519(0), new Polynomial25519(1)) + }; + Montgomery nq[] = new Montgomery[] { + new Montgomery(new Polynomial25519(1), new Polynomial25519(0)), + new Montgomery(new Polynomial25519(0), new Polynomial25519(1)) + }; + + int rollIdx = 0; + for (int i = 0; i < 32; i++) { + byte b = n[31 - i]; + for (int j = 0; j < 8; j++) { + int bit = -(b >> 7); + + swapConditional(nq[rollIdx % 2].x, nqpq[rollIdx % 2].x, bit); + swapConditional(nq[rollIdx % 2].z, nqpq[rollIdx % 2].z, bit); + + montgomery(nq[rollIdx % 2], nqpq[rollIdx % 2], q, + nq[(rollIdx + 1) % 2], nqpq[(rollIdx + 1) % 2]); + + swapConditional(nq[(rollIdx + 1) % 2].x, nqpq[(rollIdx + 1) % 2].x, bit); + swapConditional(nq[(rollIdx + 1) % 2].z, nqpq[(rollIdx + 1) % 2].z, bit); + + rollIdx++; + b <<= 1; + } + } + return nq[rollIdx % 2]; + } + + /** + * Adds other to the object. + * Before, "this" must be of reduced degree. + * After, "this" is of reduced degree. + * @param other A reduced degree polynomial. + */ + public void sum(Polynomial25519 other) { + for (int i = 0; i < 10; i++) { + c[i] += other.c[i]; + } + } + + /** + * Subtracts other from the object. + * Before, "this" must be of reduced degree. + * After, "this" is of reduced degree. + * @param other A reduced degree polynomial. + */ + public void diff(Polynomial25519 other) { + for (int i = 0; i < 10; i++) { + c[i] -= other.c[i]; + } + } + + /** + * Multiply the object by a scalar. + * Before, "this" must be of reduced degree and of reduced coefficients. + * After, "this" is of reduced degree and of reduced coefficients. + * @param scalar An integer less than 2^26. + */ + public void mult(int scalar) { + for (int i = 0; i < 10; i++) { + c[i] *= scalar; + } + reduceCoefficients(); + } + + /** + * Non-static version of {@code mult}. + */ + public void mult(Polynomial25519 other) { + c = Polynomial25519.innerMult(c, other.c); + reduceDegree(); + reduceCoefficients(); + } + + /** + * Returns a polynomial corresponding to the multiplication of the two polynomials in input. + * @param a A reduced degree, reduced coefficients polynomial. + * @param b A reduced degree, reduced coefficients polynomial. + * @return A reduced degree, reduced coefficients polynomial. + */ + public static Polynomial25519 mult(Polynomial25519 a, Polynomial25519 b) { + Polynomial25519 output = new Polynomial25519(); + output.c = Polynomial25519.innerMult(a.c, b.c); + output.reduceDegree(); + output.reduceCoefficients(); + return output; + } + + /** + * Returns a polynomial corresponding to the square of the input polynomial. + * @param a A reduced degree, reduced coefficients polynomial. + * @return A reduced degree, reduced coefficients polynomial. + */ + public static Polynomial25519 square(Polynomial25519 a) { + Polynomial25519 output = new Polynomial25519(); + output.c = Polynomial25519.innerSquare(a.c); + output.reduceDegree(); + output.reduceCoefficients(); + return output; + } + + /** + * Computes the square of this polynomial. + * Before, "this" must be of reduced degree, reduced coefficients. + * After, "this" is of reduced degree, reduced coefficients. + */ + public void square() { + c = Polynomial25519.innerSquare(c); + reduceDegree(); + reduceCoefficients(); + } + + /** + * Computes the reciprocal of the input by elevating to the (2^255 - 19) - 2 efficiently. + * "This" must be a reduced degree, reduced coefficient polynomial. + */ + public Polynomial25519 reciprocal() { + return innerReciprocal(this); + } + + /** + * Reduce the degree of the polynomial. + * Before, "this" must be of extended degree. + * After, "this" is of reduced degree. + */ + private void reduceDegree() { + for (int i = 8; i >= 0; i--) { + // Means adding 19 times the other. + c[i] += c[10 + i] << 4; + c[i] += c[10 + i] << 1; + c[i] += c[10 + i]; + } + // We do not need to zero the upper part, as following operations will assume they are not + // used. + } + + /** + * Reduce the coefficients of the polynomial. + * Before, "this" must be of reduced degree. + * After, "this" is of reduced degree, reduced coefficients. + */ + private void reduceCoefficients() { + do { + c[10] = 0; + for (int i = 0; i < 10; i += 2) { + long over = c[i] / 0x4000000; + c[i + 1] += over; + c[i] -= over * 0x4000000; + + over = c[i + 1] / 0x2000000; + c[i + 2] += over; + c[i + 1] -= over * 0x2000000; + } + c[0] += 19 * c[10]; + } while (c[10] != 0); + } + + /** + * Swaps a and b if iswap is 1, do nothing (but using the same time) if iswap is 0. Any other + * value is not accepted. + * @param a A reduced degree polynomial. + * @param b A reduced degree polynomial. + * @param iswap Whether should swap or not. + */ + private static void swapConditional(Polynomial25519 a, Polynomial25519 b, long iswap) { + int swap = (int) (-iswap); + for (int i = 0; i < 10; i++) { + int x = swap & (((int) a.c[i]) ^ ((int) b.c[i])); + a.c[i] = ((int) a.c[i]) ^ x; + b.c[i] = ((int) b.c[i]) ^ x; + } + } + + /** + * Computes the x coordinates of 2Q and Q+P. See appendix B (page 21) in [1]. + * @param q The x coordinate of a point Q on the curve, reduced degree form. Destroyed. + * @param p The x coordinate of a point P on the curve, reduced degree form. Destroyed. + * @param qmp The x coordinate of the point Q-P on the curve, reduced degree form. Preserved. + * @param qpq Output 2Q, in reduced degree, reduced coefficients form. + * @param qpp Output Q+P, in reduced degree, reduced coefficients form. + */ + private static void montgomery(Montgomery q, Montgomery p, Polynomial25519 qmp, + Montgomery qpq, Montgomery qpp) { + Montgomery qprime = new Montgomery(q); + qprime.x.sum(q.z); // q'.x = q.x + q.z + qprime.z.diff(q.x); // q'.z = q.z - q.x + + Montgomery pprime = new Montgomery(p); + pprime.x.sum(p.z); // p'.x = p.x + p.z + pprime.z.diff(p.x); // p'.z = p.z - p.x + + pprime.x.mult(qprime.z); // p'.x *= q'.z + pprime.z.mult(qprime.x); // p'.z *= q'.x + + qprime.x.square(); // q'.x **= 2 + qprime.z.square(); // q'.z **= 2 + + qpp.x = new Polynomial25519(pprime.x); + qpp.z = new Polynomial25519(pprime.z); + qpp.x.sum(pprime.z); // (q+p).x = p'.x + p'.z + qpp.z.diff(pprime.x); // (q+p).z = p'.z - p'.x + + qpp.x.square(); // (q+p).x **= 2 + qpp.z.square(); // (q+p).z **= 2 + qpp.z.mult(qmp); // (q+p).z *= (q-p) + + qpq.x = new Polynomial25519(qprime.x); + qpq.z = new Polynomial25519(qprime.x); + qpq.x.mult(qprime.z); // (2q).x = q'.x * q'.z + qpq.z.diff(qprime.z); // (2q).z = q'.x - q'.z + + Polynomial25519 t = new Polynomial25519(qpq.z); + qpq.z.mult(121665); // (2q).z *= (A - 2) / 4 + qpq.z.sum(qprime.x); // (2q).z += q'.x + qpq.z.mult(t); // (2q).z += t + } + + + /** + * Returns a polynomial corresponding to the multiplication of the two polynomials in input. + * @param a A reduced degree, reduced coefficients polynomial. + * @param b A reduced degree, reduced coefficients polynomial. + * @return The product polynomial. + */ + private static long[] innerMult(long[] a, long[] b) { + long[] output = new long[19]; + output[0] = + b[0] * a[0]; + output[1] = + b[0] * a[1] + + b[1] * a[0]; + output[2] = + b[1] * a[1] * 2 + + b[0] * a[2] + + b[2] * a[0]; + output[3] = + b[1] * a[2] + + b[2] * a[1] + + b[0] * a[3] + + b[3] * a[0]; + output[4] = + b[2] * a[2] + + (b[1] * a[3] + + b[3] * a[1]) * 2 + + b[0] * a[4] + + b[4] * a[0]; + output[5] = + b[2] * a[3] + + b[3] * a[2] + + b[1] * a[4] + + b[4] * a[1] + + b[0] * a[5] + + b[5] * a[0]; + output[6] = + (b[3] * a[3] + + b[1] * a[5] + + b[5] * a[1]) * 2 + + b[2] * a[4] + + b[4] * a[2] + + b[0] * a[6] + + b[6] * a[0]; + output[7] = + b[3] * a[4] + + b[4] * a[3] + + b[2] * a[5] + + b[5] * a[2] + + b[1] * a[6] + + b[6] * a[1] + + b[0] * a[7] + + b[7] * a[0]; + output[8] = + b[4] * a[4] + + (b[3] * a[5] + + b[5] * a[3] + + b[1] * a[7] + + b[7] * a[1]) * 2 + + b[2] * a[6] + + b[6] * a[2] + + b[0] * a[8] + + b[8] * a[0]; + output[9] = + b[4] * a[5] + + b[5] * a[4] + + b[3] * a[6] + + b[6] * a[3] + + b[2] * a[7] + + b[7] * a[2] + + b[1] * a[8] + + b[8] * a[1] + + b[0] * a[9] + + b[9] * a[0]; + output[10] = + (b[5] * a[5] + + b[3] * a[7] + + b[7] * a[3] + + b[1] * a[9] + + b[9] * a[1]) * 2 + + b[4] * a[6] + + b[6] * a[4] + + b[2] * a[8] + + b[8] * a[2]; + output[11] = + b[5] * a[6] + + b[6] * a[5] + + b[4] * a[7] + + b[7] * a[4] + + b[3] * a[8] + + b[8] * a[3] + + b[2] * a[9] + + b[9] * a[2]; + output[12] = + b[6] * a[6] + + (b[5] * a[7] + + b[7] * a[5] + + b[3] * a[9] + + b[9] * a[3]) * 2 + + b[4] * a[8] + + b[8] * a[4]; + output[13] = + b[6] * a[7] + + b[7] * a[6] + + b[5] * a[8] + + b[8] * a[5] + + b[4] * a[9] + + b[9] * a[4]; + output[14] = + (b[7] * a[7] + + b[5] * a[9] + + b[9] * a[5]) * 2 + + b[6] * a[8] + + b[8] * a[6]; + output[15] = + b[7] * a[8] + + b[8] * a[7] + + b[6] * a[9] + + b[9] * a[6]; + output[16] = + b[8] * a[8] + + (b[7] * a[9] + + b[9] * a[7]) * 2; + output[17] = + b[8] * a[9] + + b[9] * a[8]; + output[18] = + b[9] * a[9] * 2; + return output; + } + + /** + * Returns a polynomial corresponding to the square of the input polynomial. + * @param a A reduced degree, reduced coefficients polynomial. + * @return The squared polynomial. + */ + private static long[] innerSquare(long[] a) { + long[] output = new long[19]; + output[0] = + a[0] * a[0]; + output[1] = + a[0] * a[1] * 2; + output[2] = + (a[1] * a[1] + + a[0] * a[2]) * 2; + output[3] = + (a[1] * a[2] + + a[0] * a[3]) * 2; + output[4] = + a[2] * a[2] + + a[1] * a[3] * 4 + + a[0] * a[4] * 2; + output[5] = + (a[2] * a[3] + + a[1] * a[4] + + a[0] * a[5]) * 2; + output[6] = + (a[3] * a[3] + + a[2] * a[4] + + a[0] * a[6] + + a[1] * a[5] * 2) * 2; + output[7] = + (a[3] * a[4] + + a[2] * a[5] + + a[1] * a[6] + + a[0] * a[7]) * 2; + output[8] = + a[4] * a[4] + + (a[2] * a[6] + + a[0] * a[8] + + (a[1] * a[7] + + a[3] * a[5]) * 2) * 2; + output[9] = + (a[4] * a[5] + + a[3] * a[6] + + a[2] * a[7] + + a[1] * a[8] + + a[0] * a[9]) * 2; + output[10] = (a[5] * a[5] + + a[4] * a[6] + + a[2] * a[8] + + (a[3] * a[7] + + a[1] * a[9]) * 2) * 2; + output[11] = + (a[5] * a[6] + + a[4] * a[7] + + a[3] * a[8] + + a[2] * a[9]) * 2; + output[12] = + a[6] * a[6] + + (a[4] * a[8] + + (a[5] * a[7] + + a[3] * a[9]) * 2) * 2; + output[13] = + (a[6] * a[7] + + a[5] * a[8] + + a[4] * a[9]) * 2; + output[14] = + (a[7] * a[7] + + a[6] * a[8] + + a[5] * a[9] * 2) * 2; + output[15] = + (a[7] * a[8] + + a[6] * a[9]) * 2; + output[16] = + a[8] * a[8] + + a[7] * a[9] * 4; + output[17] = + a[8] * a[9] * 2; + output[18] = + a[9] * a[9] * 2; + return output; + } + + /** + * Computes the reciprocal of the input by elevating to the (2^255 - 19) - 2 efficiently. + * "This" must be a reduced degree, reduced coefficient polynomial. + */ + private static Polynomial25519 innerReciprocal(Polynomial25519 z) { + // In the comment we wrote the exponent of the input. + // TODO: can avoid t1? + /* 2 */ Polynomial25519 z2 = Polynomial25519.square(z); + /* 4 */ Polynomial25519 t1 = Polynomial25519.square(z2); + /* 8 */ Polynomial25519 t0 = Polynomial25519.square(t1); + /* 9 */ Polynomial25519 z9 = Polynomial25519.mult(t0, z); + /* 11 */ Polynomial25519 z11 = Polynomial25519.mult(z9, z2); + /* 22 */ t0 = Polynomial25519.square(z11); + /* 31 = 2^5 - 2^0 */ Polynomial25519 z2FiveZero = Polynomial25519.mult(t0, z9); + + /* 2^6 - 2^1 */ t0 = Polynomial25519.square(z2FiveZero); + /* 2^7 - 2^2 */ t1 = Polynomial25519.square(t0); + /* 2^8 - 2^3 */ t0 = Polynomial25519.square(t1); + /* 2^9 - 2^4 */ t1 = Polynomial25519.square(t0); + /* 2^10 - 2^5 */ t0 = Polynomial25519.square(t1); + /* 2^10 - 2^0 */ Polynomial25519 z2TenZero = Polynomial25519.mult(t0, z2FiveZero); + + /* 2^11 - 2^1 */ t0 = Polynomial25519.square(z2TenZero); + /* 2^12 - 2^2 */ t1 = Polynomial25519.square(t0); + /* 2^20 - 2^10 */ + for (int i = 2; i < 10; i += 2) { + t0 = Polynomial25519.square(t1); + t1 = Polynomial25519.square(t0); + } + /* 2^20 - 2^0 */ Polynomial25519 z2TwentyZero = Polynomial25519.mult(t1, z2TenZero); + + /* 2^21 - 2^1 */ t0 = Polynomial25519.square(z2TwentyZero); + /* 2^22 - 2^2 */ t1 = Polynomial25519.square(t0); + /* 2^40 - 2^20 */ + for (int i = 2; i < 20; i += 2) { + t0 = Polynomial25519.square(t1); + t1 = Polynomial25519.square(t0); + } + /* 2^40 - 2^0 */ t0 = Polynomial25519.mult(t1, z2TwentyZero); + + /* 2^41 - 2^1 */ t1 = Polynomial25519.square(t0); + /* 2^42 - 2^2 */ t0 = Polynomial25519.square(t1); + /* 2^50 - 2^10 */ + for (int i = 2; i < 10; i += 2) { + t1 = Polynomial25519.square(t0); + t0 = Polynomial25519.square(t1); + } + /* 2^50 - 2^0 */ Polynomial25519 z2FiftyZero = Polynomial25519.mult(t0, z2TenZero); + + /* 2^51 - 2^1 */ t0 = Polynomial25519.square(z2FiftyZero); + /* 2^52 - 2^2 */ t1 = Polynomial25519.square(t0); + /* 2^100 - 2^50 */ + for (int i = 2; i < 50; i += 2) { + t0 = Polynomial25519.square(t1); + t1 = Polynomial25519.square(t0); + } + /* 2^100 - 2^0 */ Polynomial25519 z2HundredZero = Polynomial25519.mult(t1, z2FiftyZero); + + /* 2^101 - 2^1 */ t1 = Polynomial25519.square(z2HundredZero); + /* 2^102 - 2^2 */ t0 = Polynomial25519.square(t1); + /* 2^200 - 2^100 */ + for (int i = 2; i < 100; i += 2) { + t1 = Polynomial25519.square(t0); + t0 = Polynomial25519.square(t1); + } + /* 2^200 - 2^0 */ t1 = Polynomial25519.mult(t0, z2HundredZero); + + /* 2^201 - 2^1 */ t0 = Polynomial25519.square(t1); + /* 2^202 - 2^2 */ t1 = Polynomial25519.square(t0); + /* 2^250 - 2^50 */ + for (int i = 2; i < 50; i += 2) { + t0 = Polynomial25519.square(t1); + t1 = Polynomial25519.square(t0); + } + /* 2^250 - 2^0 */ t0 = Polynomial25519.mult(t1, z2FiftyZero); + + /* 2^251 - 2^1 */ t1 = Polynomial25519.square(t0); + /* 2^252 - 2^2 */ t0 = Polynomial25519.square(t1); + /* 2^253 - 2^3 */ t1 = Polynomial25519.square(t0); + /* 2^254 - 2^4 */ t0 = Polynomial25519.square(t1); + /* 2^255 - 2^5 */ t1 = Polynomial25519.square(t0); + /* 2^255 - 21 */ return Polynomial25519.mult(t1, z11); + } + + } +} diff --git a/app/src/main/java/eidr/EddystoneEidrGenerator.java b/app/src/main/java/eidr/EddystoneEidrGenerator.java new file mode 100644 index 0000000..ca9a364 --- /dev/null +++ b/app/src/main/java/eidr/EddystoneEidrGenerator.java @@ -0,0 +1,149 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eidr; + +import android.util.Log; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + + +/** + * A sample implementation of Eddystone EIDR computation. + */ +public class EddystoneEidrGenerator { + private static final String TAG = EddystoneEidrGenerator.class.getSimpleName(); + + // The server's public ECDH Curve25519 key. Must be 32 bytes. + private byte[] serviceEcdhPublicKey; + + // The beacon's private key. Randomly generated 32-byte data. + private byte[] beaconPrivateKey; + + // The beacon's public key computed from the private key over ECDH Curve25519. + private byte[] beaconPublicKey; + + // In some test scenarios we may want to broadcast EIDs from a known Identity Key. + private byte[] beaconIdentityKey; + + /** + * Constructs an EddystoneEidrGenerator instance with a real beacon private key and a real + * service public key. + * + * @param serviceEcdhPublicKey 32-byte public key of remote server + * @param beaconEcdhPrivateKey 32-byte private key of beacon + */ + public EddystoneEidrGenerator(byte[] serviceEcdhPublicKey, byte[] beaconEcdhPrivateKey) { + checkArgument(serviceEcdhPublicKey != null && serviceEcdhPublicKey.length == 32); + checkArgument(beaconEcdhPrivateKey != null && beaconEcdhPrivateKey.length == 32); + this.serviceEcdhPublicKey = serviceEcdhPublicKey; + this.beaconPrivateKey = beaconEcdhPrivateKey; + beaconPublicKey = generateBeaconPublicKey(); + } + + /** + * Getter for the beacon Roshan + */ + public byte [] getBeaconPublicKey(){ + if(beaconPublicKey != null) + return beaconPublicKey; + return null; + } + + /** + * Sets the beacon's identity key. When set, this generator will skip the earlier steps of the + * crypto process that create an identity key (via ECDH, etc). + * + * Such use would look like: + * + * byte[] identityKey = getMyBeaconsIdentityKeyFromSomewhere(); + * int rotationExponent = getMyBeaconsRotationExponentFromThatSamePlace(); + * long beaconClockOffset = getMyBeaconsClockOffsetFromThatSamePlace(); + * long beaconNowMs = System.currentTimeMillis() - beaconClockOffset; + * EddystoneEidrGenerator eidGen = new EddystoneEidrGenerator(); + * eidGen.setIdentityKey(identityKey); + * byte[] ephemeralId = eidGen(rotationExponent, (int)(beaconNowMs / 1000)); + * + * + * @param beaconIdentityKey + */ + public void setIdentityKey(byte[] beaconIdentityKey) { + this.beaconIdentityKey = beaconIdentityKey; + // When using a given identity key, the beacon's public and private keys are unused. Nullify + // them to make sure. + beaconPublicKey = null; + beaconPrivateKey = null; + } + + /** + * Returns the beacon's public key. + */ + public byte[] generateBeaconPublicKey() { + return Curve25519.scalarMultBase(beaconPrivateKey); + } + + byte[] getSharedSecret() { + return Curve25519.scalarMult(beaconPrivateKey, serviceEcdhPublicKey); + } + + public byte[] getIdentityKey() { + if (beaconIdentityKey != null) { + return beaconIdentityKey; + } + Mac hkdfSha256Mac; + try { + hkdfSha256Mac = Mac.getInstance("HmacSHA256"); + } catch (NoSuchAlgorithmException e) { + Log.e(TAG, "Error constructing SHA256 HMAC instance", e); + return null; // XXX fix callers to cope with null + } + + byte[] publicKeys = new byte[serviceEcdhPublicKey.length + beaconPublicKey.length]; + System.arraycopy(serviceEcdhPublicKey, 0, publicKeys, 0, serviceEcdhPublicKey.length); + System.arraycopy(beaconPublicKey, 0, publicKeys, serviceEcdhPublicKey.length, beaconPublicKey.length); + + try { + hkdfSha256Mac.init(new SecretKeySpec(publicKeys, "AES")); + } catch (InvalidKeyException e) { + Log.e(TAG, "Error initializing SHA256 HMAC instance", e); + return null; + } + + byte[] sharedSecret = hkdfSha256Mac.doFinal(getSharedSecret()); + if (sharedSecret == null) { + Log.e(TAG, "Shared secret is zero. Possibly indicates a weak public key!"); + return null; + } + + try { + hkdfSha256Mac.init(new SecretKeySpec(sharedSecret, "AES")); + } catch (InvalidKeyException e) { + Log.e(TAG, "Error reinitializing SHA256 HMAC instance", e); + return null; + } + + byte[] salt = { 0x01 }; + return Arrays.copyOfRange(hkdfSha256Mac.doFinal(salt), 0, 16); + } + + private void checkArgument(boolean b) { + if (!b) { + throw new IllegalArgumentException(); + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/AuthorizedServiceTask.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/AuthorizedServiceTask.java new file mode 100644 index 0000000..1a1ed34 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/AuthorizedServiceTask.java @@ -0,0 +1,113 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package no.nordicsemi.android.nrfbeacon.nearby; + +import android.accounts.Account; +import android.app.Activity; +import android.app.Dialog; +import android.content.Intent; +import android.os.AsyncTask; +import android.util.Log; + +import com.google.android.gms.auth.GoogleAuthException; +import com.google.android.gms.auth.GoogleAuthUtil; +import com.google.android.gms.auth.GooglePlayServicesAvailabilityException; +import com.google.android.gms.auth.UserRecoverableAuthException; +import com.google.android.gms.common.GooglePlayServicesUtil; + +import java.io.IOException; + +/** + * NOP async task that allows us to check if a new user has authorized the app + * to access their account. + */ +public class AuthorizedServiceTask extends AsyncTask { + private static final String TAG = AuthorizedServiceTask.class.getSimpleName(); + //static final String authScope = "oauth2:https://www.googleapis.com/auth/userlocation.beacon.registry"; + private static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_PRX_API = 1003; + private static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_URL_SHORTNER = 1004; + private static final String AUTH_PROXIMITY_API = "oauth2:https://www.googleapis.com/auth/userlocation.beacon.registry"; + private static final String AUTH_SCOPE_URL_SHORTENER = "oauth2:https://www.googleapis.com/auth/urlshortener"; + + private final Activity activity; + private final Account account; + private String authScope; + + public AuthorizedServiceTask(Activity activity, Account accountName, final String authScope) { + this.activity = activity; + this.account = accountName; + this.authScope = authScope; + } + + @Override + protected String doInBackground(Void... params) { + Log.i(TAG, "checking authorization for " + account.name); + try { + final String token = GoogleAuthUtil.getToken(activity, account, authScope); + if(token != null){ + + } + } catch (UserRecoverableAuthException e) { + // GooglePlayServices.apk is either old, disabled, or not present + // so we need to show the user some UI in the activity to recover. + handleAuthException(activity, e); + } catch (GoogleAuthException e) { + // Some other type of unrecoverable exception has occurred. + // Report and log the error as appropriate for your app. + Log.w(TAG, "GoogleAuthException: " + e); + } catch (IOException e) { + // The fetchToken() method handles Google-specific exceptions, + // so this indicates something went wrong at a higher level. + // TIP: Check for network connectivity before starting the AsyncTask. + } + return null; + } + + private void handleAuthException(final Activity activity, final Exception e) { + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + if (e instanceof GooglePlayServicesAvailabilityException) { + // The Google Play services APK is old, disabled, or not present. + // Show a dialog created by Google Play services that allows + // the user to update the APK + int statusCode = ((GooglePlayServicesAvailabilityException) e).getConnectionStatusCode(); + Dialog dialog; + if(authScope.equals(AUTH_PROXIMITY_API)) { + dialog = GooglePlayServicesUtil.getErrorDialog( + statusCode, activity, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_PRX_API); + } else { + dialog = GooglePlayServicesUtil.getErrorDialog( + statusCode, activity, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_URL_SHORTNER); + } + dialog.show(); + } else if (e instanceof UserRecoverableAuthException) { + // Unable to authenticate, such as when the user has not yet granted + // the app access to the account, but the user can fix this. + // Forward the user to an activity in Google Play services. + Intent intent = ((UserRecoverableAuthException) e).getIntent(); + if(authScope.equals(AUTH_PROXIMITY_API)) { + activity.startActivityForResult( + intent, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_PRX_API); + } else { + activity.startActivityForResult( + intent, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_URL_SHORTNER); + } + } + } + }); + } + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/EddystoneBeaconsAdapter.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/EddystoneBeaconsAdapter.java new file mode 100644 index 0000000..ea8a8ab --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/EddystoneBeaconsAdapter.java @@ -0,0 +1,107 @@ +package no.nordicsemi.android.nrfbeacon.nearby; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Paint; +import android.net.Uri; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.UnderlineSpan; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.google.android.gms.nearby.messages.Message; + +import java.nio.charset.Charset; +import java.util.ArrayList; + +/** + * Created by rora on 22.10.2015. + */ +public class EddystoneBeaconsAdapter extends BaseAdapter { + + private ArrayList nearbyDeviceMessageList; + private LayoutInflater mInflator; + private Context context; + + public EddystoneBeaconsAdapter(Context context, ArrayList nearbyDevicesMessage) { + super(); + nearbyDeviceMessageList = nearbyDevicesMessage; + this.context = context; + mInflator = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + @Override + public int getCount() { + return nearbyDeviceMessageList.size(); + } + + @Override + public Object getItem(int position) { + return nearbyDeviceMessageList.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + public void clear() { + nearbyDeviceMessageList.clear(); + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + + ViewHolder viewHolder; + if (convertView == null) { + convertView = mInflator.inflate(R.layout.listitem_device, null); + viewHolder = new ViewHolder(); + viewHolder.tvAttachment = (TextView) convertView.findViewById(R.id.attachment_message); + viewHolder.tvNamespace = (TextView) convertView.findViewById(R.id.namespace_message); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + + Message message = nearbyDeviceMessageList.get(position); + String namespace = message.getNamespace(); + final String attachment = new String(message.getContent(), Charset.forName("UTF-8")); + SpannableString attachmentContent = null; + if(attachment.startsWith("http")) { + attachmentContent = new SpannableString(attachment); + attachmentContent.setSpan(new UnderlineSpan(), 0, attachment.length(), 0); + viewHolder.tvAttachment.setText(attachmentContent); + } else { + viewHolder.tvAttachment.setText(attachment); + } + if (namespace != null && namespace.length() > 0) + viewHolder.tvNamespace.setText(namespace); + //viewHolder.tvAttachment.setText(attachment); + + if(attachmentContent != null && attachmentContent.toString().startsWith("http")) { + //viewHolder.tvAttachment.setPaintFlags(viewHolder.tvAttachment.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + viewHolder.tvAttachment.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(attachment)); + context.startActivity(browserIntent); + } + }); + } else { + viewHolder.tvAttachment.setOnClickListener(null); + } + + return convertView; + } + + private static class ViewHolder { + TextView tvNamespace; + TextView tvAttachment; + } +} + diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/LaunchActivity.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/LaunchActivity.java new file mode 100644 index 0000000..7fa9680 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/LaunchActivity.java @@ -0,0 +1,48 @@ +/************************************************************************************************************************************************* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ************************************************************************************************************************************************/ + +package no.nordicsemi.android.nrfbeacon.nearby; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; + +public class LaunchActivity extends AppCompatActivity { + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // If this activity is the root activity of the task, the app is not running + if (isTaskRoot()) { + // Start the app before finishing + final Intent startAppIntent = new Intent(getApplicationContext(), SplashscreenActivity.class); + startAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (getIntent() != null && getIntent().getExtras() != null) + startAppIntent.putExtras(getIntent().getExtras()); + startActivity(startAppIntent); + } + + // Now finish, which will drop the user in to the activity that was at the top + // of the task stack + finish(); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/MainActivity.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/MainActivity.java new file mode 100644 index 0000000..ddd149a --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/MainActivity.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby; + +import android.Manifest; +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.support.design.widget.TabLayout; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.MenuItem; +import android.widget.Toast; + +import no.nordicsemi.android.nrfbeacon.nearby.beacon.BeaconsFragment; +import no.nordicsemi.android.nrfbeacon.nearby.update.UpdateFragment; + +public class MainActivity extends AppCompatActivity { + + public static final String OPENED_FROM_LAUNCHER = "no.nordicsemi.android.nrfbeacon.nearby.extra.opened_from_launcher"; + public static final String TAG = "BEACON"; + private static final int REQUEST_RESOLVE_ERROR = 261; //random + private static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_PRX_API = 1003; + private static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_URL_SHORTNER = 1004; + + private BeaconsFragment mBeaconsFragment; + private UpdateFragment mUpdateFragment; + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + switch (requestCode){ + case REQUEST_RESOLVE_ERROR: + if(resultCode == Activity.RESULT_OK){ + mBeaconsFragment.updateNearbyPermissionStatus(true); + } + else Toast.makeText(this, getString(R.string.rationale_permission_denied), Toast.LENGTH_SHORT).show(); + break; + case REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_PRX_API: + if(resultCode == Activity.RESULT_OK){ + Toast.makeText(this, getString(R.string.retry_beacon_registration), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, getString(R.string.rationale_permission_denied) + ". Unable to register beacon", Toast.LENGTH_SHORT).show(); + } + break; + case REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_URL_SHORTNER: + if(resultCode == Activity.RESULT_OK){ + Toast.makeText(this, getString(R.string.retry_url_shortner), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(this, getString(R.string.rationale_permission_denied) + ". Unable to shorten URL", Toast.LENGTH_SHORT).show(); + } + break; + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + // Ensure that Bluetooth exists + if (!ensureBleExists()) + finish(); + + // Setup the custom toolbar + final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + // Prepare the sliding tab layout and the view pager + final TabLayout tabLayout = (TabLayout) findViewById(R.id.sliding_tabs); + final ViewPager pager = (ViewPager) findViewById(R.id.view_pager); + //pager.setOffscreenPageLimit(2); + pager.setAdapter(new FragmentAdapter(getSupportFragmentManager())); + tabLayout.setupWithViewPager(pager); + pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + @Override + public void onPageSelected(final int position) { + Log.v(TAG, "position: " + position); + switch (position){ + case 1: + mUpdateFragment.ensurePermissionGranted(new String[]{Manifest.permission.GET_ACCOUNTS}); + break; + } + } + + @Override + public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) { + // empty + } + + @Override + public void onPageScrollStateChanged(int state) { + } + }); + + + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + onBackPressed(); + return true; + } + return false; + } + + @Override + protected void onStart() { + super.onStart(); + } + + @Override + protected void onResume() { + super.onResume(); + // we are in main fragment, show 'home up' if entered from Launcher (splash screen activity) + final boolean openedFromLauncher = getIntent().getBooleanExtra(MainActivity.OPENED_FROM_LAUNCHER, false); + getSupportActionBar().setDisplayHomeAsUpEnabled(!openedFromLauncher); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + /** + * Checks whether the device supports Bluetooth Low Energy communication + * + * @return true if BLE is supported, false otherwise + */ + private boolean ensureBleExists() { + if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { + Toast.makeText(this, R.string.no_ble, Toast.LENGTH_LONG).show(); + return false; + } + return true; + } + + public void setBeaconsFragment(BeaconsFragment beaconsFragment) { + this.mBeaconsFragment = beaconsFragment; + } + + public void setUPdateFragment(UpdateFragment updateFragment) { + this.mUpdateFragment = updateFragment; + } + + private class FragmentAdapter extends FragmentPagerAdapter { + + public FragmentAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + switch (position) { + case 0: + return new BeaconsFragment(); + default: + case 1: + return new UpdateFragment(); + } + } + + @Override + public int getCount() { + return 2; + } + + @Override + public CharSequence getPageTitle(int position) { + return getResources().getStringArray(R.array.tab_title)[position]; + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/NearbyBackgroundService.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/NearbyBackgroundService.java new file mode 100644 index 0000000..1098f85 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/NearbyBackgroundService.java @@ -0,0 +1,102 @@ +package no.nordicsemi.android.nrfbeacon.nearby; + +import android.app.IntentService; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.service.notification.StatusBarNotification; +import android.support.v4.app.NotificationCompat; +import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; + +import com.google.android.gms.nearby.Nearby; +import com.google.android.gms.nearby.messages.Message; +import com.google.android.gms.nearby.messages.MessageListener; + +import java.nio.charset.Charset; +import java.util.ArrayList; + +/** + * Created by rora on 28.01.2016. + */ +public class NearbyBackgroundService extends IntentService { + + private static final String DISPLAY_NOTIFICATION = "no.nordicsemi.android.nrfbeacon.nearby.DISPLAY_NOTIFICATION"; + private static final String REMOVE_NOTIFICATION = "no.nordicsemi.android.nrfbeacon.nearby.REMOVE_NOTIFICATION"; + private static final String NEARBY_MESSAGE = "no.nordicsemi.android.nrfbeacon.nearby.NEARBY_MESSAGE"; + public static final String NEARBY_DEVICE_DATA = "NEARBY_DEVICE_DATA"; + private static final String TAG = "BEACON"; + + private static final int OPEN_ACTIVITY_REQ = 195; // random + private static final int NOTIFICATION_ID = 1; + + private NotificationManager mNotificationManager; + private Intent mParentIntent; + private PendingIntent mPendingIntent; + private ArrayList mNearbyDevicesMessageList; + + public NearbyBackgroundService(String name) { + super(name); + } + + public NearbyBackgroundService() { + super("NearbyBackgroundService"); + } + + @Override + public void onCreate() { + super.onCreate(); + mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + mNearbyDevicesMessageList = new ArrayList<>(); + } + + + @Override + public void onDestroy() { + super.onDestroy(); + Log.v(TAG, "Destroyed"); + } + + @Override + protected void onHandleIntent(final Intent intent) { + + Nearby.Messages.handleIntent(intent, new MessageListener() { + @Override + public void onFound(Message message) { + String nearbyMessage = new String(message.getContent(), Charset.forName("UTF-8")); + Log.i(TAG, "Found message via PendingIntent: " + nearbyMessage); + sendMessage(DISPLAY_NOTIFICATION, message); + } + + @Override + public void onLost(Message message) { + String nearbyMessage = new String(message.getContent(), Charset.forName("UTF-8")); + Log.i(TAG, "Lost message via PendingIntent: " + nearbyMessage); + sendMessage(REMOVE_NOTIFICATION, message); + } + }); + } + + private void sendMessage(String broadcast, Message message) { + Intent intent; + Bundle bundle; + switch (broadcast){ + case DISPLAY_NOTIFICATION: + intent = new Intent(broadcast); + bundle = new Bundle(); + bundle.putParcelable(NEARBY_MESSAGE, message); + intent.putExtras(bundle); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + break; + case REMOVE_NOTIFICATION: + intent = new Intent(broadcast); + bundle = new Bundle(); + bundle.putParcelable(NEARBY_MESSAGE, message); + intent.putExtras(bundle); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + break; + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/SplashscreenActivity.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/SplashscreenActivity.java new file mode 100644 index 0000000..1454faf --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/SplashscreenActivity.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; + +public class SplashscreenActivity extends Activity { + /** Splash screen duration time in milliseconds */ + private static final int DELAY = 1000; + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_splashscreen); + + // Jump to MainActivity after DELAY milliseconds + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + final Intent intent = new Intent(SplashscreenActivity.this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent.putExtra(MainActivity.OPENED_FROM_LAUNCHER, true); + startActivity(intent); + finish(); + } + }, DELAY); + } + + @Override + public void onBackPressed() { + // do nothing. Protect from exiting the application when splash screen is shown + } + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/UpdateService.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/UpdateService.java new file mode 100644 index 0000000..a4c486b --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/UpdateService.java @@ -0,0 +1,1145 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.UUID; + +import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.bluetooth.BluetoothGattService; +import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothProfile; +import android.content.Intent; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.ParcelUuid; +import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; +import android.util.Pair; + +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +public class UpdateService extends Service { + private static final String TAG = "UpdateService"; + + public final static String ACTION_STATE_CHANGED = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_STATE_CHANGED"; + public final static String ACTION_GATT_ERROR = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_GATT_ERROR"; + public final static String ACTION_DONE = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_DONE"; + public final static String ACTION_UUID_READY = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_UUID_READY"; + public final static String ACTION_MAJOR_MINOR_READY = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_MAJOR_MINOR_READY"; + public final static String ACTION_RSSI_READY = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_RSSI_READY"; + public final static String ACTION_MANUFACTURER_ID_READY = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_MANUFACTURER_ID_READY"; + public final static String ACTION_ADV_INTERVAL_READY = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_ADV_INTERVAL_READY"; + public final static String ACTION_LED_STATUS_READY = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_LED_STATUS_READY"; + + public final static String ACTION_BROADCAST_CAPABILITIES = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_BROADCAST_CAPABILITIES"; + public final static String ACTION_ACTIVE_SLOT = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_ACTIVE_SLOT"; + public final static String ACTION_ADVERTISING_INTERVAL = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_ADVERTISING_INTERVAL"; + public final static String ACTION_RADIO_TX_POWER = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_RADIO_TX_POWER"; + public final static String ACTION_ADVANCED_ADVERTISED_TX_POWER = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_ADVANCED_ADVERTISED_TX_POWER"; + public final static String ACTION_LOCK_STATE = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_LOCK_STATE"; + public final static String ACTION_UNLOCK = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_UNLOCK"; + public final static String ACTION_ECDH_KEY = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_ECDH_KEY"; + public final static String ACTION_EID_IDENTITY_KEY = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_EID_IDENTITY_KEY"; + public final static String ACTION_READ_WRITE_ADV_SLOT = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_READ_WRITE_ADV_SLOT"; + public final static String ACTION_ADVANCED_FACTORY_RESET = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_ADVANCED_FACTORY_RESET"; + public final static String ACTION_ADVANCED_REMAIN_CONNECTABLE = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_ADVANCED_REMAIN_CONNECTABLE"; + public final static String ACTION_UNLOCK_BEACON = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_UNLOCK_BEACON"; + public static final String ACTION_BROADCAST_ALL_SLOT_INFO = "no.nordicsemi.android.nrfbeacon.nearby.ACTION_BROADCAST_ALL_SLOT_INFO"; + + + public final static String EXTRA_DATA = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_DATA"; + public final static String EXTRA_FRAME_TYPE = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_FRAME_TYPE"; + public final static String EXTRA_NAMESPACE_ID = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_NAMESPACE_ID"; + public final static String EXTRA_INSTANCE_ID = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_INSTANCE_ID"; + public final static String EXTRA_URL = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_URL"; + public final static String EXTRA_CLOCK_VALUE = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_CLOCK_VALUE"; + public final static String EXTRA_TIMER_EXPONENT = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_TIMER_EXPONENT"; + public final static String EXTRA_EID = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_EID"; + public final static String EXTRA_VOLTAGE = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_VOLTAGE"; + public final static String EXTRA_BEACON_TEMPERATURE = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_BEACON_TEMPERATURE"; + public final static String EXTRA_PDU_COUNT = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_PDU_COUNT"; + public final static String EXTRA_TIME_SINCE_BOOT = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_TIME_SINCE_BOOT"; + public final static String EXTRA_ETLM = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_ETLM"; + public final static String EXTRA_SALT = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_SALT"; + public final static String EXTRA_MESSAGE_INTEGRITY_CHECK = "no.nordicsemi.android.nrfbeacon.nearby.EXTRA_MESSAGE_INTEGRITY_CHECK"; + + private static final int EMPTY_SLOT = -1; + private static final int TYPE_UID = 0x00; + private static final int TYPE_URL = 0x10; + private static final int TYPE_TLM = 0x20; + private static final int TYPE_EID = 0x30; + + public static final int LOCKED = 0x00; + public static final int UNLOCKED = 0x01; + public static final int UNLOCKED_AUTOMATIC_RELOCK_DISABLED = 0x02; + + public final static int ERROR_UNSUPPORTED_DEVICE = -1; + + private int mConnectionState; + public final static int STATE_DISCONNECTED = 0; + public final static int STATE_CONNECTING = 1; + public final static int STATE_DISCOVERING_SERVICES = 2; + public final static int STATE_CONNECTED = 3; + public final static int STATE_DISCONNECTING = 4; + + public final static int SERVICE_UUID = 1; + public final static int SERVICE_MAJOR_MINOR = 2; + public final static int SERVICE_CALIBRATION = 3; + + public static final UUID EDDYSTONE_GATT_CONFIG_SERVICE_UUID = new UUID(0xA3C875008ED34BDFL, 0x8A39A01BEBEDE295L); + private static final UUID EDDYSTONE_BROADCAST_CAPABILITIES_UUID = new UUID(0xA3C875018ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_ACTIVE_SLOT_UUID = new UUID(0xA3C875028ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_ADVERTISING_INTERVAL_UUID = new UUID(0xA3C875038ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_RADIO_TX_POWER_UUID = new UUID(0xA3C875048ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_ADVANCED_ADVERTISED_TX_POWER_UUID = new UUID(0xA3C875058ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_LOCK_STATE_UUID = new UUID(0xA3C875068ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_UNLOCK_UUID = new UUID(0xA3C875078ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_ECDH_KEY_UUID = new UUID(0xA3C875088ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_EID_IDENTITY_KEY_UUID = new UUID(0xA3C875098ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_READ_WRITE_ADV_SLOT_UUID = new UUID(0xA3C8750A8ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_ADVANCED_FACTORY_RESET_UUID = new UUID(0xA3C8750B8ed34bdfL, 0x8a39a01bebede295L); + private static final UUID EDDYSTONE_ADVANCED_REMAIN_CONNECTABLE_UUID = new UUID(0xA3C8750C8ed34bdfL, 0x8a39a01bebede295L); + + private BluetoothAdapter mAdapter; + private BluetoothDevice mBluetoothDevice; + private BluetoothGatt mBluetoothGatt; + private BluetoothGattCharacteristic mBroadcastCapabilitesCharacterisitc; + private BluetoothGattCharacteristic mRadioTxPowerCharacteristic; + private BluetoothGattCharacteristic mActiveSlotCharacteristic; + private BluetoothGattCharacteristic mAdvertisingIntervalCharacteristic; + private BluetoothGattCharacteristic mAdvancedAdvertisedTxPowerCharacteristic; + private BluetoothGattCharacteristic mLockStateCharacteristic; + private BluetoothGattCharacteristic mUnlockCharacteristic; + private BluetoothGattCharacteristic mPublicEcdhKeyCharacteristic; + private BluetoothGattCharacteristic mEidIdentityKeyCharacteristic; + private BluetoothGattCharacteristic mReadWriteAdvSlotCharacteristic; + private BluetoothGattCharacteristic mAdvancedFactoryResetCharacteristic; + private BluetoothGattCharacteristic mAdvancedRemainConnectableCharacteristic; + + private Handler mHandler; + private boolean mIsBeaconLocked = true; + private final Queue mQueue = new LinkedList(); + private boolean mConfigureSlot = false; + private boolean mReadlAllSlots = false; + private int mSlotCounter = 0; + + private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { + + int mLockState = 0x00; + + @Override + public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) { + if (status != BluetoothGatt.GATT_SUCCESS) { + Log.v("BEACON", "Connection state change error: " + status); + broadcastError(status); + return; + } + + Log.v("BEACON", "Connection state change: " + newState); + + if (newState == BluetoothProfile.STATE_CONNECTED) { + setState(STATE_DISCOVERING_SERVICES); + mActiveSlotsTypes.clear(); + // Attempts to discover services after successful connection. + Log.v("BEACON", "delaying service discovery for 2s"); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + gatt.discoverServices(); + } + }, 2500); + Log.v("BEACON", "Calling gatt.discoverServies"); + } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { + mQueue.clear(); + mActiveSlotsTypes.clear(); + setState(STATE_DISCONNECTED); + refreshDeviceCache(gatt); + if(gatt != null) + gatt.close(); + mBluetoothGatt = null; + stopSelf(); + } + } + + @Override + public void onServicesDiscovered(final BluetoothGatt gatt, final int status) { + if (status != BluetoothGatt.GATT_SUCCESS) { + Log.v("BEACON", "Service discovery error: " + status); + broadcastError(status); + return; + } + Log.v("BEACON", "onServices Discovered"); + // We have successfully connected + setState(STATE_CONNECTED); + + // Search for config service + final BluetoothGattService configService = gatt.getService(EDDYSTONE_GATT_CONFIG_SERVICE_UUID); + if (configService == null) { + // Config service is not present + Log.v("BEACON", "Gatt error on service discovery: " + ERROR_UNSUPPORTED_DEVICE); + broadcastError(ERROR_UNSUPPORTED_DEVICE); + setState(STATE_DISCONNECTING); + gatt.disconnect(); + return; + } + + mBroadcastCapabilitesCharacterisitc = configService.getCharacteristic(EDDYSTONE_BROADCAST_CAPABILITIES_UUID); + mRadioTxPowerCharacteristic = configService.getCharacteristic(EDDYSTONE_RADIO_TX_POWER_UUID); + mActiveSlotCharacteristic = configService.getCharacteristic(EDDYSTONE_ACTIVE_SLOT_UUID); + mAdvertisingIntervalCharacteristic = configService.getCharacteristic(EDDYSTONE_ADVERTISING_INTERVAL_UUID); + mAdvancedAdvertisedTxPowerCharacteristic = configService.getCharacteristic(EDDYSTONE_ADVANCED_ADVERTISED_TX_POWER_UUID); + mLockStateCharacteristic = configService.getCharacteristic(EDDYSTONE_LOCK_STATE_UUID); + mUnlockCharacteristic = configService.getCharacteristic(EDDYSTONE_UNLOCK_UUID); + mPublicEcdhKeyCharacteristic = configService.getCharacteristic(EDDYSTONE_ECDH_KEY_UUID); + mEidIdentityKeyCharacteristic = configService.getCharacteristic(EDDYSTONE_EID_IDENTITY_KEY_UUID); + mReadWriteAdvSlotCharacteristic = configService.getCharacteristic(EDDYSTONE_READ_WRITE_ADV_SLOT_UUID); + mAdvancedFactoryResetCharacteristic = configService.getCharacteristic(EDDYSTONE_ADVANCED_FACTORY_RESET_UUID); + mAdvancedRemainConnectableCharacteristic = configService.getCharacteristic(EDDYSTONE_ADVANCED_REMAIN_CONNECTABLE_UUID); + Log.v("BEACON", "Service discovery complete"); + if (mIsBeaconLocked) { + Log.v("BEACON", "Beacon Locked: " + mIsBeaconLocked); + add(RequestType.READ_CHARACTERISTIC, mUnlockCharacteristic); + Log.v("BEACON", "Read Challenge and queue size: " + mQueue.size()); + } + } + + @Override + public void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) { + if (status != BluetoothGatt.GATT_SUCCESS) { + Log.v("BEACON", "Characteristic write error: " + status); + broadcastError(status); + return; + } + + if (EDDYSTONE_ACTIVE_SLOT_UUID.equals(characteristic.getUuid())) { + if(mReadlAllSlots) + add(RequestType.READ_CHARACTERISTIC, mActiveSlotCharacteristic); + else if (!mStartReadingInitialCharacteristics) { + add(RequestType.READ_CHARACTERISTIC, mActiveSlotCharacteristic); + startReadingCharacteristicsForActiveSlot(); + } + else { + mStartReadingInitialCharacteristics = false; + add(RequestType.READ_CHARACTERISTIC, mActiveSlotCharacteristic); + } + } else if (EDDYSTONE_ADVERTISING_INTERVAL_UUID.equals(characteristic.getUuid())) { + add(RequestType.READ_CHARACTERISTIC, mAdvertisingIntervalCharacteristic); + } else if (EDDYSTONE_RADIO_TX_POWER_UUID.equals(characteristic.getUuid())) { + add(RequestType.READ_CHARACTERISTIC, mRadioTxPowerCharacteristic); + } else if (mAdvancedAdvertisedTxPowerCharacteristic != null && EDDYSTONE_ADVANCED_ADVERTISED_TX_POWER_UUID.equals(characteristic.getUuid())) { + add(RequestType.READ_CHARACTERISTIC, mAdvancedAdvertisedTxPowerCharacteristic); + } else if (EDDYSTONE_LOCK_STATE_UUID.equals(characteristic.getUuid())) { + broadcastLockState(ParserUtils.getIntValue(characteristic.getValue(), 0, BluetoothGattCharacteristic.FORMAT_UINT8)); + } else if (EDDYSTONE_UNLOCK_UUID.equals(characteristic.getUuid())) { + if (mIsBeaconLocked) + add(RequestType.READ_CHARACTERISTIC, mLockStateCharacteristic); + } else if (EDDYSTONE_READ_WRITE_ADV_SLOT_UUID.equals(characteristic.getUuid())) { + startReadingCharacteristicsForActiveSlot(); + } else if (mAdvancedFactoryResetCharacteristic != null && EDDYSTONE_ADVANCED_FACTORY_RESET_UUID.equals(characteristic.getUuid())) { + broadcastAdvancedFactoryReset(characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0)); + } else if (mAdvancedRemainConnectableCharacteristic != null && EDDYSTONE_ADVANCED_REMAIN_CONNECTABLE_UUID.equals(characteristic.getUuid())) { + add(RequestType.READ_CHARACTERISTIC, mAdvancedFactoryResetCharacteristic); + } + processNext(); + } + + @Override + public void onCharacteristicRead(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) { + if (status != BluetoothGatt.GATT_SUCCESS) { + logw("Characteristic read error: " + status); + broadcastError(status); + return; + } + if (mIsBeaconLocked) { + if (EDDYSTONE_UNLOCK_UUID.equals(characteristic.getUuid())) { + Log.v("BEACON", "Broadcasting challenge"); + broadcastUnlockRequest(characteristic.getValue()); + processNext(); + return; + } else if (EDDYSTONE_LOCK_STATE_UUID.equals(characteristic.getUuid())) { + mLockState = ParserUtils.getIntValue(characteristic.getValue(), 0, BluetoothGattCharacteristic.FORMAT_UINT8); + switch (mLockState) { + case LOCKED: + mIsBeaconLocked = true; + processNext(); + return; + case UNLOCKED: + mIsBeaconLocked = false; + mLockState = UNLOCKED; + broadcastLockState(mLockState); + processNext(); + mReadlAllSlots = true; + add(RequestType.READ_CHARACTERISTIC, mBroadcastCapabilitesCharacterisitc); + return; + case UNLOCKED_AUTOMATIC_RELOCK_DISABLED: + mIsBeaconLocked = false; + mLockState = UNLOCKED_AUTOMATIC_RELOCK_DISABLED; + broadcastLockState(mLockState); + processNext(); + mReadlAllSlots = true; + add(RequestType.READ_CHARACTERISTIC, mBroadcastCapabilitesCharacterisitc); + return; + } + } + } + + if (EDDYSTONE_BROADCAST_CAPABILITIES_UUID.equals(characteristic.getUuid())) { + broadcastBeaconCapabilities(characteristic.getValue()); + startReadingAllActiveSlots(characteristic.getValue()); + } else if (EDDYSTONE_ACTIVE_SLOT_UUID.equals(characteristic.getUuid())) { + + if(mReadlAllSlots){ + mSlotCounter = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0); + if(mSlotCounter <= mMaxSlots - 1) { + add(RequestType.READ_CHARACTERISTIC, mReadWriteAdvSlotCharacteristic); + } else stopReadingAllActiveSlots(); + } else broadcastActiveSlot(characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0)); + } else if (EDDYSTONE_ADVERTISING_INTERVAL_UUID.equals(characteristic.getUuid())) { + broadcastAdvertisingInterval(ParserUtils.getIntValue(characteristic.getValue(), 0, ParserUtils.FORMAT_UINT16_BIG_INDIAN)); + } else if (EDDYSTONE_RADIO_TX_POWER_UUID.equals(characteristic.getUuid())) { + broadcastRadioTxPower(characteristic.getValue()); + } else if (EDDYSTONE_ADVANCED_ADVERTISED_TX_POWER_UUID.equals(characteristic.getUuid())) { + broadcastAdvancedAdvertisedTxPower(characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0)); + } else if (EDDYSTONE_LOCK_STATE_UUID.equals(characteristic.getUuid())) { + Log.v("Beacon", "Lock state: " + ParserUtils.getIntValue(characteristic.getValue(), 0, BluetoothGattCharacteristic.FORMAT_UINT8)); + broadcastLockState(mLockState); + } else if (EDDYSTONE_UNLOCK_UUID.equals(characteristic.getUuid())) { + } else if (EDDYSTONE_ECDH_KEY_UUID.equals(characteristic.getUuid())) { + broadcastEcdhKey(characteristic.getValue()); + } else if (EDDYSTONE_EID_IDENTITY_KEY_UUID.equals(characteristic.getUuid())) { + broadcastEidIdentityKey(characteristic.getValue()); + } else if (EDDYSTONE_READ_WRITE_ADV_SLOT_UUID.equals(characteristic.getUuid())) { + broadcastReadWriteAdvSlot(characteristic.getValue()); + } else if (EDDYSTONE_ADVANCED_REMAIN_CONNECTABLE_UUID.equals(characteristic.getUuid())) { + broadcastAdvancedRemainConnectable(characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0)); + } + processNext(); + } + }; + + private int mMaxSlots = -1; + private int mMaxEidSlots = -1; + private ArrayList mActiveSlotsTypes = new ArrayList<>(); + private boolean mStartReadingInitialCharacteristics = false; + + public class ServiceBinder extends Binder { + + public byte[] mBeaconLockCode; + + /** + * Connects to the service. The bluetooth device must have been passed during binding to the service in {@link UpdateService#EXTRA_DATA} field. + * + * @return true if connection process has been initiated + */ + public boolean connect() { + if (mAdapter == null) { + logw("BluetoothAdapter not initialized or unspecified address."); + return false; + } + + if (mBluetoothDevice == null) { + logw("Target device not specified. Start service with the BluetoothDevice set in EXTRA_DATA field."); + return false; + } + + // the device may be already connected + if (mConnectionState == STATE_CONNECTED) { + return true; + } + + setState(STATE_CONNECTING); + mBluetoothGatt = mBluetoothDevice.connectGatt(UpdateService.this, false, mGattCallback); + return true; + } + + /** + * Disconnects from the device and closes the Bluetooth GATT object afterwards. + */ + public void disconnectAndClose() { + // This sometimes happen when called from UpdateService.ACTION_GATT_ERROR event receiver in UpdateFragment. + if (mBluetoothGatt == null) + return; + + setState(STATE_DISCONNECTING); + mBluetoothGatt.disconnect(); + + // Sometimes the connection gets error 129 or 133. Calling disconnect() method does not really disconnect... sometimes the connection is already broken. + // Here we have a security check that notifies UI about disconnection even if onConnectionStateChange(...) has not been called. + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (mConnectionState == STATE_DISCONNECTING) + mGattCallback.onConnectionStateChange(mBluetoothGatt, BluetoothGatt.GATT_SUCCESS, BluetoothProfile.STATE_DISCONNECTED); + } + }, 1500); + } + + /** + * Reads all the values from the device, one by one. + * + * @return true if at least one required characteristic has been found on the beacon. + */ + public boolean read() { + if (mBluetoothGatt == null) + return false; + + if (mBroadcastCapabilitesCharacterisitc != null) { + mBluetoothGatt.readCharacteristic(mBroadcastCapabilitesCharacterisitc); + return true; + } else if (mActiveSlotCharacteristic != null) { + mBluetoothGatt.readCharacteristic(mActiveSlotCharacteristic); + return true; + } else if (mAdvertisingIntervalCharacteristic != null) { + mBluetoothGatt.readCharacteristic(mAdvertisingIntervalCharacteristic); + return true; + } + return false; + } + + /** + * Returns true if the beacon supports the advanced configuration. + */ + public boolean isAdvancedSupported() { + return mAdvancedAdvertisedTxPowerCharacteristic != null || mLockStateCharacteristic != null || mUnlockCharacteristic != null; + } + + public int getState() { + return mConnectionState; + } + + //Unlocking the beacon by writing to the unclock characteristic which is called when a client connects to the beacon's configuration service + public void unlockBeacon(final byte[] encryptedLockCode, final byte[] beaconLockCode) { + mBeaconLockCode = beaconLockCode; + if(mUnlockCharacteristic.setValue(encryptedLockCode)) { + add(RequestType.WRITE_CHARACTERISTIC, mUnlockCharacteristic); + } + } + + //Changing active slot to the selected active slot + public void changeToSelectedActiveSlot(final byte [] position) { + if(mActiveSlotCharacteristic.setValue(position)) { + add(RequestType.WRITE_CHARACTERISTIC, mActiveSlotCharacteristic); + } + } + + public void configureActiveSlot(final byte [] newSlotData, final String frameType) { + if(mReadWriteAdvSlotCharacteristic.setValue(newSlotData)){ + mConfigureSlot = true; + final int activeSlot = getActiveSlot(); + mActiveSlotsTypes.set(activeSlot, frameType); //Update the slotList on new slot configuration + add(RequestType.WRITE_CHARACTERISTIC, mReadWriteAdvSlotCharacteristic); + } + } + + public void configureRadioTxPower(byte[] radioTxPower) { + if(mRadioTxPowerCharacteristic.setValue(radioTxPower)){ + add(RequestType.WRITE_CHARACTERISTIC, mRadioTxPowerCharacteristic); + } + } + + public void configureAdvancedAdvertisedTxPower(final byte[] radioTxPower) { + if(mAdvancedAdvertisedTxPowerCharacteristic.setValue(radioTxPower)){ + add(RequestType.WRITE_CHARACTERISTIC, mAdvancedAdvertisedTxPowerCharacteristic); + } + } + public void configureAdvertistingInterval(byte[] advertisingInterval) { + if(mAdvertisingIntervalCharacteristic.setValue(advertisingInterval)) + add(RequestType.WRITE_CHARACTERISTIC, mAdvertisingIntervalCharacteristic); + } + + public void lockBeacon(byte[] lockCode) { + if(mLockStateCharacteristic.setValue(lockCode)){ + add(RequestType.WRITE_CHARACTERISTIC, mLockStateCharacteristic); + } + } + + public void startReadingCharacteristicsForActiveSlot() { + add(RequestType.READ_CHARACTERISTIC, mAdvertisingIntervalCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mRadioTxPowerCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mReadWriteAdvSlotCharacteristic); + } + + public void startReadingInitialCharacteristicsSet(){ + add(RequestType.READ_CHARACTERISTIC, mBroadcastCapabilitesCharacterisitc); + add(RequestType.READ_CHARACTERISTIC, mActiveSlotCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mAdvertisingIntervalCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mRadioTxPowerCharacteristic); + if(mAdvancedAdvertisedTxPowerCharacteristic != null) + add(RequestType.READ_CHARACTERISTIC, mAdvancedAdvertisedTxPowerCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mLockStateCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mReadWriteAdvSlotCharacteristic); + if(mAdvancedRemainConnectableCharacteristic != null) + add(RequestType.READ_CHARACTERISTIC, mAdvancedRemainConnectableCharacteristic); + } + + public byte [] getBroadcastCapabilities(){ + final BluetoothGattCharacteristic characteristic = mBroadcastCapabilitesCharacterisitc; + if(characteristic != null){ + final byte [] data = characteristic.getValue(); + if(data == null || data.length < 7){ + return null; + } + return data; + } + return null; + } + + /** + * Obtains the cached value of the active slot characteristic. If the value has not been obtained yet using {@link #read()}, or the characteristic has not been found on the beacon, + * -1 is returned. + * + * @return the advertising interval or -1 + */ + public int getActiveSlot() { + final BluetoothGattCharacteristic characteristic = mActiveSlotCharacteristic; + if(characteristic != null){ + final byte [] data = characteristic.getValue(); + if(data == null || data.length == 0){ + return -1; + } + return characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0); + } + return -1; + } + + /** + * Obtains the cached value of the advertising interval characteristic. If the value has not been obtained yet using {@link #read()}, or the characteristic has not been found on the beacon, + * null is returned. + * + * @return the advertising interval or null + */ + public Integer getAdvInterval() { + final BluetoothGattCharacteristic characteristic = mAdvertisingIntervalCharacteristic; + if (characteristic != null) { + final byte[] data = characteristic.getValue(); + if (data == null || data.length == 0) + return null; + return ParserUtils.getIntValue(characteristic.getValue(), 0, ParserUtils.FORMAT_UINT16_BIG_INDIAN); + } + return null; + } + + /** + * Obtains the cached value of the Radio Tx Power characteristic. If the value has not been obtained yet using {@link #read()}, or the characteristic has not been found on the beacon, + * null is returned. + * + * @return the Radio Tx Power or null + */ + public Integer getRadioTxPower() { + final BluetoothGattCharacteristic characteristic = mRadioTxPowerCharacteristic; + if (characteristic != null) { + final byte[] data = characteristic.getValue(); + if (data == null || data.length == 0) + return null; + return characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0); + } + return null; + } + + /** + * Obtains the cached value of the Advanced Advertised Tx Power characteristic. If the value has not been obtained yet using {@link #read()}, or the characteristic has not been found on the beacon, + * null is returned. + * + * @return the Advanced Advertised Tx Power or null + */ + public Integer getAdvancedAdvertisedTxPower() { + if(mAdvancedAdvertisedTxPowerCharacteristic == null) + return null; + + final BluetoothGattCharacteristic characteristic = mAdvancedAdvertisedTxPowerCharacteristic; + if (characteristic != null) { + final byte[] data = characteristic.getValue(); + if (data == null || data.length == 0) + return null; + return characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0); + } + return null; + } + + /** + * Obtains the cached value of the Lock State characteristic. If the value has not been obtained yet using {@link #read()}, or the characteristic has not been found on the beacon, + * null is returned. + * + * @return the Lock State or null + */ + public Integer getLockState() { + final BluetoothGattCharacteristic characteristic = mLockStateCharacteristic; + if (characteristic != null) { + final byte[] data = characteristic.getValue(); + if (data == null || data.length == 0) + return null; + return ParserUtils.getIntValue(characteristic.getValue(), 0, BluetoothGattCharacteristic.FORMAT_UINT8); + } + return null; + } + + /** + * Obtains the cached value of the Public ECDH Key characteristic. If the value has not been obtained yet using {@link #read()}, or the characteristic has not been found on the beacon, + * null is returned. + * + * @return the Public ECDH Key or null + */ + public byte[] getBeaconPublicEcdhKey() { + final BluetoothGattCharacteristic characteristic = mPublicEcdhKeyCharacteristic; + if (characteristic != null) { + final byte[] data = characteristic.getValue(); + if (data == null || data.length == 0) + return null; + return characteristic.getValue(); + } + return null; + } + + /** + * Obtains the cached value of the Encrypted Identity Key characteristic. If the value has not been obtained yet using {@link #read()}, or the characteristic has not been found on the beacon, + * null is returned. + * + * @return the Encrypted Identity Key or null + */ + public byte[] getIdentityKey() { + final BluetoothGattCharacteristic characteristic = mEidIdentityKeyCharacteristic; + if (characteristic != null) { + final byte[] data = characteristic.getValue(); + if (data == null || data.length == 0) + return null; + return characteristic.getValue(); + } + return null; + } + + /** + * Obtains the cached value of the Read Write Adv Slot characteristic. If the value has not been obtained yet using {@link #read()}, or the characteristic has not been found on the beacon, + * null is returned. + * + * @return the Read Write Adv Slot or null + */ + public byte[] getReadWriteAdvSlotData() { + final BluetoothGattCharacteristic characteristic = mReadWriteAdvSlotCharacteristic; + if (characteristic != null) { + final byte[] data = characteristic.getValue(); + if (data == null || data.length == 0) + return null; + return characteristic.getValue(); + } + return null; + } + + /** + * Get beacon lock code stored in the service + * + * @return the beacon lock code or null + */ + public byte[] getBeaconLockCode() { + if(mBeaconLockCode != null) + return mBeaconLockCode; + return null; + } + + /** + * Get beacon slot information stored in the service + * + * @return the beacon slot iformation or null + */ + public ArrayList getAllSlotInformation() { + return mActiveSlotsTypes; + } + } + + @Override + public void onCreate() { + super.onCreate(); + + initialize(); + mHandler = new Handler(); + mConnectionState = STATE_DISCONNECTED; + } + + @Override + public void onDestroy() { + super.onDestroy(); + + if (mBluetoothGatt != null) + mBluetoothGatt.disconnect(); + mHandler = null; + mBluetoothDevice = null; + } + + @Override + public IBinder onBind(final Intent intent) { + return new ServiceBinder(); + } + + @Override + public boolean onUnbind(final Intent intent) { + // We want to allow rebinding + return true; + } + + @Override + public int onStartCommand(final Intent intent, final int flags, final int startId) { + mBluetoothDevice = intent.getParcelableExtra(EXTRA_DATA); + return START_NOT_STICKY; + } + + /** + * Initializes a reference to the local Bluetooth adapter. + */ + private void initialize() { + final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); + mAdapter = bluetoothManager.getAdapter(); + } + + private void setState(final int state) { + mConnectionState = state; + final Intent intent = new Intent(ACTION_STATE_CHANGED); + intent.putExtra(EXTRA_DATA, state); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastUuid(final UUID uuid) { + final Intent intent = new Intent(ACTION_UUID_READY); + intent.putExtra(EXTRA_DATA, new ParcelUuid(uuid)); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastBeaconCapabilities(final byte [] broadcastCapabilities) { + final Intent intent = new Intent(ACTION_BROADCAST_CAPABILITIES); + intent.putExtra(EXTRA_DATA, broadcastCapabilities); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastActiveSlot(final boolean activeSlot) { + final Intent intent = new Intent(ACTION_ACTIVE_SLOT); + if(activeSlot) + intent.putExtra(EXTRA_DATA, 0); + else + intent.putExtra(EXTRA_DATA, -1); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastActiveSlot(final int activeSlot) { + final Intent intent = new Intent(ACTION_ACTIVE_SLOT); + intent.putExtra(EXTRA_DATA, activeSlot); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastAdvertisingInterval(final int advertisingInterval) { + final Intent intent = new Intent(ACTION_ADVERTISING_INTERVAL); + intent.putExtra(EXTRA_DATA, advertisingInterval); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastRadioTxPower(final byte [] radioTxPower) { + final Intent intent = new Intent(ACTION_RADIO_TX_POWER); + intent.putExtra(EXTRA_DATA, radioTxPower); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastAdvancedAdvertisedTxPower(final int advertisedTxPower) { + final Intent intent = new Intent(ACTION_ADVANCED_ADVERTISED_TX_POWER); + intent.putExtra(EXTRA_DATA, advertisedTxPower); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastLockState(final int lockState) { + final Intent intent = new Intent(ACTION_LOCK_STATE); + intent.putExtra(EXTRA_DATA, lockState); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastUnlock(final byte [] unlock) { + final Intent intent = new Intent(ACTION_UNLOCK); + intent.putExtra(EXTRA_DATA, unlock); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastEcdhKey(final byte [] ecdhKey) { + final Intent intent = new Intent(ACTION_ECDH_KEY); + intent.putExtra(EXTRA_DATA, ecdhKey); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastEidIdentityKey(final byte [] identityKey) { + final Intent intent = new Intent(ACTION_EID_IDENTITY_KEY); + intent.putExtra(EXTRA_DATA, identityKey); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastReadWriteAdvSlot(final byte [] readWriteAdvSlot) { + final Intent intent = new Intent(ACTION_READ_WRITE_ADV_SLOT); + if(readWriteAdvSlot == null || readWriteAdvSlot.length == 0){ + if(mReadlAllSlots) { + mActiveSlotsTypes.add("EMPTY"); + mSlotCounter = mSlotCounter + 1 ; + if(mSlotCounter <= mMaxSlots - 1 ) { + if (mActiveSlotCharacteristic.setValue(new byte[]{(byte) mSlotCounter})) + add(RequestType.WRITE_CHARACTERISTIC, mActiveSlotCharacteristic); + } else stopReadingAllActiveSlots(); + } else { + intent.putExtra(EXTRA_FRAME_TYPE, EMPTY_SLOT); + intent.putExtra(EXTRA_DATA, readWriteAdvSlot); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + return; + } + final int frameType = ParserUtils.getIntValue(readWriteAdvSlot, 0, BluetoothGattCharacteristic.FORMAT_UINT8); + + switch (frameType){ + case TYPE_UID: + if(mReadlAllSlots) { + mActiveSlotsTypes.add("UID"); + mSlotCounter = mSlotCounter + 1 ; + if(mSlotCounter <= mMaxSlots - 1 ) { + if (mActiveSlotCharacteristic.setValue(new byte[]{(byte) mSlotCounter})) + add(RequestType.WRITE_CHARACTERISTIC, mActiveSlotCharacteristic); + } else stopReadingAllActiveSlots(); + return; + } + intent.putExtra(EXTRA_FRAME_TYPE, frameType); + intent.putExtra(EXTRA_NAMESPACE_ID, ParserUtils.bytesToHex(readWriteAdvSlot, 2, 10, true)); + intent.putExtra(EXTRA_INSTANCE_ID, ParserUtils.bytesToHex(readWriteAdvSlot, 12, 6, true)); + intent.putExtra(EXTRA_DATA, readWriteAdvSlot); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + break; + case TYPE_URL: + if(mReadlAllSlots) { + mActiveSlotsTypes.add("URL"); + mSlotCounter = mSlotCounter + 1 ; + if(mSlotCounter <= mMaxSlots - 1 ) { + if (mActiveSlotCharacteristic.setValue(new byte[]{(byte) mSlotCounter})) + add(RequestType.WRITE_CHARACTERISTIC, mActiveSlotCharacteristic); + } else stopReadingAllActiveSlots(); + return; + } + + intent.putExtra(EXTRA_FRAME_TYPE, frameType); + intent.putExtra(EXTRA_URL, ParserUtils.decodeUri(readWriteAdvSlot, 2, readWriteAdvSlot.length-2)); + intent.putExtra(EXTRA_DATA, readWriteAdvSlot); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + break; + case TYPE_TLM: + if(mReadlAllSlots) { + mActiveSlotsTypes.add("TLM"); + mSlotCounter = mSlotCounter + 1 ; + if(mSlotCounter <= mMaxSlots - 1 ) { + if (mActiveSlotCharacteristic.setValue(new byte[]{(byte) mSlotCounter})) + add(RequestType.WRITE_CHARACTERISTIC, mActiveSlotCharacteristic); + } else stopReadingAllActiveSlots(); + return; + } + + intent.putExtra(EXTRA_FRAME_TYPE, frameType); + if(mActiveSlotsTypes.contains("EID")){ + intent.putExtra(EXTRA_ETLM, ParserUtils.bytesToHex(readWriteAdvSlot, 2, 12, true)); + intent.putExtra(EXTRA_SALT, ParserUtils.bytesToHex(readWriteAdvSlot, 14, 2, true)); + intent.putExtra(EXTRA_MESSAGE_INTEGRITY_CHECK, ParserUtils.bytesToHex(readWriteAdvSlot, 16, 2, true)); + intent.putExtra(EXTRA_DATA, readWriteAdvSlot); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + return; + } + + final int voltage = ParserUtils.decodeUint16BigEndian(readWriteAdvSlot, 2); + if(voltage > 0){ + intent.putExtra(EXTRA_VOLTAGE, String.valueOf(voltage) + getString(R.string.voltage_unit)); + } else { + intent.putExtra(EXTRA_VOLTAGE, getString(R.string.batt_voltage_unsupported)); + } + + final float temp = ParserUtils.decode88FixedPointNotation(readWriteAdvSlot, 4); + if (temp > -128.0f) + intent.putExtra(EXTRA_BEACON_TEMPERATURE, String.valueOf(temp) + getString(R.string.temperature_unit)); + else + intent.putExtra(EXTRA_BEACON_TEMPERATURE, getString(R.string.temperature_unsupported)); + + intent.putExtra(EXTRA_PDU_COUNT, String.valueOf(ParserUtils.decodeUint32BigEndian(readWriteAdvSlot, 6))); + intent.putExtra(EXTRA_TIME_SINCE_BOOT, String.valueOf(ParserUtils.decodeUint32BigEndian(readWriteAdvSlot, 10) * 100)); + intent.putExtra(EXTRA_DATA, readWriteAdvSlot); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + break; + case TYPE_EID: + if(mReadlAllSlots) { + mActiveSlotsTypes.add("EID"); + mSlotCounter = mSlotCounter + 1 ; + if(mSlotCounter <= mMaxSlots - 1 ) + if (mActiveSlotCharacteristic.setValue(new byte[]{(byte) mSlotCounter})) + add(RequestType.WRITE_CHARACTERISTIC, mActiveSlotCharacteristic); + else stopReadingAllActiveSlots(); + return; + } + add(RequestType.READ_CHARACTERISTIC, mPublicEcdhKeyCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mEidIdentityKeyCharacteristic); + intent.putExtra(EXTRA_FRAME_TYPE, frameType); + intent.putExtra(EXTRA_TIMER_EXPONENT, String.valueOf(ParserUtils.getIntValue(readWriteAdvSlot, 1, BluetoothGattCharacteristic.FORMAT_UINT8))); + intent.putExtra(EXTRA_CLOCK_VALUE, String.valueOf(ParserUtils.getIntValue(readWriteAdvSlot, 2, ParserUtils.FORMAT_UINT32_BIG_INDIAN))); + intent.putExtra(EXTRA_EID, String.valueOf(ParserUtils.bytesToHex(readWriteAdvSlot, 6, 8, true))); + intent.putExtra(EXTRA_DATA, readWriteAdvSlot); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + break; + } + } + + private void broadcastAdvancedFactoryReset(final int factoryReset) { + final Intent intent = new Intent(ACTION_ADVANCED_FACTORY_RESET); + intent.putExtra(EXTRA_DATA, factoryReset); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastAdvancedRemainConnectable(final int remainConnectable) { + final Intent intent = new Intent(ACTION_ADVANCED_REMAIN_CONNECTABLE); + if(remainConnectable > 0) + intent.putExtra(EXTRA_DATA, true); + else + intent.putExtra(EXTRA_DATA, false); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastError(final int error) { + final Intent intent = new Intent(ACTION_GATT_ERROR); + intent.putExtra(EXTRA_DATA, error); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastUnlockRequest(final byte [] challenge) { + final Intent intent = new Intent(ACTION_UNLOCK_BEACON); + intent.putExtra(EXTRA_DATA, challenge); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void broadcastAllSlotInformation(){ + final Intent intent = new Intent(ACTION_BROADCAST_ALL_SLOT_INFO); + intent.putStringArrayListExtra(EXTRA_DATA, mActiveSlotsTypes); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + private void startReadingAllActiveSlots(byte [] mBroadcastCapabilities) { + if (mMaxSlots < 0) + mMaxSlots = ParserUtils.getIntValue(mBroadcastCapabilities, 1, BluetoothGattCharacteristic.FORMAT_UINT8); + if (mMaxEidSlots < 0) + mMaxEidSlots = ParserUtils.getIntValue(mBroadcastCapabilities, 2, BluetoothGattCharacteristic.FORMAT_UINT8); + if (mSlotCounter < mMaxSlots) + add(RequestType.READ_CHARACTERISTIC, mActiveSlotCharacteristic); + } + + private void stopReadingAllActiveSlots() { + mReadlAllSlots = false; + mSlotCounter = 0; + mStartReadingInitialCharacteristics = true; + if(mActiveSlotCharacteristic.setValue(new byte [] {(byte) mSlotCounter})) { + add(RequestType.WRITE_CHARACTERISTIC, mActiveSlotCharacteristic); + startReadingCharacteristicsForActiveSlot(); + } + } + + private void startReadingInitialCharacteristicsSet() { + add(RequestType.READ_CHARACTERISTIC, mBroadcastCapabilitesCharacterisitc); + if(!mReadlAllSlots) { + add(RequestType.READ_CHARACTERISTIC, mActiveSlotCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mAdvertisingIntervalCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mRadioTxPowerCharacteristic); + if (mAdvancedAdvertisedTxPowerCharacteristic != null) + add(RequestType.READ_CHARACTERISTIC, mAdvancedAdvertisedTxPowerCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mLockStateCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mReadWriteAdvSlotCharacteristic); + if (mAdvancedRemainConnectableCharacteristic != null) + add(RequestType.READ_CHARACTERISTIC, mAdvancedRemainConnectableCharacteristic); + } + } + + private void startReadingCharacteristicsForActiveSlot() { + add(RequestType.READ_CHARACTERISTIC, mAdvertisingIntervalCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mRadioTxPowerCharacteristic); + if (mAdvancedAdvertisedTxPowerCharacteristic != null) + add(RequestType.READ_CHARACTERISTIC, mAdvancedAdvertisedTxPowerCharacteristic); + add(RequestType.READ_CHARACTERISTIC, mReadWriteAdvSlotCharacteristic); + if (mAdvancedRemainConnectableCharacteristic != null) + add(RequestType.READ_CHARACTERISTIC, mAdvancedRemainConnectableCharacteristic); + broadcastAllSlotInformation(); + } + + /** + * Clears the device cache. + *

+ * CAUTION:
+ * It is very unsafe to call the refresh() method. First of all it's hidden so it may be removed in the future release of Android. We do it because Nordic Beacon may advertise as a beacon, as + * Beacon Config or DFU. Android does not clear cache then device is disconnected unless manually restarted Bluetooth Adapter. To do this in the code we need to call + * {@link BluetoothGatt#refresh()} method. However is may cause a lot of troubles. Ideally it should be called before connection attempt but we get 'gatt' object by calling connectGatt method so + * when the connection already has been started. Calling refresh() afterwards causes errors 129 and 133 to pop up from time to time when refresh takes place actually during service discovery. It + * seems to be asynchronous method. Therefore we are refreshing the device after disconnecting from it, before closing gatt. Sometimes you may obtain services from cache, not the actual values so + * reconnection is required. + * + * @param gatt + * the Bluetooth GATT object to refresh. + */ + private boolean refreshDeviceCache(final BluetoothGatt gatt) { + /* + * There is a refresh() method in BluetoothGatt class but for now it's hidden. We will call it using reflections. + */ + try { + final Method refresh = gatt.getClass().getMethod("refresh"); + if (refresh != null) { + return (Boolean) refresh.invoke(gatt); + } + } catch (final Exception e) { + loge("An exception occurred while refreshing device"); + } + return false; + } + + private void loge(final String message) { + if (BuildConfig.DEBUG) + Log.e(TAG, message); + } + + private void logw(final String message) { + if (BuildConfig.DEBUG) + Log.w(TAG, message); + } + + public static int decodeUInt16(final BluetoothGattCharacteristic characteristic, final int offset) { + final byte[] data = characteristic.getValue(); + return (unsignedByteToInt(data[offset]) << 8) | unsignedByteToInt(data[offset + 1]); + } + + public static UUID decodeBeaconUUID(final BluetoothGattCharacteristic characteristic) { + final byte[] data = characteristic.getValue(); + final long mostSigBits = (unsignedByteToLong(data[0]) << 56) + (unsignedByteToLong(data[1]) << 48) + (unsignedByteToLong(data[2]) << 40) + (unsignedByteToLong(data[3]) << 32) + + (unsignedByteToLong(data[4]) << 24) + (unsignedByteToLong(data[5]) << 16) + (unsignedByteToLong(data[6]) << 8) + unsignedByteToLong(data[7]); + final long leastSigBits = (unsignedByteToLong(data[8]) << 56) + (unsignedByteToLong(data[9]) << 48) + (unsignedByteToLong(data[10]) << 40) + (unsignedByteToLong(data[11]) << 32) + + (unsignedByteToLong(data[12]) << 24) + (unsignedByteToLong(data[13]) << 16) + (unsignedByteToLong(data[14]) << 8) + unsignedByteToLong(data[15]); + return new UUID(mostSigBits, leastSigBits); + } + + /** + * Convert a signed byte to an unsigned long. + */ + public static long unsignedByteToLong(byte b) { + return b & 0xFF; + } + + /** + * Convert a signed byte to an unsigned int. + */ + public static int unsignedByteToInt(int b) { + return b & 0xFF; + } + + /** + * BluetoothGatt request types. + */ + public enum RequestType { + // CHARACTERISTIC_NOTIFICATION, + READ_CHARACTERISTIC, + READ_DESCRIPTOR, + // READ_RSSI, + WRITE_CHARACTERISTIC, + WRITE_DESCRIPTOR + } + + public void add(RequestType type, BluetoothGattDescriptor descriptor) { + Request request = new Request(type, descriptor); + add(request); + } + + public void add(RequestType type, BluetoothGattCharacteristic characteristic) { + Request request = new Request(type, characteristic); + add(request); + } + + synchronized private void add(Request request) { + mQueue.add(request); + if (mQueue.size() == 1) { + mQueue.peek().start(mBluetoothGatt); + } + } + + /** + * Process the next request in the queue for a BluetoothGatt function (such as characteristic read). + */ + synchronized private void processNext() { + // The currently executing request is kept on the head of the queue until this is called. + if (mQueue.isEmpty()) + throw new RuntimeException("No active request in processNext()"); + mQueue.remove(); + if (!mQueue.isEmpty()) { + mQueue.peek().start(mBluetoothGatt); + } + } + + /** + * The object that holds a Gatt request while in the queue. + *
+ * This object holds the parameters for calling BluetoothGatt methods (see start()); + */ + public class Request { + final RequestType requestType; + BluetoothGattCharacteristic characteristic; + BluetoothGattDescriptor descriptor; + + public Request(RequestType requestType, BluetoothGattCharacteristic characteristic) { + this.requestType = requestType; + this.characteristic = characteristic; + } + + public Request(RequestType requestType, BluetoothGattDescriptor descriptor) { + this.requestType = requestType; + this.descriptor = descriptor; + } + + public void start(BluetoothGatt bluetoothGatt) { + switch (requestType) { + case READ_CHARACTERISTIC: + if (!bluetoothGatt.readCharacteristic(characteristic)) { + throw new IllegalArgumentException("Characteristic is not valid: " + characteristic.getUuid().toString()); + } + break; + case READ_DESCRIPTOR: + if (!bluetoothGatt.readDescriptor(descriptor)) { + throw new IllegalArgumentException("Descriptor is not valid"); + } + break; + case WRITE_CHARACTERISTIC: + if (!bluetoothGatt.writeCharacteristic(characteristic)) { + throw new IllegalArgumentException("Characteristic is not valid"); + } + break; + case WRITE_DESCRIPTOR: + if (!bluetoothGatt.writeDescriptor(descriptor)) { + throw new IllegalArgumentException("Characteristic is not valid"); + } + break; + } + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/beacon/BeaconsFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/beacon/BeaconsFragment.java new file mode 100644 index 0000000..b2ccefa --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/beacon/BeaconsFragment.java @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, getActivity() list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, getActivity() list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from getActivity() + * software without specific prior written permission. + * + * getActivity() SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF getActivity() SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.beacon; + +import android.Manifest; +import android.accounts.Account; +import android.accounts.AccountManager; +import android.app.Activity; +import android.app.PendingIntent; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothManager; +import android.content.Context; +import android.content.Intent; +import android.content.IntentSender; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v4.content.ContextCompat; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.common.AccountPicker; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.ResultCallback; +import com.google.android.gms.common.api.Status; +import com.google.android.gms.nearby.Nearby; +import com.google.android.gms.nearby.messages.Message; +import com.google.android.gms.nearby.messages.MessageFilter; +import com.google.android.gms.nearby.messages.MessageListener; +import com.google.android.gms.nearby.messages.NearbyMessagesStatusCodes; +import com.google.android.gms.nearby.messages.Strategy; +import com.google.android.gms.nearby.messages.SubscribeOptions; + +import java.nio.charset.Charset; +import java.util.ArrayList; + +import no.nordicsemi.android.nrfbeacon.nearby.AuthorizedServiceTask; +import no.nordicsemi.android.nrfbeacon.nearby.EddystoneBeaconsAdapter; +import no.nordicsemi.android.nrfbeacon.nearby.MainActivity; +import no.nordicsemi.android.nrfbeacon.nearby.NearbyBackgroundService; +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.common.BaseFragment; +import no.nordicsemi.android.nrfbeacon.nearby.common.PermissionRationaleDialogFragment; +import no.nordicsemi.android.nrfbeacon.nearby.settings.NearbySettingsActivity; +import no.nordicsemi.android.nrfbeacon.nearby.util.NetworkUtils; + +public class BeaconsFragment extends BaseFragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, PermissionRationaleDialogFragment.PermissionDialogListener { + + public static final String EXTRA_ADAPTER_POSITION = "no.nordicsemi.android.nrfbeacon.extra.adapter_position"; + public static final String TAG = "BEACON"; + private static final String ACCOUNT_NAME_PREF = "userAccount"; + private static final String SHARED_PREFS_NAME = "nrfNearbyInfo"; + private static final String NEARBY_MESSAGE = "no.nordicsemi.android.nrfbeacon.nearby.NEARBY_MESSAGE"; + public static final String NEARBY_DEVICE_DATA = "NEARBY_DEVICE_DATA"; + private static final String AUTH_PROXIMITY_API = "oauth2:https://www.googleapis.com/auth/userlocation.beacon.registry"; + + private final static int OPEN_ACTIVITY_REQ = 195; // random + static final int REQUEST_CODE_USER_ACCOUNT = 1002; + private static final int REQUEST_BACKGROUND_SCANNING = 252; + private static final int REQUEST_PERMISSION_REQ_CODE = 76; // any 8-bit number + private static final int REQUEST_ENABLE_BT = 1; + private static final int REQUEST_RESOLVE_ERROR = 261; //random + private static final int NOTIFICATION_ID = 1; + + private boolean mFragmentResumed; + public ArrayList mNearbyDevicesMessageList; + public ArrayList mTempList; + private int mSelectedTabPosition = 0; + //private Context mContext; + private EddystoneBeaconsAdapter mEddystoneBeaconsAdapter; + private ImageView mNearbyPermission; + private TextView mTextView; + private boolean mNearbyPermissionGranted = false; + private GoogleApiClient mGoogleApiClient; + private boolean mResolvingError; + private boolean mScanForNearbyInBackground = false; + private PendingIntent mPendingIntent; + private Intent mParentIntent; + private NotificationManagerCompat mNotificationManager; + private Context mContext; + + @Override + public void onActivityCreated(final Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @Override + public void onAttach(final Context context) { + super.onAttach(context); + mContext = context; + + } + + @Override + public void onDestroy() { + super.onDestroy(); + final MainActivity parent = (MainActivity) getActivity(); + parent.setBeaconsFragment(null); + } + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mSelectedTabPosition = getArguments().getInt("index"); + } + + if(savedInstanceState != null){ + mSelectedTabPosition = savedInstanceState.getInt(EXTRA_ADAPTER_POSITION); + } + + final MainActivity parent = (MainActivity) mContext; + parent.setBeaconsFragment(this); + } + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_beacons_list, container, false); + final ListView listView = (ListView) rootView.findViewById(R.id.listNearbyBeacons); + mNearbyDevicesMessageList = new ArrayList<>(); + mTempList = new ArrayList<>(); + mEddystoneBeaconsAdapter = new EddystoneBeaconsAdapter(getActivity(), mNearbyDevicesMessageList); + listView.setAdapter(mEddystoneBeaconsAdapter); + mTextView = (TextView) rootView.findViewById(R.id.tvNearbyPermission); + mNearbyPermission = (ImageView) rootView.findViewById(R.id.imageView); + + mParentIntent = new Intent(getActivity(), MainActivity.class); + mNotificationManager = NotificationManagerCompat.from(getActivity()); + mScanForNearbyInBackground = PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean(getString(R.string.nearby_settings_key), false); + mGoogleApiClient = new GoogleApiClient.Builder(getActivity()) + .addApi(Nearby.MESSAGES_API) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .build(); + + return rootView; + } + + @Override + public void onViewCreated(final View view, final Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + setHasOptionsMenu(true); + + mTextView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + getNearbyPermissionStatusAndSubscribe(); + mTextView.setClickable(false); + } + }); + getNearbyPermissionStatusAndSubscribe(); + } + + @Override + public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { + inflater.inflate(R.menu.menu_nearby_about, menu); + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + switch (item.getItemId()) { + case R.id.action_nearby_settings: + Intent nearby_settings = new Intent(getActivity(), NearbySettingsActivity.class); + startActivityForResult(nearby_settings, REQUEST_BACKGROUND_SCANNING); + return true; + } + return false; + } + + @Override + public void onStart() { + super.onStart(); + final String [] permissions = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.GET_ACCOUNTS}; + ensurePermission(permissions); + } + + @Override + public void onStop() { + super.onStop(); + if(!mScanForNearbyInBackground){ + unsubscribe(); + disconnectFromGoogleApiClient(); + } + + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + switch (requestCode) { + case REQUEST_BACKGROUND_SCANNING: + if (resultCode == Activity.RESULT_OK){ + boolean flag = Boolean.valueOf(data.getData().toString()); + Log.v(TAG, "background scanning enableD? " + flag); + updateNearbyScanning(); + } + break; + case REQUEST_ENABLE_BT: + if (resultCode == Activity.RESULT_OK) + connectToGoogleApiClient(); + else + onDestroy(); + break; + case REQUEST_CODE_USER_ACCOUNT: + if (resultCode == Activity.RESULT_OK) { + if (data != null) { + final String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); + setUserAccountName(accountName); + // The first time the account tries to contact the beacon service we'll pop a dialog + // asking the user to authorize our activity. Ensure that's handled cleanly here, rather + // than when the scan tries to fetch the status of every beacon within range. + Account [] accountsList = AccountManager.get(getActivity()).getAccounts(); + for (Account account : accountsList){ + if (accountName.equals(account.name)){ + if(NetworkUtils.checkNetworkConnectivity(getActivity())) + new AuthorizedServiceTask(getActivity(), account, AUTH_PROXIMITY_API).execute(); + else + Toast.makeText(getActivity(), getString(R.string.check_internet_connectivity), Toast.LENGTH_SHORT).show(); + break; + } + } + } + } + connectToGoogleApiClient(); + break; + case REQUEST_RESOLVE_ERROR: + if(resultCode == Activity.RESULT_OK) + getNearbyPermissionStatusAndSubscribe(); + else Toast.makeText(getActivity(), getString(R.string.rationale_permission_denied), Toast.LENGTH_SHORT).show(); + break; + + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + switch (requestCode) { + case REQUEST_PERMISSION_REQ_CODE: { + if(permissions.length > 0) + for(int i = 0; i < permissions.length; i++){ + if(Manifest.permission.ACCESS_COARSE_LOCATION.equals(permissions[i])){ + if(grantResults[i] == PackageManager.PERMISSION_GRANTED) + onPermissionGranted(Manifest.permission.ACCESS_COARSE_LOCATION); + else Toast.makeText(getActivity(), R.string.rationale_permission_denied, Toast.LENGTH_SHORT).show(); + } else if (Manifest.permission.GET_ACCOUNTS.equals(permissions[i])){ + if(grantResults[i] == PackageManager.PERMISSION_GRANTED) + onPermissionGranted(Manifest.permission.GET_ACCOUNTS); + else Toast.makeText(getActivity(), R.string.rationale_permission_denied, Toast.LENGTH_SHORT).show(); + } + } + break; + } + } + } + + @Override + protected void onPermissionGranted(final String permission) { + // Now, when the permission is granted, we may start scanning for beacons. + // We bind even if the FAB was clicked. + if(Manifest.permission.ACCESS_COARSE_LOCATION.equalsIgnoreCase(permission)){ + if(!isBleEnabled()){ + enableBle(); + } else connectToGoogleApiClient(); + } else if (Manifest.permission.GET_ACCOUNTS.equalsIgnoreCase(permission)){ + selectUserAccount(); + } + } + + public void updateAdapter(boolean clearAdapter){ + if(clearAdapter) + mEddystoneBeaconsAdapter.clear(); + mEddystoneBeaconsAdapter.notifyDataSetChanged(); + } + + + + public void updateNearbyPermissionStatus(boolean flag){ + mNearbyPermissionGranted = flag; + if(!mNearbyPermissionGranted) { + mNearbyPermission.setVisibility(View.GONE); + mTextView.setVisibility(View.VISIBLE); + mTextView.setClickable(true); + } + else { + mNearbyPermission.setVisibility(View.VISIBLE); + mTextView.setVisibility(View.GONE); + } + } + + public void prepareForScanning(){ + final String [] permissions = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.GET_ACCOUNTS}; + if (ensurePermission(permissions)) { + if (!isBleEnabled()) { + enableBle(); + connectToGoogleApiClient(); + } else connectToGoogleApiClient(); + } + } + + /** + * Checks whether the Bluetooth adapter is enabled. + */ + private boolean isBleEnabled() { + final BluetoothManager bm = (BluetoothManager) getActivity().getSystemService(Context.BLUETOOTH_SERVICE); + final BluetoothAdapter ba = bm.getAdapter(); + return ba != null && ba.isEnabled(); + } + + /** + * Tries to start Bluetooth adapter. + */ + private void enableBle() { + final Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + startActivityForResult(enableIntent, REQUEST_ENABLE_BT); + } + + private void selectUserAccount() { + String accountName = getUserAccountName(); + if (accountName == null) { + String[] accountTypes = new String[]{"com.google"}; + Intent intent = AccountPicker.newChooseAccountIntent( + null, null, accountTypes, false, null, null, null, null); + startActivityForResult(intent, REQUEST_CODE_USER_ACCOUNT); + } + } + + private String getUserAccountName(){ + SharedPreferences sharedPreferences = getActivity().getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE); + return sharedPreferences.getString(ACCOUNT_NAME_PREF, null); + } + + private void setUserAccountName(final String accountName){ + SharedPreferences sharedPreferences = getActivity().getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(ACCOUNT_NAME_PREF, accountName).apply(); + } + + private void connectToGoogleApiClient(){ + getNearbyPermissionStatusAndSubscribe(); + } + + @Override + public void onConnected(Bundle bundle) { + Log.v(TAG, "Connected "); + getNearbyPermissionStatusAndSubscribe(); + } + + @Override + public void onConnectionSuspended(int i) { + Log.v(TAG, "Connection susspended: " + i); + } + + @Override + public void onConnectionFailed(ConnectionResult connectionResult) { + Log.v(TAG, "Connection failed: " + connectionResult.getErrorMessage()); + } + + public void getNearbyPermissionStatusAndSubscribe(){ + if(mGoogleApiClient != null && !mGoogleApiClient.isConnected()){ + if(!mGoogleApiClient.isConnecting()){ + mGoogleApiClient.connect(); + } + } else { + Nearby.Messages.getPermissionStatus(mGoogleApiClient).setResultCallback(new ResultCallback() { + @Override + public void onResult(@NonNull Status status) { + if (status.isSuccess()) { + updateNearbyPermissionStatus(true); + + subscribe(); + } else if (status.getStatusCode() == NearbyMessagesStatusCodes.APP_NOT_OPTED_IN) { + try { + status.startResolutionForResult(getActivity(), REQUEST_RESOLVE_ERROR); + } catch (IntentSender.SendIntentException e) { + mResolvingError = false; + Log.i(TAG, "Failed to resolve error status.", e); + } + } + } + }); + } + } + + private void subscribe() { + Log.v(TAG, "Subscribing to beacons"); + MessageFilter filter = new MessageFilter.Builder() + .includeNamespacedType("nrf-nearby-1100", "string") + .build(); + if (!mGoogleApiClient.isConnected()) { + if (!mGoogleApiClient.isConnecting()) { + mGoogleApiClient.connect(); + } + } else if (!mScanForNearbyInBackground) { + SubscribeOptions options = new SubscribeOptions.Builder().setStrategy(Strategy.BLE_ONLY).setFilter(filter).build(); + Nearby.Messages.subscribe(mGoogleApiClient, mMessageListener, options).setResultCallback(new ResultCallback() { + @Override + public void onResult(@NonNull Status status) { + if (status.isSuccess()) { + Log.i(TAG, "Subscribed successfully for foreground scanning."); + } else { + Log.i(TAG, "Could not subscribe."); + handleUnsuccessfulNearbyResult(status); + } + } + }); + + } else { + SubscribeOptions options = new SubscribeOptions.Builder().setStrategy(Strategy.BLE_ONLY).build(); + Nearby.Messages.subscribe(mGoogleApiClient, getPendingIntent(), options) + .setResultCallback(new ResultCallback() { + @Override + public void onResult(Status status) { + if (status.isSuccess()) { + Log.i(TAG, "Subscribed successfully for background scanning."); + } else { + Log.i(TAG, "Could not subscribe."); + handleUnsuccessfulNearbyResult(status); + } + } + }); + } + } + + private void unsubscribe(){ + if(mGoogleApiClient.isConnected()) { + Nearby.Messages.unsubscribe(mGoogleApiClient, mMessageListener); + } + } + + private void disconnectFromGoogleApiClient(){ + + if(mGoogleApiClient.isConnected()) { + unsubscribe(); + mGoogleApiClient.disconnect(); + Log.v(TAG, "is connected? " + mGoogleApiClient.isConnected()); + } + mNearbyDevicesMessageList.clear(); + mNotificationManager.cancelAll(); + } + + private PendingIntent getPendingIntent() { + PendingIntent p = PendingIntent.getService(getActivity(), 0, + getBackgroundSubscribeServiceIntent(), PendingIntent.FLAG_UPDATE_CURRENT); + return p; + } + + public Intent getBackgroundSubscribeServiceIntent() { + return new Intent(getActivity(), NearbyBackgroundService.class); + } + + private void handleUnsuccessfulNearbyResult(Status status) { + Log.i(TAG, "Processing error, status = " + status); + if (mResolvingError) { + // Already attempting to resolve an error. + return; + } else if (status.hasResolution()) { + try { + mResolvingError = true; + status.startResolutionForResult(getActivity(), + REQUEST_RESOLVE_ERROR); + } catch (IntentSender.SendIntentException e) { + mResolvingError = false; + Log.i(TAG, "Failed to resolve error status.", e); + } + } else { + if (status.getStatusCode() == CommonStatusCodes.NETWORK_ERROR) { + Toast.makeText(getActivity(), + "No connectivity, cannot proceed. Fix in 'Settings' and try again.", + Toast.LENGTH_LONG).show(); + } else { + // To keep things simple, pop a toast for all other error messages. + Toast.makeText(getActivity(), "Unsuccessful: " + + status.getStatusMessage(), Toast.LENGTH_LONG).show(); + } + } + } + + private final MessageListener mMessageListener = new MessageListener() { + @Override + public void onFound(Message message) { + String nearbyMessage = new String(message.getContent(), Charset.forName("UTF-8")); + Log.i(TAG, "Found message via PendingIntent: " + nearbyMessage); + displayNotification(message); + } + + @Override + public void onLost(Message message) { + String nearbyMessage = new String(message.getContent(), Charset.forName("UTF-8")); + Log.i(TAG, "Lost message via PendingIntent: " + nearbyMessage); + updateNotification(message); + } + }; + + private void displayNotification(Message message){ + if (!checkIfnearbyDeviceAlreadyExists(new String(message.getContent(), Charset.forName("UTF-8")))) { + Log.i(TAG, "Adding message"); + mNearbyDevicesMessageList.add(message); + updateAdapter(false); + Log.i(TAG, "count after adding: " + mNearbyDevicesMessageList.size()); + createNotification(); + } + } + + private void createNotification() { + + if(mNearbyDevicesMessageList.size() == 0){ + mNotificationManager.cancelAll(); + return; + } + + final ArrayList nearbyMessageList = loadNearbyMessageListForNotification(); + mParentIntent.putExtra(NEARBY_DEVICE_DATA, nearbyMessageList); + mParentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mPendingIntent = PendingIntent.getActivities(getActivity(), OPEN_ACTIVITY_REQ, new Intent[]{mParentIntent}, PendingIntent.FLAG_UPDATE_CURRENT); + + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(getActivity()) + .setSmallIcon(R.drawable.ic_eddystone) + .setColor(ContextCompat.getColor(getActivity(), R.color.actionBarColor)) + .setContentTitle(getString(R.string.app_name)) + .setContentIntent(mPendingIntent); + + if(mNearbyDevicesMessageList.size() == 1) { + mBuilder.setContentText(new String(mNearbyDevicesMessageList.get(0).getContent(), Charset.forName("UTF-8"))); + } else { + NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); + inboxStyle.setBigContentTitle(getString(R.string.app_name)); + inboxStyle.setSummaryText(mNearbyDevicesMessageList.size() + " beacons found"); + mBuilder.setContentText(mNearbyDevicesMessageList.size() + " beacons found"); + for (int i = 0; i < mNearbyDevicesMessageList.size(); i++) { + inboxStyle.addLine(new String(mNearbyDevicesMessageList.get(i).getContent(), Charset.forName("UTF-8"))); + } + mBuilder.setStyle(inboxStyle); + } + mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); + } + + private void updateNotification(Message message){ + if (checkIfnearbyDeviceAlreadyExists(new String(message.getContent(), Charset.forName("UTF-8")))) { + Log.i(TAG, "removing message: " + message); + removeLostNearbyMessage(new String(message.getContent(), Charset.forName("UTF-8"))); + Log.i(TAG, "count after removing: " + mNearbyDevicesMessageList.size()); + createNotification(); + } + } + + private ArrayList loadNearbyMessageListForNotification(){ + final ArrayList nearbyMessageList = new ArrayList<>(); + for(int i = 0; i < mNearbyDevicesMessageList.size(); i++){ + nearbyMessageList.add(mNearbyDevicesMessageList.get(i)); + } + return nearbyMessageList; + } + + private boolean checkIfnearbyDeviceAlreadyExists(String nearbyDeviceMessage){ + String message; + for(int i = 0; i < mNearbyDevicesMessageList.size(); i++){ + message = new String(mNearbyDevicesMessageList.get(i).getContent(), Charset.forName("UTF-8")); + if(nearbyDeviceMessage.equals(message)){ + return true; + } + } + return false; + } + + private void removeLostNearbyMessage(String nearbyDeviceMessage){ + String message; + for(int i = 0; i < mNearbyDevicesMessageList.size(); i++){ + message = new String(mNearbyDevicesMessageList.get(i).getContent(), Charset.forName("UTF-8")); + if(nearbyDeviceMessage.equals(message)){ + mNearbyDevicesMessageList.remove(i); + updateAdapter(false); + break; + } + } + } + + public void updateNearbyScanning(){ + boolean flag = PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean(getString(R.string.nearby_settings_key), true); + if(mScanForNearbyInBackground != flag){ + mScanForNearbyInBackground = flag; + unsubscribe(); + disconnectFromGoogleApiClient(); + mNotificationManager.cancelAll(); + mNearbyDevicesMessageList.clear(); + updateAdapter(true); + connectToGoogleApiClient(); + } else if(!mScanForNearbyInBackground && !flag){ + mNotificationManager.cancelAll(); + mNearbyDevicesMessageList.clear(); + updateAdapter(true); + connectToGoogleApiClient(); + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/BaseFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/BaseFragment.java new file mode 100644 index 0000000..1460480 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/BaseFragment.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.nrfbeacon.nearby.common; + +import android.Manifest; +import android.content.pm.PackageManager; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.content.ContextCompat; + +import java.util.ArrayList; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + + +public abstract class BaseFragment extends Fragment implements PermissionRationaleDialogFragment.PermissionDialogListener { + private static final int REQUEST_PERMISSION_REQ_CODE = 76; // any 8-bit number + private ArrayList mPermissionList; + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @Override + public void onRequestPermission() { + if(mPermissionList != null && mPermissionList.size() > 0) + requestPermissions(mPermissionList.toArray(new String[mPermissionList.size()]), REQUEST_PERMISSION_REQ_CODE); + else checkForUngrantedPermissions(new String [] {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.GET_ACCOUNTS}); + } + + /** + * Method called when user has granted the coarse location permission to the application. + */ + protected abstract void onPermissionGranted(final String permission); + + /** + * Ensures the required permission has been granted by the user. On Android pre-6.0 it always returns true. + * In case the permission has not been granted this method may also show a dialog with rationale. + * @return true if the permission required for BLE scanning is granted + */ + + protected boolean ensurePermission(final String [] permissions) { + // Since Android 6.0 we need to obtain either Manifest.permission.ACCESS_COARSE_LOCATION or Manifest.permission.ACCESS_FINE_LOCATION to be able to scan for + // Bluetooth LE devices. This is related to beacons as proximity devices. + // On API older than Marshmallow the following code does nothing. + mPermissionList = new ArrayList<>(); + if(permissions.length > 0 ) { + for (int i = 0; i < permissions.length; i++) { + if (ContextCompat.checkSelfPermission(getContext(), permissions[i]) != PackageManager.PERMISSION_GRANTED) { + // When user pressed Deny and still wants to use this functionality, show the rationale + if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), permissions[i])) { + if(permissions[i] == Manifest.permission.ACCESS_COARSE_LOCATION) { + final PermissionRationaleDialogFragment dialog = PermissionRationaleDialogFragment.getInstance(getString(R.string.rationale_message_location)); + dialog.show(getChildFragmentManager(), null); + return false; + } else if(permissions[i] == Manifest.permission.GET_ACCOUNTS) { + final PermissionRationaleDialogFragment dialog = PermissionRationaleDialogFragment.getInstance(getString(R.string.rationale_message_contacts)); + dialog.show(getChildFragmentManager(), null); + return false; + } + } else { + mPermissionList.add(permissions[i]); + } + } else { + onPermissionGranted(permissions[i]); + } + } + + if(mPermissionList.size() > 0) { + onRequestPermission(); + return true; + } + } + return true; + } + + protected void checkForUngrantedPermissions(final String [] permissions) { + mPermissionList = new ArrayList<>(); + if(permissions.length > 0 ) { + for (int i = 0; i < permissions.length; i++) { + if (ContextCompat.checkSelfPermission(getContext(), permissions[i]) != PackageManager.PERMISSION_GRANTED) { + // When user pressed Deny and still wants to use this functionality, show the rationale + mPermissionList.add(permissions[i]); + } + } + + if(mPermissionList.size() > 0) { + onRequestPermission(); + } + } + } + + + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/BoardHelpFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/BoardHelpFragment.java new file mode 100644 index 0000000..c065186 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/BoardHelpFragment.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.common; + +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +public class BoardHelpFragment extends DialogFragment { + public static final int MODE_DFU = 1; + public static final int MODE_UPDATE = 2; + + private static final String MODE = "mode"; + + public static BoardHelpFragment getInstance(final int mode) { + final BoardHelpFragment fragment = new BoardHelpFragment(); + + final Bundle args = new Bundle(); + args.putInt(MODE, mode); + fragment.setArguments(args); + + return fragment; + } + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { + final Bundle bundle = getArguments(); + final int mode = bundle.getInt(MODE); + + getDialog().setTitle(R.string.update_about_title); + final TextView aboutView = (TextView) inflater.inflate(R.layout.fragment_dialog_help, container, false); + switch (mode) { + case MODE_DFU: + aboutView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.beacon_sw1, 0, 0, 0); + aboutView.setText(R.string.update_about_message_dfu); + break; + case MODE_UPDATE: + default: + aboutView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.beacon_sw2, 0, 0, 0); + aboutView.setText(R.string.update_about_message_update); + break; + } + return aboutView; + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/PermissionRationaleDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/PermissionRationaleDialogFragment.java new file mode 100644 index 0000000..26f3307 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/common/PermissionRationaleDialogFragment.java @@ -0,0 +1,81 @@ +/************************************************************************************************************************************************* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + *

+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + *

+ * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + *

+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + *

+ * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + *

+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ************************************************************************************************************************************************/ + +package no.nordicsemi.android.nrfbeacon.nearby.common; + +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.Fragment; +import android.support.v7.app.AlertDialog; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + + +public class PermissionRationaleDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { + + private static final String RATIONALE_MESSAGE = "RATIONALE_MESSAGE"; + private String mRationaleMessage; + + public static PermissionRationaleDialogFragment getInstance(final String message){ + PermissionRationaleDialogFragment fragment = new PermissionRationaleDialogFragment(); + Bundle bundle = new Bundle(); + bundle.putString(RATIONALE_MESSAGE, message); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null) + mRationaleMessage = getArguments().getString(RATIONALE_MESSAGE); + } + + public interface PermissionDialogListener { + void onRequestPermission(); + } + + @Override + public void onAttach(Context activity) { + super.onAttach(activity); + } + + @NonNull + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + return new AlertDialog.Builder(getContext()).setTitle(R.string.rationale_title) + .setMessage(mRationaleMessage) + .setPositiveButton(R.string.rationale_request, this) + .setNegativeButton(R.string.rationale_cancel, null).create(); + } + + @Override + public void onClick(final DialogInterface dialogInterface, final int i) { + ((PermissionDialogListener)getParentFragment()).onRequestPermission(); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/DeviceListAdapter.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/DeviceListAdapter.java new file mode 100644 index 0000000..d660967 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/DeviceListAdapter.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.scanner; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.support.v18.scanner.ScanResult; + +/** + * DeviceListAdapter class is list adapter for showing scanned Devices name, address and RSSI image based on RSSI values. + */ +public class DeviceListAdapter extends BaseAdapter { + private static final int TYPE_TITLE = 0; + private static final int TYPE_ITEM = 1; + private static final int TYPE_EMPTY = 2; + + private final List mDevices = new ArrayList<>(); + + /** + * If such device exists on the bonded device list, this method does nothing. If not then the device is updated (rssi value) or added. + * + * @param results scan results + */ + public void update(final List results) { + for (final ScanResult result : results) { + final ExtendedBluetoothDevice device = findDevice(result); + if (device == null) { + mDevices.add(new ExtendedBluetoothDevice(result)); + } else { + device.name = result.getScanRecord() != null ? result.getScanRecord().getDeviceName() : null; + device.rssi = result.getRssi(); + } + } + notifyDataSetChanged(); + } + + private ExtendedBluetoothDevice findDevice(final ScanResult result) { + for (final ExtendedBluetoothDevice device : mDevices) + if (device.matches(result)) + return device; + return null; + } + + public void clearDevices() { + if (mDevices != null) { + mDevices.clear(); + notifyDataSetChanged(); + } + } + + @Override + public int getCount() { + return mDevices.isEmpty() ? 2 : mDevices.size() + 1; // 1 for title, 1 for empty text + } + + @Override + public Object getItem(int position) { + if (position == 0) + return R.string.scanner_subtitle__not_bonded; + else + return mDevices.get(position - 1); + } + + @Override + public int getViewTypeCount() { + return 3; + } + + @Override + public boolean areAllItemsEnabled() { + return false; + } + + @Override + public boolean isEnabled(int position) { + return getItemViewType(position) == TYPE_ITEM; + } + + @Override + public int getItemViewType(int position) { + if (position == 0) + return TYPE_TITLE; + + if (position == getCount() - 1 && mDevices.isEmpty()) + return TYPE_EMPTY; + + return TYPE_ITEM; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View oldView, ViewGroup parent) { + final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + final int type = getItemViewType(position); + + View view = oldView; + switch (type) { + case TYPE_EMPTY: + if (view == null) { + view = inflater.inflate(R.layout.device_list_empty, parent, false); + } + break; + case TYPE_TITLE: + if (view == null) { + view = inflater.inflate(R.layout.device_list_title, parent, false); + } + final TextView title = (TextView) view; + title.setText((Integer) getItem(position)); + break; + default: + if (view == null) { + view = inflater.inflate(R.layout.device_list_row, parent, false); + final ViewHolder holder = new ViewHolder(); + holder.name = (TextView) view.findViewById(R.id.name); + holder.address = (TextView) view.findViewById(R.id.address); + holder.rssi = (ImageView) view.findViewById(R.id.rssi); + view.setTag(holder); + } + + final ExtendedBluetoothDevice device = (ExtendedBluetoothDevice) getItem(position); + final ViewHolder holder = (ViewHolder) view.getTag(); + final String name = device.name; + holder.name.setText(name != null ? name : parent.getContext().getString(R.string.not_available)); + holder.address.setText(device.device.getAddress()); + if (device.rssi != ScannerFragment.NO_RSSI) { + final int rssiPercent = (int) (100.0f * (127.0f + device.rssi) / (127.0f + 20.0f)); + holder.rssi.setImageLevel(rssiPercent); + holder.rssi.setVisibility(View.VISIBLE); + } else { + holder.rssi.setVisibility(View.GONE); + } + break; + } + + return view; + } + + private class ViewHolder { + private TextView name; + private TextView address; + private ImageView rssi; + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ExtendedBluetoothDevice.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ExtendedBluetoothDevice.java new file mode 100644 index 0000000..dd7445e --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ExtendedBluetoothDevice.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.scanner; + +import android.bluetooth.BluetoothDevice; + +import no.nordicsemi.android.support.v18.scanner.ScanResult; + +public class ExtendedBluetoothDevice { + public BluetoothDevice device; + public int rssi; + public String name; + + public ExtendedBluetoothDevice(final ScanResult scanResult) { + this.device = scanResult.getDevice(); + this.name = scanResult.getScanRecord() != null ? scanResult.getScanRecord().getDeviceName() : null; + this.rssi = scanResult.getRssi(); + } + + public boolean matches(final ScanResult scanResult) { + return device.getAddress().equals(scanResult.getDevice().getAddress()); + } + + @Override + public boolean equals(Object o) { + if (o instanceof ExtendedBluetoothDevice) { + final ExtendedBluetoothDevice that = (ExtendedBluetoothDevice) o; + return device.getAddress().equals(that.device.getAddress()); + } + return super.equals(o); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ScannerFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ScannerFragment.java new file mode 100644 index 0000000..c38798b --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ScannerFragment.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.scanner; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat; +import no.nordicsemi.android.support.v18.scanner.ScanCallback; +import no.nordicsemi.android.support.v18.scanner.ScanFilter; +import no.nordicsemi.android.support.v18.scanner.ScanResult; +import no.nordicsemi.android.support.v18.scanner.ScanSettings; + +import android.Manifest; +import android.app.Dialog; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.ParcelUuid; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.DialogFragment; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.ListView; +import android.widget.Toast; + +/** + * ScannerFragment class scan required BLE devices and shows them in a list. This class scans and filter devices with given BLE Service UUID which may be null. It contains a + * list and a button to scan/cancel. The scanning will continue for 5 seconds and then stop. + */ +public class ScannerFragment extends DialogFragment { + private final static String TAG = "ScannerFragment"; + + private final static String PARAM_UUID = "param_uuid"; + private final static long SCAN_DURATION = 8000; + /* package */static final int NO_RSSI = -1000; + + private final static int REQUEST_PERMISSION_REQ_CODE = 76; // any 8-bit number + + private DeviceListAdapter mAdapter; + private Handler mHandler = new Handler(); + private Button mScanButton; + private View mPermissionRationale; + + private ParcelUuid mUuid; + private boolean mIsScanning = false; + + /** + * Static implementation of fragment so that it keeps data when phone orientation is changed For standard BLE Service UUID, we can filter devices using normal android provided command + * startScanLe() with required BLE Service UUID For custom BLE Service UUID, we will use class ScannerServiceParser to filter out required device + */ + public static ScannerFragment getInstance(final UUID uuid) { + final ScannerFragment fragment = new ScannerFragment(); + + final Bundle args = new Bundle(); + if (uuid != null) + args.putParcelable(PARAM_UUID, new ParcelUuid(uuid)); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + final Bundle args = getArguments(); + mUuid = args.getParcelable(PARAM_UUID); + } + + @Override + public void onDestroyView() { + stopScan(); + super.onDestroyView(); + } + + /** + * When dialog is created then set AlertDialog with list and button views + */ + @NonNull + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); + final View dialogView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_scanner_device_selection, null); + final ListView listview = (ListView) dialogView.findViewById(android.R.id.list); + + listview.setEmptyView(dialogView.findViewById(android.R.id.empty)); + listview.setAdapter(mAdapter = new DeviceListAdapter()); + + builder.setTitle(R.string.scanner_title); + final AlertDialog dialog = builder.setView(dialogView).create(); + listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { + stopScan(); + dismiss(); + + final ScannerFragmentListener listener = (ScannerFragmentListener) getParentFragment(); + final ExtendedBluetoothDevice device = (ExtendedBluetoothDevice) mAdapter.getItem(position); + listener.onDeviceSelected(device.device, device.name != null ? device.name : getString(R.string.not_available)); + } + }); + + mPermissionRationale = dialogView.findViewById(R.id.permission_rationale); // this is not null only on API23+ + + mScanButton = (Button) dialogView.findViewById(R.id.action_cancel); + mScanButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (v.getId() == R.id.action_cancel) { + if (mIsScanning) { + dialog.cancel(); + } else { + startScan(); + } + } + } + }); + + if (savedInstanceState == null) + startScan(); + return dialog; + } + + @Override + public void onRequestPermissionsResult(final int requestCode, final @NonNull String[] permissions, final @NonNull int[] grantResults) { + switch (requestCode) { + case REQUEST_PERMISSION_REQ_CODE: { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // We have been granted the Manifest.permission.ACCESS_COARSE_LOCATION permission. Now we may proceed with scanning. + startScan(); + } else { + mPermissionRationale.setVisibility(View.VISIBLE); + Toast.makeText(getActivity(), R.string.rationale_permission_denied, Toast.LENGTH_SHORT).show(); + } + break; + } + } + } + + /** + * Scan for 5 seconds and then stop scanning when a BluetoothLE device is found then mLEScanCallback is activated This will perform regular scan for custom BLE Service UUID and then filter out + * using class ScannerServiceParser + */ + private void startScan() { + // Since Android 6.0 we need to obtain either Manifest.permission.ACCESS_COARSE_LOCATION or Manifest.permission.ACCESS_FINE_LOCATION to be able to scan for + // Bluetooth LE devices. This is related to beacons as proximity devices. + // On API older than Marshmallow the following code does nothing. + if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + // When user pressed Deny and still wants to use this functionality, show the rationale + if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) && mPermissionRationale.getVisibility() == View.GONE) { + mPermissionRationale.setVisibility(View.VISIBLE); + return; + } + + requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_PERMISSION_REQ_CODE); + return; + } + + // Hide the rationale message, we don't need it anymore. + if (mPermissionRationale != null) + mPermissionRationale.setVisibility(View.GONE); + + mAdapter.clearDevices(); + mScanButton.setText(R.string.scanner_action_cancel); + + final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner(); + final ScanSettings settings = new ScanSettings.Builder() + .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).setReportDelay(1000).setUseHardwareBatchingIfSupported(false).setUseHardwareFilteringIfSupported(false).build(); + final List filters = new ArrayList<>(); + filters.add(new ScanFilter.Builder().setServiceUuid(mUuid).build()); + scanner.startScan(filters, settings, scanCallback); + + mIsScanning = true; + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (mIsScanning) { + stopScan(); + } + } + }, SCAN_DURATION); + } + + /** + * Stop scan if user tap Cancel button + */ + private void stopScan() { + if (mIsScanning) { + mScanButton.setText(R.string.scanner_action_scan); + + final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner(); + scanner.stopScan(scanCallback); + + mIsScanning = false; + } + } + + private ScanCallback scanCallback = new ScanCallback() { + @Override + public void onScanResult(final int callbackType, final ScanResult result) { + // do nothing + } + + @Override + public void onBatchScanResults(final List results) { + mAdapter.update(results); + } + + @Override + public void onScanFailed(final int errorCode) { + // should never be called + } + }; +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ScannerFragmentListener.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ScannerFragmentListener.java new file mode 100644 index 0000000..e0290bf --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/scanner/ScannerFragmentListener.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.scanner; + +import android.bluetooth.BluetoothDevice; + +public interface ScannerFragmentListener { + + /** + * Called when user has selected the device. + * + * @param device the selected device. May not be null. + * @param name the device name. + */ + public void onDeviceSelected(final BluetoothDevice device, final String name); +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/settings/NearbySettingsActivity.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/settings/NearbySettingsActivity.java new file mode 100644 index 0000000..95a7e84 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/settings/NearbySettingsActivity.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.settings; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.MenuItem; + +import no.nordicsemi.android.nrfbeacon.nearby.MainActivity; +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.beacon.BeaconsFragment; + +public class NearbySettingsActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener{ + + private boolean mBackgroundScanningEnabled; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_nearby_settings); + final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + getSupportActionBar().setTitle(getString(R.string.settings_title)); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + mBackgroundScanningEnabled = PreferenceManager.getDefaultSharedPreferences(NearbySettingsActivity.this).getBoolean(getString(R.string.nearby_settings_key), false); + if(savedInstanceState == null) + getFragmentManager().beginTransaction().replace(R.id.content, new NearbySettingsFragment()).commit(); + + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()){ + case android.R.id.home: + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onBackPressed() { + boolean flag = PreferenceManager.getDefaultSharedPreferences(NearbySettingsActivity.this).getBoolean(getString(R.string.nearby_settings_key), false); + if(mBackgroundScanningEnabled != flag) { + mBackgroundScanningEnabled = flag; + Intent result = new Intent(); + result.setData(Uri.parse(String.valueOf(mBackgroundScanningEnabled))); + setResult(RESULT_OK, result); + } + super.onBackPressed(); + + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/settings/NearbySettingsFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/settings/NearbySettingsFragment.java new file mode 100644 index 0000000..277ebe1 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/settings/NearbySettingsFragment.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.settings; + +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceFragment; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +public class NearbySettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { + + private boolean mBackgroundScanningEnabled; + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.settings_nearby); + } + @Override + public void onResume() { + super.onResume(); + + // attach the preference change listener. It will update the summary below interval preference + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onPause() { + super.onPause(); + // unregister listener + getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) { + final SharedPreferences preferences = getPreferenceManager().getSharedPreferences(); + mBackgroundScanningEnabled = preferences.getBoolean(key, false); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/AdvertisingIntervalDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/AdvertisingIntervalDialogFragment.java new file mode 100644 index 0000000..e9a99e5 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/AdvertisingIntervalDialogFragment.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +/** + * Created by rora on 06.04.2016. + */ +public class AdvertisingIntervalDialogFragment extends DialogFragment { + private static final String ADV_INTERVAL = "ADV_INTERVAL"; + private static final String TAG = "BEACON"; + + private String mCurrentAdvInterval; + private EditText advInterval; + + public interface OnAdvertisingIntervalListener { + void configureAdvertisingInterval(final byte [] advertisingInterval); + } + + public static AdvertisingIntervalDialogFragment newInstance(final String currentAdvInterval){ + AdvertisingIntervalDialogFragment fragment = new AdvertisingIntervalDialogFragment(); + final Bundle args = new Bundle(); + args.putString(ADV_INTERVAL, currentAdvInterval); + fragment.setArguments(args); + return fragment; + } + + public AdvertisingIntervalDialogFragment(){} + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mCurrentAdvInterval = getArguments().getString(ADV_INTERVAL); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.title_config_radio_tx_power)); + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_dialog_advertising_interval, null); + final TextView textView = (TextView) view.findViewById(R.id.current_adv_interval); + textView.setText(mCurrentAdvInterval); + advInterval = (EditText) view.findViewById(R.id.advertising_interval); + final AlertDialog alertDialog = alertDialogBuilder.setView(view).setPositiveButton(getString(R.string.configure), null).setNegativeButton(getString(R.string.cancel), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(validateInput()){ + final byte [] advertisingInterval = getValueFromView(); + ((OnAdvertisingIntervalListener)getParentFragment()).configureAdvertisingInterval(advertisingInterval); + dismiss(); + } + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + return alertDialog; + } + + private boolean validateInput() { + final String advertisingInterval = advInterval.getText().toString().trim(); + + if(advertisingInterval.isEmpty()){ + advInterval.setError("Enter advertising interval value"); + return false; + } else { + boolean valid; + try { + int i = Integer.parseInt(advertisingInterval); + valid = (i & 0xFFFF0000) == 0 || (i & 0xFFFF0000) == 0xFFFF0000; + } catch (NumberFormatException e) { + valid = false; + } + if (!valid) { + advInterval.setError("Value does not match UINT16"); + return false; + } + } + + return true; + } + + private byte[] getValueFromView() { + final byte [] data = new byte[2]; + final int value = Integer.parseInt(advInterval.getText().toString().trim()); + ParserUtils.setValue(data, 0, value, ParserUtils.FORMAT_UINT16_BIG_INDIAN); + return data; + } + + @Override + public void onDetach() { + super.onDetach(); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/AllSlotInfoDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/AllSlotInfoDialogFragment.java new file mode 100644 index 0000000..7c73f74 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/AllSlotInfoDialogFragment.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.bluetooth.BluetoothGattCharacteristic; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutCompat; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import java.util.ArrayList; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +/** + * Created by rora on 07.03.2016. + */ +public class AllSlotInfoDialogFragment extends DialogFragment { + + private static final String ALL_SLOT_INFO = "ALL_SLOT_INFO"; + private ArrayList mAllSlotInfo; + + public static AllSlotInfoDialogFragment newInstance(final ArrayList allSlotInfo){ + AllSlotInfoDialogFragment fragment = new AllSlotInfoDialogFragment(); + final Bundle args = new Bundle(); + args.putStringArrayList(ALL_SLOT_INFO, allSlotInfo); + fragment.setArguments(args); + return fragment; + } + + public AllSlotInfoDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mAllSlotInfo = getArguments().getStringArrayList(ALL_SLOT_INFO); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle("All Slot Information"); + alertDialogBuilder.setMessage("Following slots have been configured in the beacon"); + + final View alertDialogView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_all_slot_info, null); + final LinearLayout slotTitleContainer = (LinearLayout) alertDialogView.findViewById(R.id.slot_title_container); + final LinearLayout slotInfoContainer = (LinearLayout) alertDialogView.findViewById(R.id.slot_info_container); + LinearLayout.LayoutParams lParams = new LinearLayout.LayoutParams(LinearLayoutCompat.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); + for(int i = 0; i < mAllSlotInfo.size(); i++) { + TextView slotTitle = new TextView(getActivity()); + slotTitle.setLayoutParams(lParams); + slotTitle.setText("Slot " + i); + slotTitleContainer.addView(slotTitle); + + TextView slotInfo = new TextView(getActivity()); + slotInfo.setLayoutParams(lParams); + slotInfo.setText(mAllSlotInfo.get(i)); + slotInfoContainer.addView(slotInfo); + + if(i > 0){ + lParams.setMargins(0, 10, 0, 0); + } + + } + + final AlertDialog alertDialog = alertDialogBuilder.setView(alertDialogView).setPositiveButton(getString(R.string.ok), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + + + return alertDialog; + } + + @Override + public void onDetach() { + super.onDetach(); + } + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/BroadcastCapabilitesDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/BroadcastCapabilitesDialogFragment.java new file mode 100644 index 0000000..f23cb78 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/BroadcastCapabilitesDialogFragment.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.bluetooth.BluetoothGattCharacteristic; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +/** + * Created by rora on 07.03.2016. + */ +public class BroadcastCapabilitesDialogFragment extends DialogFragment { + + private static final String PATTERN_TX_POWER = "[0-9a-fA-F]{32}"; + private static final String BROADCAST_CAPABILITIES = "BROADCAST_CAPABILITIES"; + private static final String TAG = "BEACON"; + private static final int IS_VARIABLE_ADV_SUPPORTED = 0x01; + private static final int IS_VARIABLE_TX_POWER_SUPPORTED = 0x02; + private static final int TYPE_UID = 0x0001; + private static final int TYPE_URL = 0x0002; + private static final int TYPE_TLM = 0x0004; + private static final int TYPE_EID = 0x0008; + private TextView mVersion; + + private byte [] mBroadcastCapabilities; + + public static BroadcastCapabilitesDialogFragment newInstance(byte [] broadcastCapabilities){ + BroadcastCapabilitesDialogFragment fragment = new BroadcastCapabilitesDialogFragment(); + final Bundle args = new Bundle(); + args.putByteArray(BROADCAST_CAPABILITIES, broadcastCapabilities); + fragment.setArguments(args); + return fragment; + } + + public BroadcastCapabilitesDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mBroadcastCapabilities = getArguments().getByteArray(BROADCAST_CAPABILITIES); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle("Broadcast Capabilities"); + + final View alertDialogView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_broadcast_capabilities, null); + mVersion = (TextView) alertDialogView.findViewById(R.id.version_value); + final TextView totalSlots = (TextView) alertDialogView.findViewById(R.id.total_slots); + final TextView totalEidSlots = (TextView) alertDialogView.findViewById(R.id.total_eid_slots); + final TextView variableAdvertisingSupported = (TextView) alertDialogView.findViewById(R.id.variable_adv_supported); + final TextView variableTxPowerSupported = (TextView) alertDialogView.findViewById(R.id.variable_tx_power_supported); + final TextView supportedFrameTypes = (TextView) alertDialogView.findViewById(R.id.frame_types); + final TextView supportedTxPower = (TextView) alertDialogView.findViewById(R.id.supported_tx_power); + + final AlertDialog alertDialog = alertDialogBuilder.setView(alertDialogView).setPositiveButton(getString(R.string.ok), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + mVersion.setText(String.valueOf(ParserUtils.getIntValue(mBroadcastCapabilities, 0, BluetoothGattCharacteristic.FORMAT_UINT8))); + totalSlots.setText(String.valueOf(ParserUtils.getIntValue(mBroadcastCapabilities, 1, BluetoothGattCharacteristic.FORMAT_UINT8))); + totalEidSlots.setText(String.valueOf(ParserUtils.getIntValue(mBroadcastCapabilities, 2, BluetoothGattCharacteristic.FORMAT_UINT8))); + + + final int capabilities = ParserUtils.getIntValue(mBroadcastCapabilities, 3, BluetoothGattCharacteristic.FORMAT_UINT8); + final boolean variableAdvertising = (capabilities & IS_VARIABLE_ADV_SUPPORTED) > 0; + if(variableAdvertising) + variableAdvertisingSupported.setText("YES"); + else + variableAdvertisingSupported.setText("NO"); + + final boolean variableTxPower = (capabilities & IS_VARIABLE_TX_POWER_SUPPORTED) > 0; + if(variableTxPower) + variableTxPowerSupported.setText("YES"); + else + variableTxPowerSupported.setText("NO"); + + final int supportedEddystoneFrameTypes = ParserUtils.getIntValue(mBroadcastCapabilities, 4, ParserUtils.FORMAT_UINT16_BIG_INDIAN); + + final boolean typeUid = (supportedEddystoneFrameTypes & TYPE_UID) > 0; + final boolean typeUrl = (supportedEddystoneFrameTypes & TYPE_URL) > 0; + final boolean typeTlm = (supportedEddystoneFrameTypes & TYPE_TLM) > 0; + final boolean typeEid = (supportedEddystoneFrameTypes & TYPE_EID) > 0; + + StringBuilder builder = new StringBuilder(); + + if(typeUid) + builder.append("UID, "); + if(typeUrl) + builder.append("URL, "); + if(typeTlm) + builder.append("TLM, "); + if(typeEid) + builder.append("EID"); + + if(builder.toString().endsWith(",")) { + builder.setLength(builder.length() - 2); + } + + supportedFrameTypes.setText(builder.toString()); + + builder = new StringBuilder(); + for(int i = 6; i < mBroadcastCapabilities.length; i++){ + builder.append(" " + ParserUtils.getIntValue(mBroadcastCapabilities, i , BluetoothGattCharacteristic.FORMAT_SINT8)).append(","); + } + + if(builder.toString().endsWith(",")){ + builder.setLength(builder.length()-1); + } + builder.append(" dBm"); + supportedTxPower.setText(builder.toString()); + + return alertDialog; + } + + @Override + public void onDetach() { + super.onDetach(); + } + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ClearSlotDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ClearSlotDialogFragment.java new file mode 100644 index 0000000..bd416bf --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ClearSlotDialogFragment.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.View; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +/** + * Created by rora on 16.03.2016. + */ +public class ClearSlotDialogFragment extends DialogFragment{ + + private static final String MESSAGE = "MESSAGE"; + private String mMessage; + + public interface OnClearSlotListener { + void clearSlot(); + } + + public static ClearSlotDialogFragment newInstance(){ + ClearSlotDialogFragment fragment = new ClearSlotDialogFragment(); + return fragment; + } + + public ClearSlotDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.action_clear_slot)); + alertDialogBuilder.setMessage(getString(R.string.action_clear_slot_message)); + final AlertDialog alertDialog = alertDialogBuilder.setPositiveButton(getString(R.string.yes), null).setNegativeButton(getString(R.string.no), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ((OnClearSlotListener) getParentFragment()).clearSlot(); + dismiss(); + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + return alertDialog; + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/CreateAttachmentDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/CreateAttachmentDialogFragment.java new file mode 100644 index 0000000..7327a9f --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/CreateAttachmentDialogFragment.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +import java.nio.charset.Charset; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +/** + * Created by rora on 07.03.2016. + */ +public class CreateAttachmentDialogFragment extends DialogFragment { + + private static final String TAG = "BEACON"; + private static final String BEACON_NAME = "BEACON_NAME"; + private String mBeaconName; + private EditText mAttachment; + + public interface OnAttachmentCreatedListener { + void createAttachmentForBeacon(final String mBeaconName, final byte[] attachmentData); + } + + public static CreateAttachmentDialogFragment newInstance(final String beaconName){ + CreateAttachmentDialogFragment fragment = new CreateAttachmentDialogFragment(); + Bundle args = new Bundle(); + args.putString(BEACON_NAME, beaconName); + fragment.setArguments(args); + return fragment; + } + + public CreateAttachmentDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null) + mBeaconName = getArguments().getString(BEACON_NAME); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.create_attachment_title)); + alertDialogBuilder.setMessage(getString(R.string.create_attachment_message)); + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_create_beacon_attachment, null); + mAttachment = (EditText) view.findViewById(R.id.attachment); + + final AlertDialog alertDialog = alertDialogBuilder.setView(view).setPositiveButton(getString(R.string.create), null).setNegativeButton(getString(R.string.cancel), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(validateInput()) { + final byte [] attachmentData = mAttachment.getText().toString().trim().getBytes(Charset.forName("UTF-8")); + ((OnAttachmentCreatedListener)getParentFragment()).createAttachmentForBeacon(mBeaconName, attachmentData); + dismiss(); + } + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + return alertDialog; + } + + @Override + public void onDetach() { + super.onDetach(); + } + + private boolean validateInput(){ + final String attachment = mAttachment.getText().toString().trim(); + if(attachment.isEmpty()){ + mAttachment.setError(getString(R.string.enter_attachment_data)); + return false; + } + return true; + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/EcdhKeyInfoDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/EcdhKeyInfoDialogFragment.java new file mode 100644 index 0000000..c6f5a81 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/EcdhKeyInfoDialogFragment.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +/** + * Created by rora on 16.03.2016. + */ +public class EcdhKeyInfoDialogFragment extends DialogFragment { + + + private static final String BEACON_ECDH_PUBLIC_KEY = "BEACON_ECDH_PUBLIC_KEY"; + private static final String ENCRYPTED_IDENTITY_KEY = "ENCRYPTED_IDENTITY_KEY"; + private static final String DECRYPTED_IDENTITY_KEY = "DECRYPTED_IDENTITY_KEY"; + private static final String FRAME_TYPE = "FRAME_TYPE"; + private static final String ACTIVE_SLOT = "ACTIVE_SLOT"; + + private static final int TYPE_UID = 0x00; + private static final int TYPE_URL = 0x10; + private static final int TYPE_TLM = 0x20; + private static final int TYPE_EID = 0x30; + private int mFrameType; + private int mActiveSlot; + private String mEncryptedIdentityKey; + private String mDecryptedIdentityKey; + private String mPublicEcdhKey; + + public static EcdhKeyInfoDialogFragment newInstance(final int activeSlot, final int frameType, final String beaconEcdhKeyPublicKey, final String encryptedIdentityKey, final String decryptedIdentityKey){ + EcdhKeyInfoDialogFragment fragment = new EcdhKeyInfoDialogFragment(); + Bundle args = new Bundle(); + args.putInt(ACTIVE_SLOT, activeSlot); + args.putInt(FRAME_TYPE, frameType); + args.putString(BEACON_ECDH_PUBLIC_KEY, beaconEcdhKeyPublicKey); + args.putString(ENCRYPTED_IDENTITY_KEY, encryptedIdentityKey); + args.putString(DECRYPTED_IDENTITY_KEY, decryptedIdentityKey); + fragment.setArguments(args); + return fragment; + } + + public EcdhKeyInfoDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + if(getArguments() != null){ + mActiveSlot = getArguments().getInt(ACTIVE_SLOT); + mFrameType = getArguments().getInt(FRAME_TYPE); + mPublicEcdhKey = getArguments().getString(BEACON_ECDH_PUBLIC_KEY); + mEncryptedIdentityKey = getArguments().getString(ENCRYPTED_IDENTITY_KEY); + mDecryptedIdentityKey = getArguments().getString(DECRYPTED_IDENTITY_KEY); + } + super.onCreate(savedInstanceState); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.title_ecdh_key_info)); + + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_dialog_ecdh, null); + AlertDialog alertDialog = alertDialogBuilder.setView(view).setPositiveButton(getString(R.string.ok), null).show(); + final TextView activeSlot = (TextView) view.findViewById(R.id.active_slot); + final TextView frameType = (TextView) view.findViewById(R.id.frame_type); + final TextView ecdhKey = (TextView) view.findViewById(R.id.ecdh_public_key); + final TextView encryptedIdentityKey = (TextView) view.findViewById(R.id.encrypted_ecdh_identity_key); + final TextView decryptedIdentityKey = (TextView) view.findViewById(R.id.decrypted_ecdh_identity_key); + activeSlot.setText(String.valueOf(mActiveSlot)); + ecdhKey.setText(mPublicEcdhKey); + + //display identity key only if the active slot frame type is EID as the identity keys will differ for each slot + switch (mFrameType){ + case TYPE_UID: + frameType.setText(getString(R.string.type_uid)); + encryptedIdentityKey.setText(getString(R.string.no_identity_key)); + decryptedIdentityKey.setText(getString(R.string.no_identity_key)); + break; + case TYPE_URL: + frameType.setText(getString(R.string.type_url)); + encryptedIdentityKey.setText(getString(R.string.no_identity_key)); + decryptedIdentityKey.setText(getString(R.string.no_identity_key)); + break; + case TYPE_TLM: + frameType.setText(getString(R.string.type_tlm)); + encryptedIdentityKey.setText(getString(R.string.no_identity_key)); + decryptedIdentityKey.setText(getString(R.string.no_identity_key)); + break; + case TYPE_EID: + frameType.setText(getString(R.string.type_tlm)); + encryptedIdentityKey.setText(mEncryptedIdentityKey); + decryptedIdentityKey.setText(mDecryptedIdentityKey); + break; + } + + + + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + return alertDialog; + + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ErrorDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ErrorDialogFragment.java new file mode 100644 index 0000000..793442e --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ErrorDialogFragment.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.View; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +/** + * Created by rora on 16.03.2016. + */ +public class ErrorDialogFragment extends DialogFragment{ + + private static final String MESSAGE = "MESSAGE"; + private String mMessage; + + + public static ErrorDialogFragment newInstance(final String message){ + ErrorDialogFragment fragment = new ErrorDialogFragment(); + final Bundle args = new Bundle(); + args.putString(MESSAGE, message); + fragment.setArguments(args); + return fragment; + } + + public ErrorDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mMessage = getArguments().getString(MESSAGE); + } + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.error_generic)); + alertDialogBuilder.setMessage(mMessage); + final AlertDialog alertDialog = alertDialogBuilder.setPositiveButton(getString(R.string.ok), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + return alertDialog; + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/LockStateDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/LockStateDialogFragment.java new file mode 100644 index 0000000..d0251e9 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/LockStateDialogFragment.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.Arrays; + +import javax.crypto.spec.SecretKeySpec; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +/** + * Created by rora on 07.03.2016. + */ +public class LockStateDialogFragment extends DialogFragment { + + private static final String PATTERN_LOCK_STATE = "[0-9a-fA-F]{32}"; + private static final String LOCK_STATE = "LOCK_STATE"; + private static final String UNLOCK_CODE = "UNLOCK_CODE"; + private static final String TAG = "BEACON"; + private static final int LOCKED = 0x00; + private static final int UNLOCKED = 0x01; + private static final int UNLOCKED_AUTOMATIC_RELOCK_DISABLED = 0x02; + + private int mCurrentLockState; + private byte [] mUnlockCode; + private EditText mOldLockCode; + private EditText mNewLockCode; + private TextView mTitleOldLockCode; + private TextView mTitleNewLockCode; + private LinearLayout mOldLockCodeContainer; + private LinearLayout mNewLockCodeContainer; + private Spinner mLockStates; + + public interface OnLockStateListener { + void lockBeacon(byte[] lockCode); + } + + public static LockStateDialogFragment newInstance(final int currentLockState, final byte [] unlockCode){ + LockStateDialogFragment fragment = new LockStateDialogFragment(); + final Bundle args = new Bundle(); + args.putInt(LOCK_STATE, currentLockState); + args.putByteArray(UNLOCK_CODE, unlockCode); + fragment.setArguments(args); + return fragment; + } + + public LockStateDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mCurrentLockState = getArguments().getInt(LOCK_STATE); + mUnlockCode = getArguments().getByteArray(UNLOCK_CODE); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle("Lock State"); + + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_dialog_lock_state, null); + mLockStates = (Spinner) view.findViewById(R.id.frame_types); + mOldLockCode = (EditText) view.findViewById(R.id.old_lock_code); + mNewLockCode = (EditText) view.findViewById(R.id.new_lock_code); + mTitleOldLockCode = (TextView) view.findViewById(R.id.title_old_lock_code); + mTitleNewLockCode = (TextView) view.findViewById(R.id.title_new_lock_code); + mOldLockCodeContainer = (LinearLayout) view.findViewById(R.id.old_lock_code_container); + mNewLockCodeContainer = (LinearLayout) view.findViewById(R.id.new_lock_code_container); + + mLockStates.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + switch (position){ + case 0: + mTitleOldLockCode.setVisibility(View.GONE); + mOldLockCodeContainer.setVisibility(View.GONE); + mTitleNewLockCode.setVisibility(View.GONE); + mNewLockCodeContainer.setVisibility(View.GONE); + break; + case 1: + mTitleOldLockCode.setVisibility(View.VISIBLE); + mOldLockCodeContainer.setVisibility(View.VISIBLE); + mTitleNewLockCode.setVisibility(View.VISIBLE); + mNewLockCodeContainer.setVisibility(View.VISIBLE); + break; + case 2: + mTitleOldLockCode.setVisibility(View.GONE); + mOldLockCodeContainer.setVisibility(View.GONE); + mTitleNewLockCode.setVisibility(View.GONE); + mNewLockCodeContainer.setVisibility(View.GONE); + break; + } + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }); + updateCurrentLockState(); + + final AlertDialog alertDialog = alertDialogBuilder.setView(view).setPositiveButton(getString(R.string.ok), null).setNegativeButton(getString(R.string.cancel), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(validateInput()){ + final byte [] lockCodeData = getValueFromView(); + ((OnLockStateListener)getParentFragment()).lockBeacon(lockCodeData); + dismiss(); + } + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + return alertDialog; + } + + private void updateCurrentLockState() { + switch(mCurrentLockState){ + case LOCKED: + mLockStates.setSelection(0); + break; + case UNLOCKED: + mLockStates.setSelection(1); + break; + case UNLOCKED_AUTOMATIC_RELOCK_DISABLED: + mLockStates.setSelection(2); + break; + } + } + + private boolean validateInput() { + + if(mOldLockCodeContainer.getVisibility() == View.VISIBLE) { + final String oldLockCode = mOldLockCode.getText().toString().trim(); + if(oldLockCode.isEmpty()){ + mOldLockCode.setError("Please enter old lock code"); + return false; + } else if (!oldLockCode.matches(PATTERN_LOCK_STATE)) { + mOldLockCode.setError("Please enter a valid value for old lock code"); + return false; + } + final byte [] oldBeaconLockCode = new byte[16]; + ParserUtils.setByteArrayValue(oldBeaconLockCode, 0, oldLockCode); + if(!Arrays.equals(mUnlockCode, oldBeaconLockCode)){ + Toast.makeText(getActivity(), getString(R.string.lock_code_error), Toast.LENGTH_SHORT).show(); + return false; + } + + } + + if(mNewLockCodeContainer.getVisibility() == View.VISIBLE) { + final String newLockCode = mNewLockCode.getText().toString().trim(); + if (newLockCode.isEmpty()) { + mNewLockCode.setError("Please enter new lock code"); + return false; + } else { + if (!newLockCode.matches(PATTERN_LOCK_STATE)) { + mNewLockCode.setError("Please enter a valid value for new lock code"); + return false; + } + } + } + return true; + } + + private byte[] getValueFromView() { + + final int lockState = mLockStates.getSelectedItemPosition(); + final String oldLockCode = mOldLockCode.getText().toString(); + final String newLockCode = mNewLockCode.getText().toString(); + final byte [] data; + + if(lockState == 0 || lockState == 2){ + data = new byte[1]; + data[0] = (byte)lockState; + return data; + } else { + data = new byte[17]; //lockstate + security key + data[0] = (byte)(lockState-1); + + final byte [] oldLockCodeBytes = new byte [16]; + ParserUtils.setByteArrayValue(oldLockCodeBytes, 0, oldLockCode); + + final byte [] newLockCodeBytes = new byte[16]; + ParserUtils.setByteArrayValue(newLockCodeBytes, 0, newLockCode); + + final byte [] encryptedLockCode = ParserUtils.aes128Encrypt(newLockCodeBytes, new SecretKeySpec(oldLockCodeBytes, "AES")); + System.arraycopy(encryptedLockCode, 0, data, 1, encryptedLockCode.length); + return data; + } + } + + @Override + public void onDetach() { + super.onDetach(); + } + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ProximityApiErrorDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ProximityApiErrorDialogFragment.java new file mode 100644 index 0000000..32dae13 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ProximityApiErrorDialogFragment.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +/** + * Created by rora on 16.03.2016. + */ +public class ProximityApiErrorDialogFragment extends DialogFragment{ + + private static final String ERROR_CODE = "ERROR_CODE"; + private static final String MESSAGE = "MESSAGE"; + private static final String STATUS = "STATUS"; + private String mErrorCode; + private String mMessage; + private String mStatus; + + + public static ProximityApiErrorDialogFragment newInstance(final String errorCode, final String message, final String status){ + ProximityApiErrorDialogFragment fragment = new ProximityApiErrorDialogFragment(); + final Bundle args = new Bundle(); + args.putString(ERROR_CODE, errorCode); + args.putString(MESSAGE, message); + args.putString(STATUS, status); + fragment.setArguments(args); + return fragment; + } + + public ProximityApiErrorDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mErrorCode = getArguments().getString(ERROR_CODE); + mMessage = getArguments().getString(MESSAGE); + mStatus = getArguments().getString(STATUS); + } + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle("Error " + mErrorCode); + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_dialog_error, null); + final TextView message = (TextView) view.findViewById(R.id.error_message); + final TextView status = (TextView) view.findViewById(R.id.error_status); + message.setText(mMessage); + status.setText(mStatus); + final AlertDialog alertDialog = alertDialogBuilder.setView(view).setPositiveButton(getString(R.string.ok), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + return alertDialog; + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RadioTxPowerDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RadioTxPowerDialogFragment.java new file mode 100644 index 0000000..b7c2fe3 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RadioTxPowerDialogFragment.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +/** + * Created by rora on 06.04.2016. + */ +public class RadioTxPowerDialogFragment extends DialogFragment { + + private static final String PATTERN_TX_POWER = "(-?\\d{1,3}(|$))+"; + private static final String RADIO_TX_POWER = "RADIO_TX_POWER"; + private static final String ADVANCED_ADV_TX_POWER = "ADVANCED_ADV_TX_POWER"; + private static final String TAG = "BEACON"; + + private String mRadioTxPower; + private boolean mAdvancedAdvTxPower; + private EditText radioTxPower; + + public interface OnRadioTxPowerListener { + void configureRadioTxPower(final byte [] radioTxPower, final boolean advanceTxPowerSupported); + } + + public static RadioTxPowerDialogFragment newInstance(final String radioTxPower, final boolean advancedAdvTxPower){ + RadioTxPowerDialogFragment fragment = new RadioTxPowerDialogFragment(); + final Bundle args = new Bundle(); + args.putString(RADIO_TX_POWER, radioTxPower); + args.putBoolean(ADVANCED_ADV_TX_POWER, advancedAdvTxPower); + fragment.setArguments(args); + return fragment; + } + + public RadioTxPowerDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mRadioTxPower = getArguments().getString(RADIO_TX_POWER); + mAdvancedAdvTxPower = getArguments().getBoolean(ADVANCED_ADV_TX_POWER); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + if(!mAdvancedAdvTxPower) { + alertDialogBuilder.setTitle(getString(R.string.title_config_radio_tx_power)); + } else { + alertDialogBuilder.setTitle(getString(R.string.title_config_adv_radio_tx_power)); + } + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_dialog_radio_tx_power, null); + final TextView currentTxPower = (TextView) view.findViewById(R.id.current_radio_tx_power); + currentTxPower.setText(mRadioTxPower); + final TextView currentTxPowerTitle = (TextView) view.findViewById(R.id.radio_tx_power_title); + radioTxPower = (EditText) view.findViewById(R.id.radio_tx_power); + final AlertDialog alertDialog = alertDialogBuilder.setView(view).setPositiveButton(getString(R.string.configure), null).setNegativeButton(getString(R.string.cancel), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + + if(mAdvancedAdvTxPower) { + radioTxPower.setHint(getString(R.string.advanced_adv_tx_power)); + currentTxPowerTitle.setText(getString(R.string.current_advanced_adv_tx_power)); + } + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(validateInput()){ + final byte [] radioTxPower = getValueFromView(); + ((OnRadioTxPowerListener)getParentFragment()).configureRadioTxPower(radioTxPower, mAdvancedAdvTxPower); + dismiss(); + } + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + return alertDialog; + } + + private boolean validateInput() { + final String advertisingInterval = radioTxPower.getText().toString().trim(); + + final String txPower = radioTxPower.getText().toString().trim(); + if(advertisingInterval.isEmpty()){ + radioTxPower.setError("Enter supported Radio Tx power value"); + return false; + } else { + if (!txPower.matches(PATTERN_TX_POWER)) { + radioTxPower.setError("Please enter a valid value for Radio Tx power"); + return false; + } + } + return true; + } + + private byte[] getValueFromView() { + final byte [] data = new byte[1]; + data[0] = (byte) Integer.parseInt(radioTxPower.getText().toString().trim()); + return data; + } + + @Override + public void onDetach() { + super.onDetach(); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ReadWriteAdvertisementSlotDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ReadWriteAdvertisementSlotDialogFragment.java new file mode 100644 index 0000000..5f2f668 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/ReadWriteAdvertisementSlotDialogFragment.java @@ -0,0 +1,587 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.bluetooth.BluetoothGattCharacteristic; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.webkit.URLUtil; +import android.widget.AdapterView; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.auth.GoogleAuthException; +import com.google.android.gms.auth.GoogleAuthUtil; +import com.squareup.okhttp.Callback; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; + +import no.nordicsemi.android.nrfbeacon.nearby.AuthorizedServiceTask; +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.util.AuthTaskUrlShortener; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +/** + * Created by rora on 07.03.2016. + */ +public class ReadWriteAdvertisementSlotDialogFragment extends DialogFragment { + + + private static final String PATTERN_NAMESPACE_ID = "[0-9a-fA-F]{20}"; + private static final String PATTERN_INSTANCE_ID = "[0-9a-fA-F]{12}"; + private static final String RW_ADVERTISEMENT_SLOT = "RW_ADVERTISEMENT_SLOT"; + private static final String SLOT_TASK = "SLOT_TASK"; + private static final String ACTIVE_SLOT = "ACTIVE_SLOT"; + private static final String TAG = "BEACON"; + private static final String ACCOUNT_NAME_PREF = "userAccount"; + private static final String SHARED_PREFS_NAME = "nrfNearbyInfo"; + private static final String AUTH_PROXIMITY_API = "oauth2:https://www.googleapis.com/auth/userlocation.beacon.registry"; + private static final String AUTH_SCOPE_URL_SHORTENER = "oauth2:https://www.googleapis.com/auth/urlshortener"; + + private static final int EMPTY_SLOT = -1; + private static final int TYPE_UID = 0x00; + private static final int TYPE_URL = 0x10; + private static final int TYPE_TLM = 0x20; + private static final int TYPE_EID = 0x30; + + + private byte [] mReadWriteAdvSlotData; + private int mActiveSlot; + private boolean mNewAddSlot; + + private LinearLayout mSlotStateContainer; + private LinearLayout mUidInfoContainer; + private LinearLayout mUrlInfoContainer; + private LinearLayout mUrlShortenerContainer; + private LinearLayout mEidInfoContainer; + private Spinner mFrameTypes; + private Spinner mUrlTypes; + private Spinner mSecurityTypes; + private TextView mActiveSlotNumber; + private TextView mSlotState; + private TextView mUrlShortText; + private EditText mNamespaceId; + private EditText mInstanceId; + private EditText mUrl; + private EditText mTimerExponent; + private int mFrameType; + private int mNewFrameType; + private Button mButtonNeutral; + private ProgressDialog mProgressDialog; + private Handler mProgressDialogHandler; + private boolean mUrlShortenerClicked = false; + + public interface OnReadWriteAdvertisementSlotListener { + void configureEidSlot(byte[] eidSlotData); + + void configureUidSlot(byte[] uidSlotData); + + void configureUrlSlot(byte[] urlSlotData); + + void configureTlmSlot(byte[] tlmSlotData); + } + + public static ReadWriteAdvertisementSlotDialogFragment newInstance(final boolean addNewSlot, final int activeSlot, byte [] readWriteAdvSlotData){ + ReadWriteAdvertisementSlotDialogFragment fragment = new ReadWriteAdvertisementSlotDialogFragment(); + final Bundle args = new Bundle(); + args.putBoolean(SLOT_TASK, addNewSlot); + args.putInt(ACTIVE_SLOT, activeSlot); + args.putByteArray(RW_ADVERTISEMENT_SLOT, readWriteAdvSlotData); + fragment.setArguments(args); + return fragment; + } + + public ReadWriteAdvertisementSlotDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mActiveSlot = getArguments().getInt(ACTIVE_SLOT); + mNewAddSlot = getArguments().getBoolean(SLOT_TASK); + mReadWriteAdvSlotData = getArguments().getByteArray(RW_ADVERTISEMENT_SLOT); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.title_rw_adv_slot)); + + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_dialog_rw_adv_slot, null); + mSlotStateContainer = (LinearLayout) view.findViewById(R.id.slot_state_container); + mUidInfoContainer = (LinearLayout) view.findViewById(R.id.uid_container); + mUrlInfoContainer = (LinearLayout) view.findViewById(R.id.url_container); + mUrlShortenerContainer = (LinearLayout) view.findViewById(R.id.url_shortener_container); + mEidInfoContainer = (LinearLayout) view.findViewById(R.id.eid_data_container); + mUrlTypes = (Spinner) view.findViewById(R.id.url_types); + mFrameTypes = (Spinner) view.findViewById(R.id.frame_types); + mSecurityTypes = (Spinner) view.findViewById(R.id.security_type); + mNamespaceId = (EditText) view.findViewById(R.id.namespace_id); + mInstanceId = (EditText) view.findViewById(R.id.instance_id); + mUrl = (EditText) view.findViewById(R.id.url_data); + mTimerExponent = (EditText) view.findViewById(R.id.timer_exponent); + mActiveSlotNumber = (TextView) view.findViewById(R.id.slot_number); + mSlotState = (TextView) view.findViewById(R.id.slot_state); + mUrlShortText = (TextView) view.findViewById(R.id.url_short_text); + + final AlertDialog alertDialog = alertDialogBuilder.setView(view) + .setPositiveButton(getString(R.string.configure), null) + .setNegativeButton(getString(R.string.cancel), null) + .setNeutralButton(getString(R.string.random_uid), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + + mProgressDialog = new ProgressDialog(getActivity()); + mProgressDialog.setCancelable(false); + mProgressDialog.setCanceledOnTouchOutside(false); + mProgressDialog.setTitle(getString(R.string.prog_dialog_url_shortener)); + mProgressDialog.setMessage(getString(R.string.prog_dialog_url_shortener_message)); + + mFrameTypes.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + switch (position) { + case 0: + mButtonNeutral.setVisibility(View.VISIBLE); + mButtonNeutral.setText(getString(R.string.random_uid)); + mUidInfoContainer.setVisibility(View.VISIBLE); + mUrlInfoContainer.setVisibility(View.GONE); + mUrlShortenerContainer.setVisibility(View.GONE); + mEidInfoContainer.setVisibility(View.GONE); + if (TYPE_UID == mFrameType) { + final String namespaceId = ParserUtils.bytesToHex(mReadWriteAdvSlotData, 2, 10, false); + final String instanceId = ParserUtils.bytesToHex(mReadWriteAdvSlotData, 11, 6, false); + mNamespaceId.setText(namespaceId); + mInstanceId.setText(instanceId); + } + mNewFrameType = TYPE_UID; + break; + case 1: + mButtonNeutral.setVisibility(View.VISIBLE); + mButtonNeutral.setText(getString(R.string.url_shorten_button)); + mUrlInfoContainer.setVisibility(View.VISIBLE); + mUrlShortenerContainer.setVisibility(View.GONE); + mUidInfoContainer.setVisibility(View.GONE); + mEidInfoContainer.setVisibility(View.GONE); + if (TYPE_URL == mFrameType) { + String url = ParserUtils.decodeUri(mReadWriteAdvSlotData, 2, mReadWriteAdvSlotData.length - 2); + if(url.startsWith("https://www.")){ + url = url.replace("https://www.", ""); + mUrlTypes.setSelection(0); + } else if(url.startsWith("http://www.")){ + url = url.replace("http://www.", ""); + mUrlTypes.setSelection(1); + } else if(url.startsWith("https://")){ + url = url.replace("https://", ""); + mUrlTypes.setSelection(2); + } else if(url.startsWith("https://")){ + url = url.replace("http://", ""); + mUrlTypes.setSelection(3); + } + mUrl.setText(url.trim()); + + + } + mNewFrameType = TYPE_URL; + break; + case 2: + mButtonNeutral.setVisibility(View.GONE); + mUidInfoContainer.setVisibility(View.GONE); + mUrlInfoContainer.setVisibility(View.GONE); + mUrlShortenerContainer.setVisibility(View.GONE); + mEidInfoContainer.setVisibility(View.GONE); + mNewFrameType = TYPE_TLM; + break; + case 3: + mButtonNeutral.setVisibility(View.GONE); + mEidInfoContainer.setVisibility(View.VISIBLE); + mUidInfoContainer.setVisibility(View.GONE); + mUrlInfoContainer.setVisibility(View.GONE); + mUrlShortenerContainer.setVisibility(View.GONE); + if (TYPE_EID == mFrameType) { + final String timerExponent = String.valueOf(ParserUtils.getIntValue(mReadWriteAdvSlotData, 1, BluetoothGattCharacteristic.FORMAT_UINT8)); + mTimerExponent.setText(timerExponent); + } + mNewFrameType = TYPE_EID; + break; + } + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }); + + if(mReadWriteAdvSlotData.length > 0) + mSecurityTypes.setSelection(0); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (validateInput()) { + byte[] data = getValueFromView(); + switch (mFrameTypes.getSelectedItemPosition()) { + case 0: + ((OnReadWriteAdvertisementSlotListener) getParentFragment()).configureUidSlot(data); + break; + case 1: + ((OnReadWriteAdvertisementSlotListener) getParentFragment()).configureUrlSlot(data); + break; + case 2: + ((OnReadWriteAdvertisementSlotListener) getParentFragment()).configureTlmSlot(data); + break; + case 3: + ((OnReadWriteAdvertisementSlotListener) getParentFragment()).configureEidSlot(data); + break; + } + dismiss(); + } + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + mButtonNeutral = alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL); + mButtonNeutral.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + switch (mFrameTypes.getSelectedItemPosition()) { + case 0: + final String randomUid = ParserUtils.randomUid(16); + final String namespace = (randomUid.substring(0, 20)); + final String instance = (randomUid.substring(20, randomUid.length())); + mNamespaceId.setText(namespace.toUpperCase()); + mInstanceId.setText(instance.toUpperCase()); + break; + case 1: + final String url = mUrl.getText().toString().trim(); + + if (!url.isEmpty()) { + mUrlShortenerClicked = true; + /*mProgressDialog.show(); + mProgressDialogHandler = new Handler(); + mProgressDialogHandler.postDelayed(mRunnableHandler, 15000);*/ + if(getUserAccount() != null) + new AuthTaskUrlShortener(mUrlShortenerCallback, url, getActivity(), getUserAccount()).execute(); + else + Toast.makeText(getActivity(), getString(R.string.user_account_unavailable), Toast.LENGTH_LONG).show(); + + } + break; + } + } + }); + + mUrl.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mUrl.setError(null); + if(mUrlShortenerContainer.getVisibility() == View.VISIBLE) + mUrlShortenerContainer.setVisibility(View.GONE); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + updateUi(); + + final String name = getUserAccountName(); + if(!name.isEmpty()) { + Account userAccount = null; + final Account[] accounts = AccountManager.get(getActivity()).getAccounts(); + for (Account account : accounts) { + if (account.name.equals(name)) { + userAccount = account; + break; + } + } + new AuthorizedServiceTask(getActivity(), userAccount, AUTH_SCOPE_URL_SHORTENER).execute(); + } + return alertDialog; + } + + private String getUserAccountName(){ + SharedPreferences mSharedPreferences = getContext().getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE); + return mSharedPreferences.getString(ACCOUNT_NAME_PREF, null); + } + + private Account getUserAccount(){ + final String name = getUserAccountName(); + if(!name.isEmpty()) { + final Account[] accounts = AccountManager.get(getActivity()).getAccounts(); + for (Account account : accounts) { + if (account.name.equals(name)) { + return account; + } + } + } + return null; + } + + private final Runnable mRunnableHandler = new Runnable() { + @Override + public void run() { + if(mProgressDialog != null && mProgressDialog.isShowing()){ + mProgressDialog.dismiss(); + } + } + }; + + private boolean validateInput() { + + if(mUidInfoContainer.getVisibility() == View.VISIBLE) { + final String namespaceId = mNamespaceId.getText().toString().trim(); + if (namespaceId.isEmpty()) { + mNamespaceId.setError("Please enter namespace id"); + return false; + } else { + if (!namespaceId.matches(PATTERN_NAMESPACE_ID)) { + mNamespaceId.setError("Please enter a valid value for namespace id"); + return false; + } + } + final String instanceId = mInstanceId.getText().toString().trim(); + if (instanceId.isEmpty()) { + mInstanceId.setError("Please enter instance id"); + return false; + } else { + if (!instanceId.matches(PATTERN_INSTANCE_ID)) { + mInstanceId.setError("Please enter a valid value for instance id"); + return false; + } + } + } + + if(mUrlInfoContainer.getVisibility() == View.VISIBLE) { + + if(mUrlShortenerContainer.getVisibility() == View.VISIBLE){ + return true; + } + + final String url = mUrlTypes.getSelectedItem().toString().trim() + mUrl.getText().toString().trim(); + if (url.isEmpty()) { + mUrl.setError("Please enter a value for URL"); + return false; + } else { + if (!URLUtil.isValidUrl(url)) { + mUrl.setError("Please enter a valid value for URL"); + return false; + } else if (!URLUtil.isNetworkUrl(url)) { + mUrl.setError("Please enter a valid value for URL"); + return false; + } else if (ParserUtils.encodeUri(url).length > 18){ + mUrl.setError("Please enter a shortened URL or press use the URL shortener!"); + return false; + } + } + } + + if(mEidInfoContainer.getVisibility() == View.VISIBLE) { + + final String timerExponent = mTimerExponent.getText().toString().trim(); + if(timerExponent.isEmpty()){ + mTimerExponent.setError(getString(R.string.timer_exponent_error)); + return false; + } else { + boolean valid; + int i = 0; + try { + i = Integer.parseInt(timerExponent); + valid = ((i & 0xFFFFFF00) == 0 || (i & 0xFFFFFF00) == 0xFFFFFF00); + } catch (NumberFormatException e) { + valid = false; + } + if (!valid) { + mTimerExponent.setError(getString(R.string.uint8_error)); + return false; + } else if ((i < 10 || i > 15)){ + mTimerExponent.setError(getString(R.string.timer_exponent_error_value)); + return false; + } + } + } + return true; + } + + private byte[] getValueFromView() { + byte [] data = null; + int length; + switch (mNewFrameType) { + case TYPE_UID: + data = new byte[17]; + data[0] = TYPE_UID; + final String namespaceId = mNamespaceId.getText().toString().trim(); + ParserUtils.setByteArrayValue(data, 1, namespaceId); + final String instanceId = mInstanceId.getText().toString().trim(); + ParserUtils.setByteArrayValue(data, 11, instanceId); + return data; + case TYPE_URL: + final String urlText; + if(mUrlShortenerContainer.getVisibility() != View.VISIBLE){ + urlText = mUrlTypes.getSelectedItem().toString().trim() + mUrl.getText().toString().trim(); + } else { + urlText = mUrlShortText.getText().toString().trim(); + } + + byte [] urlData = ParserUtils.encodeUri(urlText); + data = new byte[urlData.length + 1]; + data[0] = (byte) TYPE_URL; + System.arraycopy(urlData, 0, data , 1, urlData.length); + return data; + case TYPE_TLM: + data = new byte[1]; + data[0] = TYPE_TLM; + return data; + case TYPE_EID: + final String timerExponent = mTimerExponent.getText().toString().trim(); + + if (mSecurityTypes.getSelectedItemPosition() == 0) { + data = new byte[34]; + data[0] = TYPE_EID; + data[33] = (byte) Integer.parseInt(timerExponent); + return data; + } else { + data = new byte[18]; + data[0] = TYPE_EID; + data[17] = (byte) Integer.parseInt(timerExponent); + return data; + } + } + return data; + } + + private void updateUi() { + final int frameType; + if(mReadWriteAdvSlotData == null || mReadWriteAdvSlotData.length == 0) + frameType = EMPTY_SLOT; + else + frameType = ParserUtils.getIntValue(mReadWriteAdvSlotData, 0, BluetoothGattCharacteristic.FORMAT_UINT8); + switch (frameType){ + case TYPE_UID: + mButtonNeutral.setVisibility(View.VISIBLE); + mFrameType = TYPE_UID; + mFrameTypes.setSelection(0); + break; + case TYPE_URL: + mButtonNeutral.setVisibility(View.VISIBLE); + mButtonNeutral.setText(getString(R.string.url_shorten_button)); + mFrameType = TYPE_URL; + mFrameTypes.setSelection(1); + break; + case TYPE_TLM: + mButtonNeutral.setVisibility(View.GONE); + mFrameType = TYPE_TLM; + mFrameTypes.setSelection(2); + break; + case TYPE_EID: + mButtonNeutral.setVisibility(View.GONE); + mFrameType = TYPE_EID; + mFrameTypes.setSelection(3); + break; + case EMPTY_SLOT: + mSlotStateContainer.setVisibility(View.VISIBLE); + mSlotState.setText(getString(R.string.slot_state_empty)); + mFrameType = EMPTY_SLOT; + break; + } + mActiveSlotNumber.setText(String.valueOf(mActiveSlot)); + } + + @Override + public void onDetach() { + super.onDetach(); + } + + private final Callback mUrlShortenerCallback = new Callback() { + @Override + public void onFailure(Request request, IOException e) { + Log.v(TAG, "Failure: " + request.toString()); + if(mProgressDialog != null && mProgressDialog.isShowing()) + mProgressDialog.dismiss(); + } + + @Override + public void onResponse(Response response) throws IOException { + if(mProgressDialog != null && mProgressDialog.isShowing()) + mProgressDialog.dismiss(); + if(!response.isSuccessful()){ + //GoogleAuthUtil.clearToken(getActivity(), token); + mUrlShortenerContainer.setVisibility(View.GONE); + Toast.makeText(getActivity(), response.body().string(), Toast.LENGTH_SHORT).show(); + Account userAccount = getUserAccount(); + if(userAccount != null) + new AuthorizedServiceTask(getActivity(), userAccount, AUTH_SCOPE_URL_SHORTENER).execute(); + } else { + try { + mUrlShortenerContainer.setVisibility(View.VISIBLE); + mUrl.setError(null); + final JSONObject json = new JSONObject(response.body().string()); + mUrlShortText.setText(json.getString("id")); + + } catch (JSONException e) { + e.printStackTrace(); + } + + } + } + }; +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RegisterBeaconDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RegisterBeaconDialogFragment.java new file mode 100644 index 0000000..095a1d5 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RegisterBeaconDialogFragment.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.LinearLayout; + +import java.nio.charset.Charset; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Random; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +/** + * Created by rora on 07.03.2016. + */ +public class RegisterBeaconDialogFragment extends DialogFragment { + + private static final String PATTERN_NAMESPACE_ID = "[0-9a-fA-F]{20}"; + private static final String PATTERN_INSTANCE_ID = "[0-9a-fA-F]{12}"; + private static final String TAG = "BEACON"; + private static final int TYPE_UID = 0x00; + private static final int TYPE_EID = 0x30; + private EditText mNamespaceId; + private EditText mInstanceId; + private EditText mAttachment; + + public interface OnBeaconRegisteredListener { + void registerBeaconListener(final byte[] uid); + } + + public static RegisterBeaconDialogFragment newInstance(){ + RegisterBeaconDialogFragment fragment = new RegisterBeaconDialogFragment(); + return fragment; + } + + public RegisterBeaconDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.register_beacon_title)); + alertDialogBuilder.setMessage(getString(R.string.register_beacon_message)); + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_register_beacon, null); + mNamespaceId = (EditText) view.findViewById(R.id.namespace_id); + mInstanceId = (EditText) view.findViewById(R.id.instance_id); + + final AlertDialog alertDialog = alertDialogBuilder.setView(view) + .setPositiveButton(getString(R.string.register), null) + .setNeutralButton(getString(R.string.random_uid), null) + .setNegativeButton(getString(R.string.cancel), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (validateInput()) { + final byte[] uid = new byte[16]; + ParserUtils.setByteArrayValue(uid, 0, mNamespaceId.getText().toString().trim()); + ParserUtils.setByteArrayValue(uid, 10, mInstanceId.getText().toString().trim()); + ((OnBeaconRegisteredListener) getParentFragment()).registerBeaconListener(uid); + dismiss(); + } + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final String randomUid = ParserUtils.randomUid(16); + final String namespace = (randomUid.substring(0,20)); + final String instance = (randomUid.substring(20,randomUid.length())); + mNamespaceId.setText(namespace.toUpperCase()); + mInstanceId.setText(instance.toUpperCase()); + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + return alertDialog; + } + + @Override + public void onDetach() { + super.onDetach(); + } + + private boolean validateInput(){ + final String namespaceId = mNamespaceId.getText().toString().trim(); + if (namespaceId.isEmpty()) { + mNamespaceId.setError("Please enter namespace id"); + return false; + } else { + if (!namespaceId.matches(PATTERN_NAMESPACE_ID)) { + mNamespaceId.setError("Please enter a valid value for namespace id"); + return false; + } + + } + final String instanceId = mInstanceId.getText().toString().trim(); + if (instanceId.isEmpty()) { + mInstanceId.setError("Please enter instance id"); + return false; + } else { + if (!instanceId.matches(PATTERN_INSTANCE_ID)) { + mInstanceId.setError("Please enter a valid value for instance id"); + return false; + } + + } + return true; + } + + private byte[] aes128Encrypt(byte[] data, SecretKeySpec keySpec) { + Cipher cipher; + try { + // Ignore the "ECB encryption should not be used" warning. We use exactly one block so + // the difference between ECB and CBC is just an IV or not. In addition our blocks are + // always different since they have a monotonic timestamp. Most importantly, our blocks + // aren't sensitive. Decrypting them means means knowing the beacon time and its rotation + // period. If due to ECB an attacker could find out that the beacon broadcast the same + // block a second time, all it could infer is that for some reason the clock of the beacon + // reset, which is not very helpful + cipher = Cipher.getInstance("AES/ECB/NoPadding"); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + Log.e(TAG, "Error constructing cipher instance", e); + return null; + } + + try { + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + } catch (InvalidKeyException e) { + Log.e(TAG, "Error initializing cipher instance", e); + return null; + } + + byte[] ret; + try { + ret = cipher.doFinal(data); + } catch (IllegalBlockSizeException | BadPaddingException e) { + Log.e(TAG, "Error executing cipher", e); + return null; + } + + return ret; + } + + + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RemainConnectableDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RemainConnectableDialogFragment.java new file mode 100644 index 0000000..2f85468 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/RemainConnectableDialogFragment.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.SwitchCompat; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +/** + * Created by rora on 07.03.2016. + */ +public class RemainConnectableDialogFragment extends DialogFragment { + + private static final String PATTERN_TX_POWER = "[0-9a-fA-F]{32}"; + private static final String REMAIN_CONNECTABLE_FLAG = "REMAIN_CONNECTABLE_FLAG"; + private static final String TAG = "BEACON"; + private boolean mRemainConnectableFlag; + + public interface OnBeaconUnlockListener { + void unlockBeacon(byte[] encryptedLockCode, final byte[] beaconLockCode); + } + + public static RemainConnectableDialogFragment newInstance(final boolean flag){ + RemainConnectableDialogFragment fragment = new RemainConnectableDialogFragment(); + final Bundle args = new Bundle(); + args.putBoolean(REMAIN_CONNECTABLE_FLAG, flag); + fragment.setArguments(args); + return fragment; + } + + public RemainConnectableDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mRemainConnectableFlag = getArguments().getBoolean(REMAIN_CONNECTABLE_FLAG); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.title_remain_connectable)); + final View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_remain_connectable, null); + final AlertDialog alertDialog = alertDialogBuilder.setView(view).setPositiveButton(getString(R.string.ok), null).setNegativeButton(getString(R.string.cancel), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + final SwitchCompat switchCompat = (SwitchCompat) view.findViewById(R.id.remain_connectable); + switchCompat.setChecked(mRemainConnectableFlag); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + return alertDialog; + } + + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/UnlockBeaconDialogFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/UnlockBeaconDialogFragment.java new file mode 100644 index 0000000..fa3eb92 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/UnlockBeaconDialogFragment.java @@ -0,0 +1,149 @@ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +/** + * Created by rora on 07.03.2016. + */ +public class UnlockBeaconDialogFragment extends DialogFragment { + + private static final String PATTERN_TX_POWER = "[0-9a-fA-F]{32}"; + private static final String CHALLENGE = "CHALLENGE"; + private static final String TAG = "BEACON"; + private EditText mUnlockCode; + private OnBeaconUnlockListener beaconUnlockListener; + private byte [] mChallenge; + + public interface OnBeaconUnlockListener { + void unlockBeacon(byte [] encryptedLockCode, final byte [] beaconLockCode); + void cancelUnlockBeacon(); + } + + public static UnlockBeaconDialogFragment newInstance(byte [] challenge){ + UnlockBeaconDialogFragment fragment = new UnlockBeaconDialogFragment(); + final Bundle args = new Bundle(); + args.putByteArray(CHALLENGE, challenge); + fragment.setArguments(args); + return fragment; + } + + public UnlockBeaconDialogFragment(){ + + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(getArguments() != null){ + mChallenge = getArguments().getByteArray(CHALLENGE); + } + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); + alertDialogBuilder.setTitle(getString(R.string.unlock_beacon_title)); + alertDialogBuilder.setMessage(getString(R.string.unlock_beacon_message)); + final View alertDialogView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_dialog_unlock, null); + mUnlockCode = (EditText) alertDialogView.findViewById(R.id.lock_code); + mUnlockCode.setText("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); + + final AlertDialog alertDialog = alertDialogBuilder.setView(alertDialogView).setPositiveButton(getString(R.string.unlock), null).setNegativeButton(getString(R.string.cancel), null).show(); + alertDialog.setCanceledOnTouchOutside(false); + + alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(validateInput()) { + final String lockCode = mUnlockCode.getText().toString().trim(); + byte [] beaconLockCode = new byte[16]; + ParserUtils.setByteArrayValue(beaconLockCode, 0, lockCode); + final byte [] encryptedLockCode = ParserUtils.aes128Encrypt(mChallenge, new SecretKeySpec(beaconLockCode, "AES")); + ((OnBeaconUnlockListener)getParentFragment()).unlockBeacon(encryptedLockCode, beaconLockCode); + } + } + }); + + alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + ((OnBeaconUnlockListener)getParentFragment()).cancelUnlockBeacon(); + } + }); + + return alertDialog; + } + + @Override + public void onDetach() { + super.onDetach(); + } + + private boolean validateInput(){ + final String lockCode = mUnlockCode.getText().toString().trim(); + if(lockCode.isEmpty()){ + mUnlockCode.setError("Please enter the lock code to unlock the beacon"); + return false; + } else if (!lockCode.matches(PATTERN_TX_POWER)) { + mUnlockCode.setError("Please enter a valid value for new lock code"); + return false; + } + return true; + } + + private byte[] aes128Encrypt(byte[] data, SecretKeySpec keySpec) { + Cipher cipher; + try { + // Ignore the "ECB encryption should not be used" warning. We use exactly one block so + // the difference between ECB and CBC is just an IV or not. In addition our blocks are + // always different since they have a monotonic timestamp. Most importantly, our blocks + // aren't sensitive. Decrypting them means means knowing the beacon time and its rotation + // period. If due to ECB an attacker could find out that the beacon broadcast the same + // block a second time, all it could infer is that for some reason the clock of the beacon + // reset, which is not very helpful + cipher = Cipher.getInstance("AES/ECB/NoPadding"); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + Log.e(TAG, "Error constructing cipher instance", e); + return null; + } + + try { + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + } catch (InvalidKeyException e) { + Log.e(TAG, "Error initializing cipher instance", e); + return null; + } + + byte[] ret; + try { + ret = cipher.doFinal(data); + } catch (IllegalBlockSizeException | BadPaddingException e) { + Log.e(TAG, "Error executing cipher", e); + return null; + } + + return ret; + } + +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/UpdateFragment.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/UpdateFragment.java new file mode 100644 index 0000000..63ada17 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/update/UpdateFragment.java @@ -0,0 +1,1592 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.update; + +import android.Manifest; +import android.accounts.Account; +import android.accounts.AccountManager; +import android.app.Activity; +import android.app.ProgressDialog; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothProfile; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.provider.Settings; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.content.LocalBroadcastManager; +import android.text.SpannableString; +import android.text.style.UnderlineSpan; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.common.AccountPicker; +import com.google.sample.libeddystoneeidr.EddystoneEidrGenerator; +import com.google.sample.libproximitybeacon.ProximityBeaconImpl; +import com.squareup.okhttp.Callback; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Random; +import java.util.UUID; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +import no.nordicsemi.android.nrfbeacon.nearby.AuthorizedServiceTask; +import no.nordicsemi.android.nrfbeacon.nearby.MainActivity; +import no.nordicsemi.android.nrfbeacon.nearby.R; +import no.nordicsemi.android.nrfbeacon.nearby.UpdateService; +import no.nordicsemi.android.nrfbeacon.nearby.common.BaseFragment; +import no.nordicsemi.android.nrfbeacon.nearby.scanner.ScannerFragment; +import no.nordicsemi.android.nrfbeacon.nearby.scanner.ScannerFragmentListener; +import no.nordicsemi.android.nrfbeacon.nearby.util.NetworkUtils; +import no.nordicsemi.android.nrfbeacon.nearby.util.ParserUtils; + +//import eidr.EddystoneEidrGenerator; + +public class UpdateFragment extends BaseFragment implements ScannerFragmentListener, + UnlockBeaconDialogFragment.OnBeaconUnlockListener, + ReadWriteAdvertisementSlotDialogFragment.OnReadWriteAdvertisementSlotListener, + LockStateDialogFragment.OnLockStateListener, + RegisterBeaconDialogFragment.OnBeaconRegisteredListener, + CreateAttachmentDialogFragment.OnAttachmentCreatedListener, + RadioTxPowerDialogFragment.OnRadioTxPowerListener, + ClearSlotDialogFragment.OnClearSlotListener, + AdvertisingIntervalDialogFragment.OnAdvertisingIntervalListener { + /** + * The UUID of a service in the beacon advertising packet when in Config mode. This may be null if no filter required. + */ +// private static final UUID EDDYSTONE_GATT_CONFIG_SERVICE_UUID = UUID.fromString("A3C87500-8ED3-4BDF-8A39-A01BEBEDE295"); + private static final UUID EDDYSTONE_GATT_CONFIG_SERVICE_UUID = UUID.fromString("0000FEAA-0000-1000-8000-00805F9B34FB"); + private static final String AUTH_SCOPE_PROXIMITY_API = "oauth2:https://www.googleapis.com/auth/userlocation.beacon.registry"; + private static final String AUTH_SCOPE_URL_SHORTENER = "oauth2:https://www.googleapis.com/auth/urlshortener"; + private static final String APP_NAMESPACE_TYPE = "nrf-nearby-1100/string"; + private static final String ACCOUNT_NAME_PREF = "userAccount"; + private static final String SHARED_PREFS_NAME = "nrfNearbyInfo"; + private static final String SERVICE_ECDH_KEY = "SERVICE_ECDH_KEY"; + private static final String TAG = "BEACON"; + + static final int REQUEST_CODE_USER_ACCOUNT = 1002; + private static final int REQUEST_PERMISSION_REQ_CODE = 76; // any 8-bit number + private static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1003; + private static final int REQUEST_ENABLE_BT = 1; + + private static final int LOCKED = 0x00; + private static final int UNLOCKED = 0x01; + private static final int UNLOCKED_AUTOMATIC_RELOCK_DISABLED = 0x02; + private static final int IS_VARIABLE_TX_POWER_SUPPORTED = 0x02; + private static final int EMPTY_SLOT = -1; + private static final int TYPE_UID = 0x00; + private static final int TYPE_URL = 0x10; + private static final int TYPE_TLM = 0x20; + private static final int TYPE_EID = 0x30; + + private static final int ERROR_ALREADY_EXISTS = 409; + private static final int ERROR_UNAUTHORIZED = 401; + + private TextView mBeaconHelp; + + private Button mConnectButton; + private LinearLayout mBeaconConfigurationContainer; + private LinearLayout mFrameTypeContainer; + private LinearLayout mUidDataContainer; + private LinearLayout mUrlDataContainer; + private LinearLayout mTlmDataContainer; + private LinearLayout mEtlmDataContainer; + private LinearLayout mEidDataContainer; + private ImageView mShowBroadcastCapabilities; + private ImageView mEditSlot; + private ImageView mEditAdvInterval; + private ImageView mEditRadioTxPower; + private ImageView mShowSlotInfo; + private TextView mFrameTypeView; + private Spinner mActiveSlots; + private TextView mNamespaceId; + private TextView mInstanceId; + private TextView mUrl; + private TextView mEtlm; + private TextView mEtlmSalt; + private TextView mEtlmMessageIntCheck; + private TextView mVoltage; + private TextView mTemperature; + private TextView mPduCount; + private TextView mTimeSinceReboot; + private TextView mTimerExponent; + private TextView mClockValue; + private TextView mEid; + private TextView mAdvertisingInterval; + private TextView mRadioTxPower; + + private UpdateService.ServiceBinder mBinder; + private boolean mBounnd; + private ProximityBeaconImpl mProximityApiClient; + private UnlockBeaconDialogFragment mUnlockBeaconDialogFragment = null; + private boolean mIsBeaconLocked = true; + private byte[] mBroadcastCapabilities; + private byte[] mRwAdvertisingSlot; + private ArrayList mMaxSupportedSlots; + private ArrayAdapter mMaxActiveSlotsAdapter; + private int mActiveSlot; + private boolean mIsActiveSlotAdapterUpdated = false; + private int mCurrentLockState; + private EddystoneEidrGenerator generator; + private byte[] mUnlockCode; + private ProgressDialog mProgressDialog; + private int mFrameType; + private byte[] mRadioTxPowerData; + private byte[] mDecryptedIdentityKey; + private byte[] mEncryptedIdentityKey; + private byte[] mServiceEcdhKey; + private byte[] mBeaconPublicEcdhKey = null; + private Handler mProgressDialogHandler; + private String mBeaconEcdhPrivateKey; + private boolean mEikGenerated = false; + private int mAdvancedAdvTxPower; + private String mAccountName; + private ArrayList mActiveSlotsTypes; + private boolean mRemainConnectable = false; + private byte[] mUidForEid; + private Context mContext; + + public void ensurePermissionGranted(final String[] permissions) { + ensurePermission(permissions); + } + + private ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(final ComponentName name, final IBinder service) { + final UpdateService.ServiceBinder binder = mBinder = (UpdateService.ServiceBinder) service; + final int state = binder.getState(); + switch (state) { + case UpdateService.STATE_DISCONNECTED: + binder.connect(); + break; + case UpdateService.STATE_CONNECTED: + if (!hasOptionsMenu()) { + setHasOptionsMenu(true); + getActivity().invalidateOptionsMenu(); + } + mConnectButton.setText(R.string.action_disconnect); + //mBinder.startReadingCharacteristicsForActiveSlot(); + final Integer lockState = binder.getLockState(); + if (lockState != null) + updateUiForBeacons(BluetoothGatt.STATE_CONNECTED, lockState); + + mActiveSlotsTypes = binder.getAllSlotInformation(); + + mBroadcastCapabilities = mBinder.getBroadcastCapabilities(); + if (mBroadcastCapabilities != null) { + Log.v("BEACON", "Broadcast capabilities"); + int mMaxSupportedSlots = ParserUtils.getIntValue(mBroadcastCapabilities, 1, BluetoothGattCharacteristic.FORMAT_UINT8); + updateActiveSlotSpinner(mMaxSupportedSlots); + } + + mActiveSlot = binder.getActiveSlot(); + if (mActiveSlot > -1) { + mActiveSlots.setSelection(mActiveSlot); + } + + final Integer advertisingInterval = binder.getAdvInterval(); + if (advertisingInterval != null) + mAdvertisingInterval.setText(String.valueOf(advertisingInterval)); + + final Integer radioTxPower = binder.getRadioTxPower(); + if (radioTxPower != null) + mRadioTxPower.setText(String.valueOf(radioTxPower)); + + final Integer advanceAdvInterval = binder.getAdvancedAdvertisedTxPower(); + if (advanceAdvInterval != null) { + }//update ui + + final byte[] beaconPublicEcdhKey = binder.getBeaconPublicEcdhKey(); + if (beaconPublicEcdhKey != null && beaconPublicEcdhKey.length == 32) { + final String ecdhKey = ParserUtils.bytesToHex(beaconPublicEcdhKey, 0, 32, false); + mBeaconPublicEcdhKey = new byte[32]; + ParserUtils.setByteArrayValue(mBeaconPublicEcdhKey, 0, ecdhKey); + } + + final byte[] encryptedIdentityKey = binder.getIdentityKey(); + if (encryptedIdentityKey != null && encryptedIdentityKey.length == 16) { + mEncryptedIdentityKey = encryptedIdentityKey; + mUnlockCode = binder.getBeaconLockCode(); + if (mUnlockCode != null) { + ParserUtils.aes128decrypt(encryptedIdentityKey, new SecretKeySpec(mUnlockCode, "AES")); + mDecryptedIdentityKey = encryptedIdentityKey; + } + } + + final byte[] readWriteAdvSlot = binder.getReadWriteAdvSlotData(); + if (readWriteAdvSlot != null && readWriteAdvSlot.length > 0) { + mRwAdvertisingSlot = readWriteAdvSlot; + mFrameType = ParserUtils.getIntValue(readWriteAdvSlot, 0, BluetoothGattCharacteristic.FORMAT_UINT8); + updateUiWithFrameType(readWriteAdvSlot); + } + + } + } + + @Override + public void onServiceDisconnected(final ComponentName name) { + mBinder = null; + mIsActiveSlotAdapterUpdated = false; + } + }; + + private BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(final Context context, final Intent intent) { + final Activity activity = getActivity(); + if (activity == null || !isResumed()) + return; + + final String action = intent.getAction(); + + if (UpdateService.ACTION_STATE_CHANGED.equals(action)) { + final int state = intent.getIntExtra(UpdateService.EXTRA_DATA, UpdateService.STATE_DISCONNECTED); + + switch (state) { + case UpdateService.STATE_DISCONNECTED: + mConnectButton.setText(R.string.action_connect); + mConnectButton.setEnabled(true); + + final Intent service = new Intent(activity, UpdateService.class); + if(mBounnd) + activity.unbindService(mServiceConnection); + activity.stopService(service); + mBinder = null; + mBounnd = false; + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.dismiss(); + mProgressDialogHandler.removeCallbacks(mRunnableHandler); + } + mEikGenerated = false; + mIsBeaconLocked = true; + updateUiForBeacons(UpdateService.STATE_DISCONNECTED, UpdateService.LOCKED); + break; + case UpdateService.STATE_CONNECTED: + mConnectButton.setText(R.string.action_disconnect); + mConnectButton.setEnabled(true); + break; + case UpdateService.STATE_DISCONNECTING: + case UpdateService.STATE_CONNECTING: + mConnectButton.setEnabled(false); + break; + } + } else if (UpdateService.ACTION_UNLOCK_BEACON.equals(action)) { + Log.v(TAG, "challenge Broadcast received in fragment: " + action); + final byte[] challenge = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + if (challenge != null && challenge.length == 16) { + if (mProgressDialog != null && mProgressDialog.isShowing()) { + //mProgressDialog.dismiss(); + mProgressDialog.setMessage(getString(R.string.reading_all_slots)); + mProgressDialogHandler.removeCallbacks(mRunnableHandler); + } + mUnlockBeaconDialogFragment = UnlockBeaconDialogFragment.newInstance(challenge); + mUnlockBeaconDialogFragment.show(getChildFragmentManager(), null); + } + } else if (UpdateService.ACTION_BROADCAST_CAPABILITIES.equals(action)) { + /*final UUID uuid = ((ParcelUuid) intent.getParcelableExtra(UpdateService.EXTRA_DATA)).getUuid(); + mUuidView.setText(uuid.toString()); + setUuidControlsEnabled(true);*/ + mBroadcastCapabilities = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + if (mBroadcastCapabilities != null) { + Log.v("BEACON", "Broadcast capabilities"); + int mMaxSupportedSlots = ParserUtils.getIntValue(mBroadcastCapabilities, 1, BluetoothGattCharacteristic.FORMAT_UINT8); + updateActiveSlotSpinner(mMaxSupportedSlots); + } + } else if (UpdateService.ACTION_ACTIVE_SLOT.equals(action)) { + mActiveSlot = intent.getIntExtra(UpdateService.EXTRA_DATA, 0); + Log.v("BEACON", "Active slot: " + mActiveSlot); + } else if (UpdateService.ACTION_ADVERTISING_INTERVAL.equals(action)) { + final int advInterval = intent.getIntExtra(UpdateService.EXTRA_DATA, 0); + mAdvertisingInterval.setText(String.valueOf(advInterval) + " ms"); + } else if (UpdateService.ACTION_RADIO_TX_POWER.equals(action)) { + final byte[] radioTxPower = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + mRadioTxPowerData = radioTxPower; + mRadioTxPower.setText(ParserUtils.parse(radioTxPower, 0, radioTxPower.length, getString(R.string.update_rssi_unit))); + } else if (UpdateService.ACTION_ADVANCED_ADVERTISED_TX_POWER.equals(action)) { + mAdvancedAdvTxPower = intent.getIntExtra(UpdateService.EXTRA_DATA, 0); + } else if (UpdateService.ACTION_LOCK_STATE.equals(action)) { + updateUiForBeacons(BluetoothProfile.STATE_CONNECTED, intent.getIntExtra(UpdateService.EXTRA_DATA, 0)); + } else if (UpdateService.ACTION_UNLOCK.equals(action)) { + final byte[] data = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + } else if (UpdateService.ACTION_ECDH_KEY.equals(action)) { + final byte[] data = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + if (!mEikGenerated && data.length == 32) { + final String ecdhKey = ParserUtils.bytesToHex(data, 0, 32, false); + mBeaconPublicEcdhKey = new byte[32]; + ParserUtils.setByteArrayValue(mBeaconPublicEcdhKey, 0, ecdhKey); + } + } else if (UpdateService.ACTION_EID_IDENTITY_KEY.equals(action)) { + byte[] data = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + mEncryptedIdentityKey = data; + if(mUnlockCode != null) { + data = ParserUtils.aes128decrypt(data, new SecretKeySpec(mUnlockCode, "AES")); + mDecryptedIdentityKey = data; + } else { + if (mBinder != null ){ + mUnlockCode = mBinder.getBeaconLockCode(); + data = ParserUtils.aes128decrypt(data, new SecretKeySpec(mUnlockCode, "AES")); + mDecryptedIdentityKey = data; + } + } + } else if (UpdateService.ACTION_READ_WRITE_ADV_SLOT.equals(action)) { + if (mProgressDialog != null && mProgressDialog.isShowing()) + mProgressDialog.dismiss(); + mFrameType = intent.getIntExtra(UpdateService.EXTRA_FRAME_TYPE, -1); + updateUiWithFrameType(intent); + } else if (UpdateService.ACTION_ADVANCED_FACTORY_RESET.equals(action)) { + final byte[] data = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + } else if (UpdateService.ACTION_ADVANCED_REMAIN_CONNECTABLE.equals(action)) { + mRemainConnectable = intent.getExtras().getBoolean(UpdateService.EXTRA_DATA); + } else if (UpdateService.ACTION_BROADCAST_ALL_SLOT_INFO.equals(action)) { + mActiveSlotsTypes = intent.getStringArrayListExtra(UpdateService.EXTRA_DATA); + ensurePermission(new String [] {Manifest.permission.GET_ACCOUNTS}); + Log.v(TAG, "SLot info list size: " + mActiveSlotsTypes.size()); + } else if (UpdateService.ACTION_DONE.equals(action)) { + final boolean advanced = intent.getBooleanExtra(UpdateService.EXTRA_DATA, false); + mBinder.read(); + } else if (UpdateService.ACTION_GATT_ERROR.equals(action)) { + final int error = intent.getIntExtra(UpdateService.EXTRA_DATA, 0); + switch (error) { + case UpdateService.ERROR_UNSUPPORTED_DEVICE: + Toast.makeText(activity, R.string.update_error_device_not_supported, Toast.LENGTH_SHORT).show(); + break; + default: + Toast.makeText(activity, getString(R.string.update_error_other, error), Toast.LENGTH_SHORT).show(); + break; + } + mBinder.disconnectAndClose(); + } + } + }; + + private void updateUiWithFrameType(Intent intent) { + switch (mFrameType) { + case TYPE_UID: + mFrameTypeView.setText(getString(R.string.type_uid)); + final String namespaceId = intent.getExtras().getString(UpdateService.EXTRA_NAMESPACE_ID, ""); + final String instanceId = intent.getExtras().getString(UpdateService.EXTRA_INSTANCE_ID, ""); + mRwAdvertisingSlot = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + mUidDataContainer.setVisibility(View.VISIBLE); + mUrlDataContainer.setVisibility(View.GONE); + mTlmDataContainer.setVisibility(View.GONE); + mEtlmDataContainer.setVisibility(View.GONE); + mEidDataContainer.setVisibility(View.GONE); + mNamespaceId.setText(namespaceId); + mInstanceId.setText(instanceId); + break; + + case TYPE_URL: + mFrameTypeView.setText(getString(R.string.type_url)); + final String url = intent.getExtras().getString(UpdateService.EXTRA_URL, ""); + mRwAdvertisingSlot = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + mUrlDataContainer.setVisibility(View.VISIBLE); + mUidDataContainer.setVisibility(View.GONE); + mTlmDataContainer.setVisibility(View.GONE); + mEtlmDataContainer.setVisibility(View.GONE); + mEidDataContainer.setVisibility(View.GONE); + + final SpannableString urlAttachment = new SpannableString(url); + urlAttachment.setSpan(new UnderlineSpan(), 0, url.length(), 0); + mUrl.setText(urlAttachment); + //mUrl.setText(url); + break; + + case TYPE_TLM: + mEidDataContainer.setVisibility(View.GONE); + mUrlDataContainer.setVisibility(View.GONE); + mUidDataContainer.setVisibility(View.GONE); + + mRwAdvertisingSlot = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + final boolean containsEid = mActiveSlotsTypes.contains(getString(R.string.type_eid)); + if (containsEid) { + mEtlmDataContainer.setVisibility(View.VISIBLE); + mFrameTypeView.setText(getString(R.string.type_etlm)); + final String etlm = ParserUtils.bytesToHex(mRwAdvertisingSlot, 2, 12, true); + final String salt = ParserUtils.bytesToHex(mRwAdvertisingSlot, 14, 2, true); + final String messageIntegrityCheck = ParserUtils.bytesToHex(mRwAdvertisingSlot, 16, 2, true); + + mEtlm.setText(etlm); + mEtlmSalt.setText(salt); + mEtlmMessageIntCheck.setText(messageIntegrityCheck); + } else { + mFrameTypeView.setText(getString(R.string.type_tlm)); + final String batteryVoltage = intent.getExtras().getString(UpdateService.EXTRA_VOLTAGE, ""); + final String beaconTemperature = intent.getExtras().getString(UpdateService.EXTRA_BEACON_TEMPERATURE, ""); + final String pduCount = intent.getExtras().getString(UpdateService.EXTRA_PDU_COUNT, ""); + final String timeSinceBoot = intent.getExtras().getString(UpdateService.EXTRA_TIME_SINCE_BOOT, ""); + + mTlmDataContainer.setVisibility(View.VISIBLE); + mVoltage.setText(batteryVoltage); + mTemperature.setText(beaconTemperature); + mPduCount.setText(pduCount); + mTimeSinceReboot.setText(timeSinceBoot); + } + break; + + case TYPE_EID: + mFrameTypeView.setText(getString(R.string.type_eid)); + final String timerExponent = intent.getExtras().getString(UpdateService.EXTRA_TIMER_EXPONENT); + final String clockValue = intent.getExtras().getString(UpdateService.EXTRA_CLOCK_VALUE); + final String eid = intent.getExtras().getString(UpdateService.EXTRA_EID, ""); + mRwAdvertisingSlot = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + + mEidDataContainer.setVisibility(View.VISIBLE); + mUrlDataContainer.setVisibility(View.GONE); + mUidDataContainer.setVisibility(View.GONE); + mTlmDataContainer.setVisibility(View.GONE); + mEtlmDataContainer.setVisibility(View.GONE); + mTimerExponent.setText(timerExponent); + mClockValue.setText(clockValue); + mEid.setText(eid); + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.dismiss(); + mProgressDialogHandler.removeCallbacks(mRunnableHandler); + } + break; + case EMPTY_SLOT: + mFrameTypeView.setText(getString(R.string.slot_state_empty)); + mRwAdvertisingSlot = intent.getByteArrayExtra(UpdateService.EXTRA_DATA); + mUrlDataContainer.setVisibility(View.GONE); + mUidDataContainer.setVisibility(View.GONE); + mTlmDataContainer.setVisibility(View.GONE); + mEidDataContainer.setVisibility(View.GONE); + break; + } + } + + private void updateUiWithFrameType(final byte[] readWriteAdvSlot) { + switch (mFrameType) { + case TYPE_UID: + mFrameTypeView.setText(getString(R.string.type_uid)); + final String namespaceId = ParserUtils.bytesToHex(readWriteAdvSlot, 2, 10, true); + final String instanceId = ParserUtils.bytesToHex(readWriteAdvSlot, 12, 6, true); + mUidDataContainer.setVisibility(View.VISIBLE); + mUrlDataContainer.setVisibility(View.GONE); + mTlmDataContainer.setVisibility(View.GONE); + mEtlmDataContainer.setVisibility(View.GONE); + mEidDataContainer.setVisibility(View.GONE); + mNamespaceId.setText(namespaceId); + mInstanceId.setText(instanceId); + break; + + case TYPE_URL: + mFrameTypeView.setText(getString(R.string.type_url)); + final String url = ParserUtils.decodeUri(readWriteAdvSlot, 2, readWriteAdvSlot.length - 2); + mUrlDataContainer.setVisibility(View.VISIBLE); + mUidDataContainer.setVisibility(View.GONE); + mTlmDataContainer.setVisibility(View.GONE); + mEtlmDataContainer.setVisibility(View.GONE); + mEidDataContainer.setVisibility(View.GONE); + + final SpannableString urlAttachment = new SpannableString(url); + urlAttachment.setSpan(new UnderlineSpan(), 0, url.length(), 0); + mUrl.setText(urlAttachment); + //mUrl.setText(url); + break; + + case TYPE_TLM: + mEidDataContainer.setVisibility(View.GONE); + mUrlDataContainer.setVisibility(View.GONE); + mUidDataContainer.setVisibility(View.GONE); + final boolean containsEid = mActiveSlotsTypes.contains(getString(R.string.type_eid)); + if(containsEid){ + mEtlmDataContainer.setVisibility(View.VISIBLE); + mFrameTypeView.setText(getString(R.string.type_etlm)); + final String etlm = ParserUtils.bytesToHex(readWriteAdvSlot, 2, 12, true); + final String salt = ParserUtils.bytesToHex(readWriteAdvSlot, 14, 2, true); + final String messageIntegrityCheck = ParserUtils.bytesToHex(readWriteAdvSlot, 16, 2, true); + + mEtlm.setText(etlm); + mEtlmSalt.setText(salt); + mEtlmMessageIntCheck.setText(messageIntegrityCheck); + + + } else { + mFrameTypeView.setText(getString(R.string.type_tlm)); + mTlmDataContainer.setVisibility(View.VISIBLE); + final int voltage = ParserUtils.decodeUint16BigEndian(readWriteAdvSlot, 2); + if (voltage > 0) { + mVoltage.setText(String.valueOf(voltage)); + } else { + mVoltage.setText(getString(R.string.batt_voltage_unsupported)); + } + + final float temp = ParserUtils.decode88FixedPointNotation(readWriteAdvSlot, 4); + if (temp > -128.0f) + mTemperature.setText(String.valueOf(temp)); + else + mTemperature.setText(getString(R.string.temperature_unsupported)); + + final String pduCount = String.valueOf(ParserUtils.decodeUint32BigEndian(readWriteAdvSlot, 6)); + final String timeSinceBoot = String.valueOf(ParserUtils.decodeUint32BigEndian(readWriteAdvSlot, 10) * 100); + + mPduCount.setText(pduCount); + mTimeSinceReboot.setText(timeSinceBoot); + } + + break; + + case TYPE_EID: + mFrameTypeView.setText(getString(R.string.type_eid)); + final String timerExponent = String.valueOf(ParserUtils.getIntValue(readWriteAdvSlot, 1, BluetoothGattCharacteristic.FORMAT_UINT8)); + final String clockValue = String.valueOf(ParserUtils.getIntValue(readWriteAdvSlot, 2, ParserUtils.FORMAT_UINT32_BIG_INDIAN)); + final String eid = String.valueOf(ParserUtils.bytesToHex(readWriteAdvSlot, 6, 8, true)); + mEidDataContainer.setVisibility(View.VISIBLE); + mUrlDataContainer.setVisibility(View.GONE); + mUidDataContainer.setVisibility(View.GONE); + mTlmDataContainer.setVisibility(View.GONE); + mEtlmDataContainer.setVisibility(View.GONE); + mTimerExponent.setText(timerExponent); + mClockValue.setText(clockValue); + mEid.setText(eid); + break; + case EMPTY_SLOT: + mFrameTypeView.setText(getString(R.string.slot_state_empty)); + mUrlDataContainer.setVisibility(View.GONE); + mUidDataContainer.setVisibility(View.GONE); + mTlmDataContainer.setVisibility(View.GONE); + mEtlmDataContainer.setVisibility(View.GONE); + mEidDataContainer.setVisibility(View.GONE); + break; + } + } + + private void updateActiveSlotSpinner(int maxSupportedSlots) { + mMaxSupportedSlots = new ArrayList<>(); + + for (int i = 0; i < maxSupportedSlots; i++) { + mMaxSupportedSlots.add("Slot " + i); + } + + mMaxActiveSlotsAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, mMaxSupportedSlots); + mMaxActiveSlotsAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mIsActiveSlotAdapterUpdated = true; + mActiveSlots.setAdapter(mMaxActiveSlotsAdapter); + } + + @Override + public void onStart() { + super.onStart(); + + // This will connect to the service only if it's already running + final Activity activity = getActivity(); + final Intent service = new Intent(activity, UpdateService.class); + mBounnd = activity.bindService(service, mServiceConnection, 0); + } + + @Override + public void onStop() { + super.onStop(); + + if (mBounnd) + getActivity().unbindService(mServiceConnection); + } + + @Override + public void onDestroy() { + super.onDestroy(); + + if (getActivity().isFinishing()) { + final Activity activity = getActivity(); + final Intent service = new Intent(activity, UpdateService.class); + activity.stopService(service); + } + + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.dismiss(); + } + + final MainActivity parent = (MainActivity) mContext; + parent.setBeaconsFragment(null); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + mContext = context; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + final MainActivity parent = (MainActivity) mContext; + parent.setUPdateFragment(this); + } + + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { + final View view = inflater.inflate(R.layout.fragment_update, container, false); + mProgressDialogHandler = new Handler(); + mBeaconConfigurationContainer = (LinearLayout) view.findViewById(R.id.beacon_configuration_container); + mFrameTypeContainer = (LinearLayout) view.findViewById(R.id.frame_type_container); + mFrameTypeView = (TextView) view.findViewById(R.id.frame_type); + mFrameTypeContainer = (LinearLayout) view.findViewById(R.id.frame_type_container); + mUidDataContainer = (LinearLayout) view.findViewById(R.id.uid_data_container); + mUrlDataContainer = (LinearLayout) view.findViewById(R.id.url_data_container); + mTlmDataContainer = (LinearLayout) view.findViewById(R.id.tlm_data_container); + mEtlmDataContainer= (LinearLayout) view.findViewById(R.id.etlm_data_container); + mEidDataContainer = (LinearLayout) view.findViewById(R.id.eid_data_container); + mEditSlot = (ImageView) view.findViewById(R.id.edit_slot); + mEditAdvInterval = (ImageView) view.findViewById(R.id.edit_adv_interval); + mShowBroadcastCapabilities = (ImageView) view.findViewById(R.id.show_broadcast_capabilities); + mShowSlotInfo = (ImageView) view.findViewById(R.id.show_slot_info); + mEditRadioTxPower = (ImageView) view.findViewById(R.id.edit_radio_tx_power); + mActiveSlots = (Spinner) view.findViewById(R.id.active_slots); + mNamespaceId = (TextView) view.findViewById(R.id.namespace_id); + mInstanceId = (TextView) view.findViewById(R.id.instance_id); + mUrl = (TextView) view.findViewById(R.id.url_data); + mEtlm = (TextView) view.findViewById(R.id.etlm_data); + mEtlmSalt = (TextView) view.findViewById(R.id.etlm_salt); + mEtlmMessageIntCheck = (TextView) view.findViewById(R.id.etlm_message_integrity_check); + mVoltage = (TextView) view.findViewById(R.id.voltage); + mTemperature = (TextView) view.findViewById(R.id.temperature); + mPduCount = (TextView) view.findViewById(R.id.advertiser_count); + mTimeSinceReboot = (TextView) view.findViewById(R.id.time_since_boot); + mTimerExponent = (TextView) view.findViewById(R.id.timer_exponent); + mClockValue = (TextView) view.findViewById(R.id.clock_value); + mEid = (TextView) view.findViewById(R.id.eid); + mAdvertisingInterval = (TextView) view.findViewById(R.id.adv_interval_ms); + mRadioTxPower = (TextView) view.findViewById(R.id.radio_tx_power); + mBeaconHelp = (TextView) view.findViewById(R.id.beacon_update_help); + mProgressDialog = new ProgressDialog(getActivity()); + mProgressDialog.setCancelable(false); + mProgressDialog.setCanceledOnTouchOutside(false); + + initDataFromSharedPrefs(); + // Configure the CONNECT / DISCONNECT button + + final Button connectButton = mConnectButton = (Button) view.findViewById(R.id.action_connect); + connectButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(final View v) { + + if (mBinder == null) { + if(isBleEnabled()) { + if(isLocationEnabled()) { + final ScannerFragment scannerFragment = ScannerFragment.getInstance(EDDYSTONE_GATT_CONFIG_SERVICE_UUID); + scannerFragment.show(getChildFragmentManager(), null); + } else { + showToast("Please enable location services to scan for devices"); + } + } else { + enableBle(); + } + } else { + mBinder.disconnectAndClose(); + updateUiForBeacons(BluetoothProfile.STATE_DISCONNECTED, UpdateService.LOCKED); + + } + } + }); + + mShowBroadcastCapabilities.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final BroadcastCapabilitesDialogFragment broadcastCapabilitesDialogFragment = BroadcastCapabilitesDialogFragment.newInstance(mBroadcastCapabilities); + broadcastCapabilitesDialogFragment.show(getChildFragmentManager(), null); + } + }); + + mShowSlotInfo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final AllSlotInfoDialogFragment m = AllSlotInfoDialogFragment.newInstance(mActiveSlotsTypes); + m.show(getChildFragmentManager(), null); + } + }); + + mEditSlot.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final ReadWriteAdvertisementSlotDialogFragment dialogFragment = ReadWriteAdvertisementSlotDialogFragment.newInstance(false, mActiveSlot, mRwAdvertisingSlot); + dialogFragment.show(getChildFragmentManager(), null); + } + }); + + mEditRadioTxPower.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final RadioTxPowerDialogFragment dialogFragment = RadioTxPowerDialogFragment.newInstance(ParserUtils.parse(mRadioTxPowerData, 0, mRadioTxPowerData.length, "").trim(), false); + dialogFragment.show(getChildFragmentManager(), null); + } + }); + + mEditAdvInterval.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + final AdvertisingIntervalDialogFragment dialogFragment = AdvertisingIntervalDialogFragment.newInstance(mAdvertisingInterval.getText().toString().trim()); + dialogFragment.show(getChildFragmentManager(), null); + } + }); + + mActiveSlots.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + final byte[] data = new byte[1]; + data[0] = (byte) position; + if (mIsActiveSlotAdapterUpdated) + mIsActiveSlotAdapterUpdated = false; + else { + mEikGenerated = false; + mBinder.changeToSelectedActiveSlot(data); + } + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }); + + mUrl.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(mUrl.getText().toString())); + getActivity().startActivity(browserIntent); + } + }); + + return view; + } + + private boolean isVariableAdvertisingSupported() { + final int capabilities = ParserUtils.getIntValue(mBroadcastCapabilities, 3, BluetoothGattCharacteristic.FORMAT_UINT8); + + return (capabilities & IS_VARIABLE_TX_POWER_SUPPORTED) > 0; + } + + private void initDataFromSharedPrefs() { + final SharedPreferences sharedPreferences = getActivity().getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE); + final String serviceEcdhKey = sharedPreferences.getString(SERVICE_ECDH_KEY, ""); + if (!serviceEcdhKey.isEmpty()) { + mServiceEcdhKey = new byte[32]; + ParserUtils.setByteArrayValue(mServiceEcdhKey, 0, serviceEcdhKey); + } + } + + @Override + public void onViewCreated(final View view, final Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + setHasOptionsMenu(false); + + LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mServiceBroadcastReceiver, createIntentFilters()); + } + + + @Override + public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { + inflater.inflate(R.menu.menu_update, menu); + } + + @Override + public boolean onOptionsItemSelected(final MenuItem item) { + final int id = item.getItemId(); + RegisterBeaconDialogFragment registerBeaconDialogFragment; + switch (id) { + case R.id.action_about: + /*final BoardHelpFragment helpFragment = BoardHelpFragment.getInstance(BoardHelpFragment.MODE_UPDATE); + helpFragment.show(getChildFragmentManager(), null);*/ + return true; + case R.id.action_clear_slot: + ClearSlotDialogFragment clearSlotDialogFragment = ClearSlotDialogFragment.newInstance(); + clearSlotDialogFragment.show(getChildFragmentManager(), null); + return true; + case R.id.action_refresh_slot: + if (mBinder != null) { + if (mProgressDialog != null) { + mProgressDialog.setTitle(getString(R.string.prog_dialog_reading)); + mProgressDialog.setMessage(getString(R.string.prog_dialog_rw_adv_slot_msg)); + mProgressDialog.show(); + mProgressDialogHandler.postDelayed(mRunnableHandler, 10000); + } + mBinder.startReadingCharacteristicsForActiveSlot(); + } + return true; + case R.id.action_lock: + if (!mIsBeaconLocked) { + LockStateDialogFragment lockStateDialogFragment = LockStateDialogFragment.newInstance(mCurrentLockState, mUnlockCode); + lockStateDialogFragment.show(getChildFragmentManager(), null); + } else { + Toast.makeText(getActivity(), getString(R.string.unlock_beacon_error), Toast.LENGTH_LONG).show(); + } + return true; + case R.id.action_ecdh_info: + if (mBeaconPublicEcdhKey != null) { + EcdhKeyInfoDialogFragment ecdhKeyInfoDialogFragment = EcdhKeyInfoDialogFragment.newInstance(mActiveSlot, mFrameType, + ParserUtils.bytesToHex(mBeaconPublicEcdhKey, 0, 32, true), ParserUtils.bytesToHex(mEncryptedIdentityKey, 0, 16, true), + ParserUtils.bytesToHex(mDecryptedIdentityKey, 0, 16, true)); + ecdhKeyInfoDialogFragment.show(getChildFragmentManager(), null); + } else { + ErrorDialogFragment errorDialogFragment = ErrorDialogFragment.newInstance(getString(R.string.error_no_ecdh_info)); + errorDialogFragment.show(getChildFragmentManager(), null); + } + break; + case R.id.action_register_beacons: + if(mFrameTypeView.getText().toString().equals("EMPTY")){ + return true; + } + switch (mFrameType) { + case TYPE_UID: + registerUidBeacon(); + return true; + case TYPE_EID: + registerBeaconDialogFragment = RegisterBeaconDialogFragment.newInstance(); + registerBeaconDialogFragment.show(getChildFragmentManager(), null); + //registerEidBeacon(); + return true; + default: + final String message = "Cannot register URL/TLM/eTLM beacon type"; + showToast(message); + return true; + + } + + case R.id.action_adv_advertised_tx_power: + RadioTxPowerDialogFragment dialogFragment = RadioTxPowerDialogFragment.newInstance(String.valueOf(mAdvancedAdvTxPower), true); + dialogFragment.show(getChildFragmentManager(), null); + break; + case R.id.action_remain_connectable: + RemainConnectableDialogFragment remainConnectableDialogFragment = RemainConnectableDialogFragment.newInstance(mRemainConnectable); + remainConnectableDialogFragment.show(getChildFragmentManager(), null); + break; + } + return false; + } + + private IntentFilter createIntentFilters() { + final IntentFilter filter = new IntentFilter(); + filter.addAction(UpdateService.ACTION_STATE_CHANGED); + filter.addAction(UpdateService.ACTION_DONE); + filter.addAction(UpdateService.ACTION_GATT_ERROR); + filter.addAction(UpdateService.ACTION_UNLOCK_BEACON); + filter.addAction(UpdateService.ACTION_BROADCAST_CAPABILITIES); + filter.addAction(UpdateService.ACTION_ACTIVE_SLOT); + filter.addAction(UpdateService.ACTION_ADVERTISING_INTERVAL); + filter.addAction(UpdateService.ACTION_RADIO_TX_POWER); + filter.addAction(UpdateService.ACTION_ADVANCED_ADVERTISED_TX_POWER); + filter.addAction(UpdateService.ACTION_LOCK_STATE); + filter.addAction(UpdateService.ACTION_UNLOCK); + filter.addAction(UpdateService.ACTION_ECDH_KEY); + filter.addAction(UpdateService.ACTION_EID_IDENTITY_KEY); + filter.addAction(UpdateService.ACTION_READ_WRITE_ADV_SLOT); + filter.addAction(UpdateService.ACTION_ADVANCED_FACTORY_RESET); + filter.addAction(UpdateService.ACTION_ADVANCED_REMAIN_CONNECTABLE); + filter.addAction(UpdateService.ACTION_BROADCAST_ALL_SLOT_INFO); + Log.v(TAG, "Intent filters created"); + return filter; + } + + private void registerEidBeacon(final byte[] uid) { + final JSONObject jBody = createEidBeaconJson(uid); + if (jBody != null) { + if (mProximityApiClient != null) { + if (NetworkUtils.checkNetworkConnectivity(getActivity())) { + if (mProgressDialog != null) { + mProgressDialog.setTitle("Registering EID Beacon"); + mProgressDialog.setMessage("Please wait while the EID beacon is registered in the proximity API"); + mProgressDialog.show(); + mProgressDialogHandler.postDelayed(mRunnableHandler, 10000); + } + mProximityApiClient.registerBeacon(beaconRegistrationCallback, jBody); + } else showToast(getString(R.string.check_internet_connectivity)); + } else { + ensurePermission(new String[]{Manifest.permission.GET_ACCOUNTS}); + } + } else showToast(getString(R.string.service_ecdh_missing)); + } + + private void registerUidBeacon() { + final JSONObject jBody = createUidBeaconJson(); + if (jBody != null) + if (mProximityApiClient != null) { + if (NetworkUtils.checkNetworkConnectivity(getActivity())) { + authoriseAccount(getUserAccount()); + if (mProgressDialog != null) { + mProgressDialog.setTitle("Registering UID Beacon"); + mProgressDialog.setMessage("Please wait while the EID beacon is registered in the proximity API"); + mProgressDialog.show(); + mProgressDialogHandler.postDelayed(mRunnableHandler, 10000); + } + mProximityApiClient.registerBeacon(beaconRegistrationCallback, jBody); + } else showToast(getString(R.string.check_internet_connectivity)); + } else { + ensurePermission(new String[]{Manifest.permission.GET_ACCOUNTS}); + } + } + + private JSONObject createEidBeaconJson(final byte[] uid) { + + JSONObject body; + try { + body = new JSONObject(); + + JSONObject advertisedId = new JSONObject() + .put("type", "EDDYSTONE") + .put("id", ParserUtils.base64Encode(uid)); + body.put("advertisedId", advertisedId); + + body.put("status", "ACTIVE"); + + // TODO: encode the remaining beacon parameters like location, description, etc. + // https://developers.google.com/beacons/proximity/reference/rest/v1beta1/beacons#Beacon + if (mServiceEcdhKey == null) { + return null; + } + String beaconEcdhPublicKey = ParserUtils.base64Encode(mBeaconPublicEcdhKey); + String serviceEcdhPublicKey = ParserUtils.base64Encode(mServiceEcdhKey); + + final byte[] eidr = new byte[8]; + ParserUtils.setByteArrayValue(eidr, 0, mEid.getText().toString().trim().replace("0x", "")); + String initialEidr = ParserUtils.base64Encode(eidr); + + JSONObject ephemeralIdRegistration = new JSONObject() + .put("beaconEcdhPublicKey", beaconEcdhPublicKey) + .put("serviceEcdhPublicKey", serviceEcdhPublicKey) + .put("rotationPeriodExponent", mTimerExponent.getText().toString()) + .put("initialClockValue", mClockValue.getText().toString()) + .put("initialEid", initialEidr); + body.put("ephemeralIdRegistration", ephemeralIdRegistration); + + Log.d(TAG, "request:" + body.toString(2)); + } catch (JSONException e) { + //logAndShowToast("JSONException building request body", e); + return null; + } + return body; + } + + private JSONObject createUidBeaconJson() { + + JSONObject body; + try { + body = new JSONObject(); + String namespaceId = mNamespaceId.getText().toString().trim(); + String instanceId = mInstanceId.getText().toString().trim(); + if (namespaceId.startsWith("0x")) + namespaceId = namespaceId.substring(2, namespaceId.length()); + + if (instanceId.startsWith("0x")) + instanceId = instanceId.substring(2, instanceId.length()); + + final String uid = namespaceId + instanceId; + + JSONObject advertisedId = new JSONObject() + .put("type", "EDDYSTONE") + .put("id", ParserUtils.base64Encode(uid)); + body.put("advertisedId", advertisedId); + + body.put("status", "ACTIVE"); + + Log.d(TAG, "request:" + body.toString(2)); + } catch (JSONException e) { + //logAndShowToast("JSONException building request body", e); + return null; + } + return body; + } + + Callback beaconRegistrationCallback = new Callback() { + @Override + public void onFailure(Request request, IOException e) { + + } + + @Override + public void onResponse(Response response) throws IOException { + + try { + mProgressDialog.dismiss(); + mProgressDialogHandler.removeCallbacks(mRunnableHandler); + String body = response.body().string(); + final JSONObject jsonResponse = new JSONObject(body); + if (!response.isSuccessful()) { + final JSONObject jsonError = jsonResponse.getJSONObject("error"); + final int errorCode = jsonError.getInt("code"); + final String message = jsonError.getString("message"); + ProximityApiErrorDialogFragment errorDialogFragment; + switch (errorCode) { + case ERROR_ALREADY_EXISTS: + errorDialogFragment = ProximityApiErrorDialogFragment.newInstance(String.valueOf(errorCode), message, getString(R.string.error_beacon_already_exists)); + errorDialogFragment.show(getChildFragmentManager(), null); + break; + case ERROR_UNAUTHORIZED: + errorDialogFragment = ProximityApiErrorDialogFragment.newInstance(String.valueOf(errorCode), message, "Unable to register beacon"); + errorDialogFragment.show(getChildFragmentManager(), null); + Account userAccount = getUserAccount(); + if(userAccount != null) + new AuthorizedServiceTask(getActivity(), userAccount, AUTH_SCOPE_PROXIMITY_API).execute(); + break; + + case 403: + default: + errorDialogFragment = ProximityApiErrorDialogFragment.newInstance(String.valueOf(errorCode), "Unknown error", "Unable to register beacon"); + errorDialogFragment.show(getChildFragmentManager(), null); + break; + } + return; + } + showToast(getString(R.string.registration_success)); + + final String beaconName = jsonResponse.getString("beaconName"); + CreateAttachmentDialogFragment createAttachmentDialogFragment = CreateAttachmentDialogFragment.newInstance(beaconName); + createAttachmentDialogFragment.show(getChildFragmentManager(), null); + + } catch (JSONException e) { + e.printStackTrace(); + } + } + }; + + private void showToast(final String message) { + Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mServiceBroadcastReceiver); + Log.v(TAG, "Receiver unregistered!"); + mServiceBroadcastReceiver = null; + } + + @Override + public void onDeviceSelected(final BluetoothDevice device, final String name) { + if (mProgressDialog != null) { + mProgressDialog.setTitle(getString(R.string.prog_dialog_connect_title)); + mProgressDialog.setMessage(getString(R.string.prog_dialog_connect_message)); + mProgressDialog.show(); + } + + final Activity activity = getActivity(); + final Intent service = new Intent(activity, UpdateService.class); + service.putExtra(UpdateService.EXTRA_DATA, device); + updateUiForBeacons(BluetoothProfile.STATE_CONNECTED, UpdateService.LOCKED); + activity.startService(service); + mBounnd = true; + activity.bindService(service, mServiceConnection, 0); + } + + private final Runnable mRunnableHandler = new Runnable() { + @Override + public void run() { + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.dismiss(); + } + } + }; + + private void updateUiForBeacons(int connectionState, int lockState) { + switch (connectionState) { + case BluetoothProfile.STATE_CONNECTED: + if (UpdateService.LOCKED == lockState) { + mIsBeaconLocked = true; + mCurrentLockState = LOCKED; + } else if (UpdateService.UNLOCKED == lockState) { + mIsBeaconLocked = false; + mCurrentLockState = UNLOCKED; + if (mUnlockBeaconDialogFragment != null) mUnlockBeaconDialogFragment.dismiss(); + mBeaconHelp.setVisibility(View.GONE); + mBeaconConfigurationContainer.setVisibility(View.VISIBLE); + mFrameTypeContainer.setVisibility(View.VISIBLE); + } else if (UpdateService.UNLOCKED_AUTOMATIC_RELOCK_DISABLED == lockState) { + mCurrentLockState = UNLOCKED_AUTOMATIC_RELOCK_DISABLED; + mIsBeaconLocked = false; + if (mUnlockBeaconDialogFragment != null) mUnlockBeaconDialogFragment.dismiss(); + mBeaconHelp.setVisibility(View.GONE); + mBeaconConfigurationContainer.setVisibility(View.VISIBLE); + mFrameTypeContainer.setVisibility(View.VISIBLE); + } + break; + case BluetoothProfile.STATE_DISCONNECTED: + setHasOptionsMenu(false); + getActivity().invalidateOptionsMenu(); + mBeaconHelp.setVisibility(View.VISIBLE); + mBeaconConfigurationContainer.setVisibility(View.GONE); + mFrameTypeContainer.setVisibility(View.GONE); + //clear all resources on disconnection + mBeaconPublicEcdhKey = null; + mDecryptedIdentityKey = null; + if (mServiceEcdhKey != null) { + final SharedPreferences sharedPreferences = getActivity().getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(SERVICE_ECDH_KEY, ParserUtils.bytesToHex(mServiceEcdhKey, 0, 32, false)).apply(); + } + mServiceEcdhKey = null; + mBeaconEcdhPrivateKey = null; + mIsBeaconLocked = true; + break; + } + } + + @Override + public void unlockBeacon(byte[] encryptedLockCode, final byte[] beaconLockCode) { + setHasOptionsMenu(true); + getActivity().invalidateOptionsMenu(); + mUnlockCode = beaconLockCode; + mBinder.unlockBeacon(encryptedLockCode, beaconLockCode); + } + + @Override + public void cancelUnlockBeacon() { + final Activity activity = getActivity(); + final Intent service = new Intent(activity, UpdateService.class); + activity.stopService(service); + } + + @Override + public void configureUidSlot(byte[] uidSlotData) { + mActiveSlotsTypes.set(mActiveSlot, "UID"); + mBinder.configureActiveSlot(uidSlotData, "UID"); + } + + @Override + public void configureUrlSlot(byte[] urlSlotData) { + mActiveSlotsTypes.set(mActiveSlot, "URL"); + mBinder.configureActiveSlot(urlSlotData, "URL"); + } + + @Override + public void configureTlmSlot(byte[] tlmSlotData) { + mActiveSlotsTypes.set(mActiveSlot, "TLM"); + mBinder.configureActiveSlot(tlmSlotData, "TLM"); + } + + @Override + public void configureEidSlot(final byte[] eidSlotData) { + + if (mProximityApiClient != null) { + if (NetworkUtils.checkNetworkConnectivity(getActivity())) { + if (mProgressDialog != null) { + mProgressDialog.setTitle(getString(R.string.prog_dialog_config_eid_title)); + mProgressDialog.setMessage(getString(R.string.retrieve_resolver_keys)); + mProgressDialog.show(); + mProgressDialogHandler.postDelayed(mRunnableHandler, 10000); + } + mProximityApiClient.getEphemeralIdRegistrationParams(new Callback() { + @Override + public void onFailure(Request request, IOException e) { + + } + + @Override + public void onResponse(Response response) throws IOException { + + try { + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.dismiss(); + mProgressDialogHandler.removeCallbacks(mRunnableHandler); + } + JSONObject jsonResponse = new JSONObject(response.body().string()); + if (!response.isSuccessful()) { + final JSONObject jsonError = jsonResponse.getJSONObject("error"); + final int errorCode = jsonError.getInt("code"); + final String message = jsonError.getString("message"); + ProximityApiErrorDialogFragment errorDialogFragment; + switch (errorCode) { + case ERROR_UNAUTHORIZED: + Account userAccount = getUserAccount(); + if (userAccount != null) + new AuthorizedServiceTask(getActivity(), userAccount, AUTH_SCOPE_PROXIMITY_API).execute(); + return; + default: + errorDialogFragment = ProximityApiErrorDialogFragment.newInstance(String.valueOf(errorCode), message, ""); + errorDialogFragment.show(getChildFragmentManager(), null); + return; + } + } + String body = response.body().string(); + //final JSONObject json = new JSONObject(body); + Log.d(TAG, "getEphemeralIdRegistrationParams response: " + jsonResponse.toString(2)); + String serviceEcdhPublicKey = jsonResponse.getString("serviceEcdhPublicKey"); + mServiceEcdhKey = ParserUtils.base64Decode(serviceEcdhPublicKey); + Log.d(TAG, "Service ECDH Key: " + ParserUtils.bytesToHex(mServiceEcdhKey, 0, 32, false)); + + if (mProgressDialog != null && mProgressDialog.isShowing()) + mProgressDialog.setMessage(getString(R.string.writing_rw_adv_slot_char)); + + if (eidSlotData.length == 34) { + mEikGenerated = false; + System.arraycopy(mServiceEcdhKey, 0, eidSlotData, 1, mServiceEcdhKey.length); + mActiveSlotsTypes.set(mActiveSlot, "EID"); + mBinder.configureActiveSlot(eidSlotData, "EID"); + } else { + byte[] beaconPrivateEcdhKey = new byte[32]; + new Random().nextBytes(beaconPrivateEcdhKey); + Log.d(TAG, "Beacon ECDH Private Key: " + ParserUtils.bytesToHex(beaconPrivateEcdhKey, 0, 32, false)); + mBeaconEcdhPrivateKey = ParserUtils.bytesToHex(beaconPrivateEcdhKey, 0, 32, false); + generator = new EddystoneEidrGenerator(mServiceEcdhKey, beaconPrivateEcdhKey); + mBeaconPublicEcdhKey = generator.getBeaconPublicKey(); + Log.d(TAG, "Beacon ECDH Public Key: " + ParserUtils.bytesToHex(mBeaconPublicEcdhKey, 0, 32, false)); + byte[] identityKey = generator.getIdentityKey(); + mEikGenerated = true; + Log.d(TAG, "Unencrypted Idenity Key: " + ParserUtils.bytesToHex(identityKey, 0, 16, false)); + Log.v(TAG, "Encrypted Identity key: " + ParserUtils.bytesToHex(identityKey, 0, 16, true)); + identityKey = ParserUtils.aes128Encrypt(identityKey, new SecretKeySpec(mUnlockCode, "AES")); + System.arraycopy(identityKey, 0, eidSlotData, 1, identityKey.length); + mActiveSlotsTypes.set(mActiveSlot, "EID"); + mBinder.configureActiveSlot(eidSlotData, "EID"); + } + } catch (JSONException e) { + e.printStackTrace(); + } + } + }); + } else showToast(getString(R.string.check_internet_connectivity)); + } else { + ensurePermission(new String[]{Manifest.permission.GET_ACCOUNTS}); + showToast(getString(R.string.reconnect_to_proximity)); + } + } + + @Override + public void lockBeacon(byte[] lockCode) { + if (lockCode.length == 17) + System.arraycopy(lockCode, 1, mUnlockCode, 0, 16); + mBinder.lockBeacon(lockCode); + } + + public byte[] aes128decrypt(byte[] data, SecretKeySpec keySpec) { + Cipher cipher; + try { + // Ignore the "ECB encryption should not be used" warning. We use exactly one block so + // the difference between ECB and CBC is just an IV or not. In addition our blocks are + // always different since they have a monotonic timestamp. Most importantly, our blocks + // aren't sensitive. Decrypting them means means knowing the beacon time and its rotation + // period. If due to ECB an attacker could find out that the beacon broadcast the same + // block a second time, all it could infer is that for some reason the clock of the beacon + // reset, which is not very helpful + cipher = Cipher.getInstance("AES/ECB/NoPadding"); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + Log.e(TAG, "Error constructing cipher instance", e); + return null; + } + + try { + cipher.init(Cipher.DECRYPT_MODE, keySpec); + } catch (InvalidKeyException e) { + Log.e(TAG, "Error initializing cipher instance", e); + return null; + } + + byte[] ret; + try { + ret = cipher.doFinal(data); + } catch (IllegalBlockSizeException | BadPaddingException e) { + Log.e(TAG, "Error executing cipher", e); + return null; + } + + return ret; + } + + @Override + public void registerBeaconListener(byte[] uid) { + mUidForEid = uid; + registerEidBeacon(uid); + } + + @Override + public void createAttachmentForBeacon(final String mBeaconName, final byte[] attachmentData) { + if (mProximityApiClient != null) { + mProgressDialog.show(); + mProgressDialogHandler.postDelayed(mRunnableHandler, 10000); + mProximityApiClient.createAttachment(mCreateAttachmentCallback, mBeaconName, createBeaconAttachment(attachmentData)); + } else { + ensurePermission(new String[] {Manifest.permission.GET_ACCOUNTS}); + } + } + + private final Callback mCreateAttachmentCallback = new Callback() { + @Override + public void onFailure(Request request, IOException e) { + Log.v(TAG, "Beacon attachmentm: " + request.toString()); + } + + @Override + public void onResponse(Response response) throws IOException { + try { + mProgressDialog.dismiss(); + mProgressDialogHandler.removeCallbacks(mRunnableHandler); + String body = response.body().string(); + final JSONObject jsonResponse = new JSONObject(body); + if (!response.isSuccessful()){ + final JSONObject jsonError = jsonResponse.getJSONObject("error"); + final int errorCode = jsonError.getInt("code"); + final String message = jsonError.getString("message"); + ProximityApiErrorDialogFragment errorDialogFragment; + switch (errorCode) { + case ERROR_UNAUTHORIZED: + Account userAccount = getUserAccount(); + if(userAccount != null) + new AuthorizedServiceTask(getActivity(), userAccount, AUTH_SCOPE_PROXIMITY_API).execute(); + return; + default: + errorDialogFragment = ProximityApiErrorDialogFragment.newInstance(String.valueOf(errorCode), message, ""); + errorDialogFragment.show(getChildFragmentManager(), null); + return; + } + } + showToast(getString(R.string.attachment_siccess)); + + Log.v(TAG, "Beacon attachmentm: " + response.toString()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + }; + + private JSONObject createBeaconAttachment(final byte[] attachment) { + + JSONObject body; + try { + body = new JSONObject() + .put("namespacedType", APP_NAMESPACE_TYPE) + .put("data", ParserUtils.base64Encode(attachment)); + Log.d(TAG, "request:" + body.toString(2)); + } catch (JSONException e) { + return null; + } + return body; + } + + @Override + public void configureRadioTxPower(final byte[] radioTxPower, final boolean advanceTxPowerSupported) { + if (!advanceTxPowerSupported) + mBinder.configureRadioTxPower(radioTxPower); + else + mBinder.configureAdvancedAdvertisedTxPower(radioTxPower); + } + + @Override + public void clearSlot() { + mBinder.configureActiveSlot(new byte[]{0x00}, "EMPTY"); //configuring active slot with a 0 byte will clear the slot + } + + @Override + public void configureAdvertisingInterval(final byte[] advertisingInterval) { + mBinder.configureAdvertistingInterval(advertisingInterval); + } + + private String getUserAccountName() { + SharedPreferences sharedPreferences = getActivity().getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE); + return sharedPreferences.getString(ACCOUNT_NAME_PREF, null); + } + + private Account getUserAccount() { + final String name = getUserAccountName(); + if (!name.isEmpty()) { + final Account[] accounts = AccountManager.get(getActivity()).getAccounts(); + for (Account account : accounts) { + if (account.name.equals(name)) { + mAccountName = account.name; + return account; + } + } + } + return null; + } + + + + private void setUserAccountName(final String accountName){ + SharedPreferences sharedPreferences = getActivity().getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(ACCOUNT_NAME_PREF, accountName).apply(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + switch (requestCode) { + case REQUEST_PERMISSION_REQ_CODE: { + if(permissions.length > 0) + for(int i = 0; i < permissions.length; i++){ + if (permissions[i].equals(Manifest.permission.GET_ACCOUNTS)){ + if(grantResults[i] == PackageManager.PERMISSION_GRANTED) + onPermissionGranted(permissions[i]); + else Toast.makeText(getActivity(), R.string.rationale_permission_denied, Toast.LENGTH_SHORT).show(); + } else if (permissions[i].equals(Manifest.permission.ACCESS_COARSE_LOCATION)) { + if (grantResults[i] == PackageManager.PERMISSION_GRANTED) + onPermissionGranted(permissions[i]); + else Toast.makeText(getActivity(), R.string.rationale_permission_denied, Toast.LENGTH_SHORT).show(); + } + } + break; + } + } + } + + @Override + protected void onPermissionGranted(String permission) { + Account account; + if (Manifest.permission.GET_ACCOUNTS.equalsIgnoreCase(permission)){ + String accountName = getUserAccountName(); + if (mProximityApiClient == null) { + if (accountName == null) { + String[] accountTypes = new String[]{"com.google"}; + Intent intent = AccountPicker.newChooseAccountIntent( + null, null, accountTypes, false, null, null, null, null); + startActivityForResult(intent, REQUEST_CODE_USER_ACCOUNT); + } else { + account = getUserAccount(); + if(account != null) { + authoriseAccount(account); + mProximityApiClient = new ProximityBeaconImpl(getActivity(), account); + } + } + } else { + account = getUserAccount(); + if(account != null) { + authoriseAccount(account); + if(mProximityApiClient == null) { + mProximityApiClient = new ProximityBeaconImpl(getActivity(), account); + } + } else Toast.makeText(getActivity(), getString(R.string.user_account_unavailable), Toast.LENGTH_LONG).show(); + } + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + switch (requestCode){ + case REQUEST_ENABLE_BT: + if(data != null) + if (resultCode != Activity.RESULT_OK) { + showToast(getString(R.string.rationale_permission_denied)); + onDestroy(); + } else { + if(ensurePermission(new String [] {Manifest.permission.ACCESS_COARSE_LOCATION})) { + if(isLocationEnabled()) { + final ScannerFragment scannerFragment = ScannerFragment.getInstance(EDDYSTONE_GATT_CONFIG_SERVICE_UUID); + scannerFragment.show(getChildFragmentManager(), null); + } else { + showToast("Please enable location services to scan for devices"); + } + } + } + break; + case REQUEST_CODE_USER_ACCOUNT: + if (resultCode == Activity.RESULT_OK) { + if (data != null) { + final String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); + setUserAccountName(accountName); + // The first time the account tries to contact the beacon service we'll pop a dialog + // asking the user to authorize our activity. Ensure that's handled cleanly here, rather + // than when the scan tries to fetch the status of every beacon within range. + Account account = getUserAccount(); + if(account != null) + authoriseAccount(account); + else showToast(getString(R.string.user_account_unavailable)); + } + } else { + showToast(getString(R.string.rationale_permission_denied)); + } + break; + } + } + + private void authoriseAccount(final Account account){ + if(NetworkUtils.checkNetworkConnectivity(getActivity())) { + new AuthorizedServiceTask(getActivity(), account, AUTH_SCOPE_PROXIMITY_API).execute(); + } + else + showToast(getString(R.string.check_internet_connectivity)); + } + + /** + * Checks whether the Bluetooth adapter is enabled. + */ + private boolean isBleEnabled() { + final BluetoothManager bm = (BluetoothManager) getActivity().getSystemService(Context.BLUETOOTH_SERVICE); + final BluetoothAdapter ba = bm.getAdapter(); + return ba != null && ba.isEnabled(); + } + + /** + * Tries to start Bluetooth adapter. + */ + private void enableBle() { + final Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + startActivityForResult(enableIntent, REQUEST_ENABLE_BT); + } + + public boolean isLocationEnabled() { + if (checkIfVersionIsMarshmallowOrAbove()) { + int locationMode = Settings.Secure.LOCATION_MODE_OFF; + + try { + locationMode = Settings.Secure.getInt(getActivity().getContentResolver(), Settings.Secure.LOCATION_MODE); + } catch (final Settings.SettingNotFoundException e) { + // do nothing + } + return locationMode != Settings.Secure.LOCATION_MODE_OFF; + } + return true; + } + + private boolean checkIfVersionIsMarshmallowOrAbove() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/AuthTaskUrlShortener.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/AuthTaskUrlShortener.java new file mode 100644 index 0000000..bc98a40 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/AuthTaskUrlShortener.java @@ -0,0 +1,124 @@ +package no.nordicsemi.android.nrfbeacon.nearby.util; + +import android.accounts.Account; +import android.app.Activity; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.AsyncTask; +import android.util.Log; + +import com.google.android.gms.auth.GoogleAuthException; +import com.google.android.gms.auth.GoogleAuthUtil; +import com.google.android.gms.auth.GooglePlayServicesAvailabilityException; +import com.google.android.gms.auth.UserRecoverableAuthException; +import com.google.android.gms.common.GooglePlayServicesUtil; +import com.squareup.okhttp.Callback; +import com.squareup.okhttp.MediaType; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.RequestBody; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +/** + * Created by rora on 07.04.2016. + */ +public class AuthTaskUrlShortener extends AsyncTask { + static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR = 1002; + public static final String AUTHORIZATION = "Authorization"; + public static final String BEARER = "Bearer "; + public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8"); + private static final String TAG = "BEACON"; + private final OkHttpClient mOkHttpClient; + private final Callback mCallBack; + private final String longUrl; + private final String BASE_URL = "https://www.googleapis.com/urlshortener/v1/url";//?key=AIzaSyDlSUOly5_hQkzeyxOr5Ff5c8AuNWaUcZM"; + private static final String SCOPE = "oauth2:https://www.googleapis.com/auth/urlshortener"; + private static final int REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_URL_SHORTNER = 1004; + private static final String AUTH_PROXIMITY_API = "oauth2:https://www.googleapis.com/auth/userlocation.beacon.registry"; + private static final String AUTH_SCOPE_URL_SHORTENER = "oauth2:https://www.googleapis.com/auth/urlshortener"; + private Activity mActivity; + private Account mAccount; + + public AuthTaskUrlShortener(final Callback mCallBack, final String longUrl, Activity context, Account account){ + this.mOkHttpClient = new OkHttpClient(); + this.mCallBack = mCallBack; + this.longUrl = longUrl; + this.mActivity = context; + this.mAccount = account; + } + + @Override + protected Void doInBackground(Void... params) { + final JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("longUrl", longUrl); + } catch (JSONException e) { + e.printStackTrace(); + } + final String token; + try { + token = GoogleAuthUtil.getToken(mActivity, mAccount, SCOPE); + Request.Builder requestBuilder = new Request.Builder() + .header(AUTHORIZATION, BEARER + token) + .url(BASE_URL) + .post(RequestBody.create(MEDIA_TYPE_JSON, jsonObject.toString())); + + Request request = requestBuilder.build(); + mOkHttpClient.newCall(request).enqueue(new HttpCallback(mCallBack)); + } catch (UserRecoverableAuthException e) { + // GooglePlayServices.apk is either old, disabled, or not present + // so we need to show the user some UI in the activity to recover. + handleAuthException(mActivity, e); + Log.e(TAG, "UserRecoverableAuthException", e); + } catch (GoogleAuthException e) { + // Some other type of unrecoverable exception has occurred. + // Report and log the error as appropriate for your app. + Log.e(TAG, "GoogleAuthException", e); + } catch (IOException e) { + // The fetchToken() method handles Google-specific exceptions, + // so this indicates something went wrong at a higher level. + // TIP: Check for network connectivity before starting the AsyncTask. + Log.e(TAG, "IOException", e); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + } + + private void handleAuthException(final Activity activity, final Exception e) { + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + if (e instanceof GooglePlayServicesAvailabilityException) { + // The Google Play services APK is old, disabled, or not present. + // Show a dialog created by Google Play services that allows + // the user to update the APK + int statusCode = ((GooglePlayServicesAvailabilityException) e).getConnectionStatusCode(); + Dialog dialog = GooglePlayServicesUtil.getErrorDialog( + statusCode, activity, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_URL_SHORTNER); + dialog.show(); + } else if (e instanceof UserRecoverableAuthException) { + // Unable to authenticate, such as when the user has not yet granted + // the app access to the account, but the user can fix this. + // Forward the user to an activity in Google Play services. + Intent intent = ((UserRecoverableAuthException) e).getIntent(); + activity.startActivityForResult( + intent, REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR_FOR_URL_SHORTNER); + + } + } + }); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/DebugLogger.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/DebugLogger.java new file mode 100644 index 0000000..99d38a1 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/DebugLogger.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.util; + +import android.util.Log; + +import no.nordicsemi.android.nrfbeacon.nearby.BuildConfig; + +public class DebugLogger { + public static void v(final String tag, final String text) { + if (BuildConfig.DEBUG) + Log.v(tag, text); + } + + public static void d(String tag, String text) { + if (BuildConfig.DEBUG) + Log.d(tag, text); + } + + public static void i(final String tag, final String text) { + if (BuildConfig.DEBUG) + Log.i(tag, text); + } + + public static void w(String tag, String text) { + if (BuildConfig.DEBUG) + Log.w(tag, text); + } + + public static void e(final String tag, final String text) { + if (BuildConfig.DEBUG) + Log.e(tag, text); + } + + public static void wtf(String tag, String text) { + if (BuildConfig.DEBUG) + Log.wtf(tag, text); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/HttpCallback.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/HttpCallback.java new file mode 100644 index 0000000..dde2ef9 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/HttpCallback.java @@ -0,0 +1,61 @@ +// Copyright 2015 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package no.nordicsemi.android.nrfbeacon.nearby.util; + +import android.os.Handler; +import android.os.Looper; + +import com.squareup.okhttp.Callback; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import java.io.IOException; + +/** + * A wrapper around OkHttp's Callback class that runs its methods on the UI thread. + */ +class HttpCallback implements Callback { + private final Callback delegate; + private final Handler handler; + + public HttpCallback(Callback delegate) { + this.delegate = delegate; + this.handler = new Handler(Looper.getMainLooper()); + } + + @Override + public void onFailure(final Request request, final IOException e) { + handler.post(new Runnable() { + @Override + public void run() { + delegate.onFailure(request, e); + } + }); + } + + @Override + public void onResponse(final Response response) throws IOException { + handler.post(new Runnable() { + @Override + public void run() { + try { + delegate.onResponse(response); + } catch (IOException e) { + delegate.onFailure(null, e); + } + } + }); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/NetworkUtils.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/NetworkUtils.java new file mode 100644 index 0000000..c33c537 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/NetworkUtils.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package no.nordicsemi.android.nrfbeacon.nearby.util; + +import android.app.Activity; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +/** + * Created by rora on 12.04.2016. + */ +public class NetworkUtils { + + public static boolean checkNetworkConnectivity(final Activity activity){ + ConnectivityManager cm = (ConnectivityManager)activity.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); + return activeNetwork != null && activeNetwork.isConnectedOrConnecting(); + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/ParserUtils.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/ParserUtils.java new file mode 100644 index 0000000..1a7983e --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/util/ParserUtils.java @@ -0,0 +1,755 @@ +/************************************************************************************************************************************************* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ************************************************************************************************************************************************/ +package no.nordicsemi.android.nrfbeacon.nearby.util; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; +import android.util.Base64; +import android.util.Log; +import android.util.SparseArray; +import android.util.Xml; +import android.webkit.URLUtil; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.Locale; +import java.util.Random; +import java.util.UUID; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; + +public class ParserUtils { + private static final char[] HEX_ARRAY = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + public static final int FORMAT_UINT24 = 0x13; + public static final int FORMAT_SINT24 = 0x23; + public static final int FORMAT_UINT16_BIG_INDIAN = 0x62; + public static final int FORMAT_UINT32_BIG_INDIAN = 0x64; + + + /** + * URI Scheme maps a byte code into the scheme and an optional scheme specific prefix. + */ + private static final SparseArray URI_SCHEMES = new SparseArray() { + { + put((byte) 0, "http://www."); + put((byte) 1, "https://www."); + put((byte) 2, "http://"); + put((byte) 3, "https://"); + put((byte) 4, "urn:uuid:"); // RFC 2141 and RFC 4122}; + } + }; + + /** + * Expansion strings for "http" and "https" schemes. These contain strings appearing anywhere in a + * URL. Restricted to Generic TLDs. + *

+ * Note: this is a scheme specific encoding. + */ + private static final SparseArray URL_CODES = new SparseArray() { + { + put((byte) 0, ".com/"); + put((byte) 1, ".org/"); + put((byte) 2, ".edu/"); + put((byte) 3, ".net/"); + put((byte) 4, ".info/"); + put((byte) 5, ".biz/"); + put((byte) 6, ".gov/"); + put((byte) 7, ".com"); + put((byte) 8, ".org"); + put((byte) 9, ".edu"); + put((byte) 10, ".net"); + put((byte) 11, ".info"); + put((byte) 12, ".biz"); + put((byte) 13, ".gov"); + } + }; + private static final String TAG = "MCP"; + + public static String bytesToHex(final byte[] bytes, final boolean add0x) { + if (bytes == null) + return ""; + return bytesToHex(bytes, 0, bytes.length, add0x); + } + + public static String bytesToHex(final byte[] bytes, final int start, final int length, final boolean add0x) { + if (bytes == null || bytes.length <= start || length <= 0) + return ""; + + final int maxLength = Math.min(length, bytes.length - start); + final char[] hexChars = new char[maxLength * 2]; + for (int j = 0; j < maxLength; j++) { + final int v = bytes[start + j] & 0xFF; + hexChars[j * 2] = HEX_ARRAY[v >>> 4]; + hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; + } + if (!add0x) + return new String(hexChars); + return "0x" + new String(hexChars); + } + + public static String bytesToAddress(final byte[] bytes, final int start) { + if (bytes == null || bytes.length < start + 6) + return ""; + + final int maxLength = 6; + final char[] hexChars = new char[maxLength * 3 - 1]; + for (int j = 0; j < maxLength; j++) { + final int v = bytes[start + j] & 0xFF; + hexChars[j * 3] = HEX_ARRAY[v >>> 4]; + hexChars[j * 3 + 1] = HEX_ARRAY[v & 0x0F]; + if (j < maxLength - 1) + hexChars[j * 3 + 2] = ':'; + } + return new String(hexChars); + } + + public static UUID bytesToUUID(final byte[] bytes, final int start, final int length) { + if (bytes == null || bytes.length < start + 16 || length != 16) + return null; + + long msb = 0L; + long lsb = 0L; + for (int i = 0; i < 8; ++i) + msb += (bytes[start + i] & 0xFFL) << (56 - i * 8); + for (int i = 0; i < 8; ++i) + lsb += (bytes[start + i + 8] & 0xFFL) << (56 - i * 8); + + return new UUID(msb, lsb); + } + + public static String deviceTypeTyString(final int type) { + switch (type) { + case BluetoothDevice.DEVICE_TYPE_CLASSIC: + return "CLASSIC"; + case BluetoothDevice.DEVICE_TYPE_DUAL: + return "CLASSIC and BLE"; + case BluetoothDevice.DEVICE_TYPE_LE: + return "BLE only"; + default: + return "UNKNOWN"; + } + } + + public static String bondingStateToString(final int state) { + switch (state) { + case BluetoothDevice.BOND_BONDING: + return "BONDING..."; + case BluetoothDevice.BOND_BONDED: + return "BONDED"; + default: + return "NOT BONDED"; + } + } + + public static String getProperties(final BluetoothGattCharacteristic characteristic) { + final int properties = characteristic.getProperties(); + final StringBuilder builder = new StringBuilder(); + if ((properties & BluetoothGattCharacteristic.PROPERTY_BROADCAST) > 0) + builder.append("B "); + if ((properties & BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS) > 0) + builder.append("E "); + if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) + builder.append("I "); + if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) + builder.append("N "); + if ((properties & BluetoothGattCharacteristic.PROPERTY_READ) > 0) + builder.append("R "); + if ((properties & BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE) > 0) + builder.append("SW "); + if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) + builder.append("W "); + if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) + builder.append("WNR "); + + if (builder.length() > 0) { + builder.setLength(builder.length() - 1); + builder.insert(0, "["); + builder.append("]"); + } + return builder.toString(); + } + + public static int setValue(final byte[] dest, int offset, int value, int formatType) { + int len = offset + getTypeLen(formatType); + if (len > dest.length) + return offset; + + switch (formatType) { + case BluetoothGattCharacteristic.FORMAT_SINT8: + value = intToSignedBits(value, 8); + // Fall-through intended + case BluetoothGattCharacteristic.FORMAT_UINT8: + dest[offset] = (byte) (value & 0xFF); + break; + + case BluetoothGattCharacteristic.FORMAT_SINT16: + value = intToSignedBits(value, 16); + // Fall-through intended + case BluetoothGattCharacteristic.FORMAT_UINT16: + dest[offset++] = (byte) (value & 0xFF); + dest[offset] = (byte) ((value >> 8) & 0xFF); + break; + + case FORMAT_SINT24: + value = intToSignedBits(value, 24); + // Fall-through intended + case FORMAT_UINT24: + dest[offset++] = (byte) (value & 0xFF); + dest[offset++] = (byte) ((value >> 8) & 0xFF); + dest[offset] = (byte) ((value >> 16) & 0xFF); + break; + + case FORMAT_UINT16_BIG_INDIAN: + dest[offset++] = (byte) ((value >> 8) & 0xFF); + dest[offset] = (byte) (value & 0xFF); + break; + + case BluetoothGattCharacteristic.FORMAT_SINT32: + value = intToSignedBits(value, 32); + // Fall-through intended + case BluetoothGattCharacteristic.FORMAT_UINT32: + dest[offset++] = (byte) (value & 0xFF); + dest[offset++] = (byte) ((value >> 8) & 0xFF); + dest[offset++] = (byte) ((value >> 16) & 0xFF); + dest[offset] = (byte) ((value >> 24) & 0xFF); + break; + + case FORMAT_UINT32_BIG_INDIAN: + dest[offset++] = (byte) ((value >> 24) & 0xFF); + dest[offset++] = (byte) ((value >> 16) & 0xFF); + dest[offset++] = (byte) ((value >> 8) & 0xFF); + dest[offset] = (byte) (value & 0xFF); + break; + + default: + return offset; + } + return len; + } + + public static int setValue(final byte[] dest, int offset, int mantissa, int exponent, int formatType) { + int len = offset + getTypeLen(formatType); + if (len > dest.length) + return offset; + + switch (formatType) { + case BluetoothGattCharacteristic.FORMAT_SFLOAT: + mantissa = intToSignedBits(mantissa, 12); + exponent = intToSignedBits(exponent, 4); + dest[offset++] = (byte) (mantissa & 0xFF); + dest[offset] = (byte) ((mantissa >> 8) & 0x0F); + dest[offset] += (byte) ((exponent & 0x0F) << 4); + break; + + case BluetoothGattCharacteristic.FORMAT_FLOAT: + mantissa = intToSignedBits(mantissa, 24); + exponent = intToSignedBits(exponent, 8); + dest[offset++] = (byte) (mantissa & 0xFF); + dest[offset++] = (byte) ((mantissa >> 8) & 0xFF); + dest[offset++] = (byte) ((mantissa >> 16) & 0xFF); + dest[offset] += (byte) (exponent & 0xFF); + break; + + default: + return offset; + } + + return len; + } + + public static int setValue(final byte[] dest, final int offset, final String value) { + if (value == null) + return offset; + + final byte[] valueBytes = value.getBytes(); + System.arraycopy(valueBytes, 0, dest, offset, valueBytes.length); + return offset + valueBytes.length; + } + + public static int setByteArrayValue(final byte[] dest, final int offset, final String value) { + if (value == null) + return offset; + + for (int i = 0; i < value.length(); i += 2) { + dest[offset + i / 2] = (byte) ((Character.digit(value.charAt(i), 16) << 4) + + Character.digit(value.charAt(i + 1), 16)); + } + return offset + value.length() / 2; + } + + public static int getIntValue(final byte[] source, final int offset, final int formatType) { + if ((offset + getTypeLen(formatType)) > source.length) + throw new ArrayIndexOutOfBoundsException(); + + switch (formatType) { + case BluetoothGattCharacteristic.FORMAT_UINT8: + return unsignedByteToInt(source[offset]); + + case BluetoothGattCharacteristic.FORMAT_UINT16: + return unsignedBytesToInt(source[offset], source[offset + 1]); + + case FORMAT_UINT24: + return unsignedBytesToInt(source[offset], source[offset + 1], source[offset + 2]); + + case BluetoothGattCharacteristic.FORMAT_UINT32: + return unsignedBytesToInt(source[offset], source[offset + 1], source[offset + 2], source[offset + 3]); + + case FORMAT_UINT16_BIG_INDIAN: + return unsignedBytesToInt(source[offset + 1], source[offset]); + + case FORMAT_UINT32_BIG_INDIAN: + return unsignedBytesToInt(source[offset + 3], source[offset + 2], source[offset + 1], source[offset]); + + case BluetoothGattCharacteristic.FORMAT_SINT8: + return unsignedToSigned(unsignedByteToInt(source[offset]), 8); + + case BluetoothGattCharacteristic.FORMAT_SINT16: + return unsignedToSigned(unsignedBytesToInt(source[offset], source[offset + 1]), 16); + + case FORMAT_SINT24: + return unsignedToSigned(unsignedBytesToInt(source[offset], source[offset + 1], source[offset + 2]), 24); + + case BluetoothGattCharacteristic.FORMAT_SINT32: + return unsignedToSigned(unsignedBytesToInt(source[offset], source[offset + 1], source[offset + 2], source[offset + 3]), 32); + } + return 0; + } + + public static int getMantissa(final byte[] source, final int offset, final int formatType) { + if ((offset + getTypeLen(formatType)) > source.length) + throw new ArrayIndexOutOfBoundsException(); + + switch (formatType) { + case BluetoothGattCharacteristic.FORMAT_SFLOAT: + return unsignedToSigned(unsignedByteToInt(source[offset]) + ((unsignedByteToInt(source[offset + 1]) & 0x0F) << 8), 12); + case BluetoothGattCharacteristic.FORMAT_FLOAT: + return unsignedToSigned(unsignedByteToInt(source[offset]) + (unsignedByteToInt(source[offset + 1]) << 8) + (unsignedByteToInt(source[offset + 2]) << 16), 24); + } + return 0; + } + + public static int getExponent(final byte[] source, final int offset, final int formatType) { + if ((offset + getTypeLen(formatType)) > source.length) + throw new ArrayIndexOutOfBoundsException(); + + switch (formatType) { + case BluetoothGattCharacteristic.FORMAT_SFLOAT: + return unsignedToSigned(unsignedByteToInt(source[offset + 1]) >> 4, 4); + case BluetoothGattCharacteristic.FORMAT_FLOAT: + return source[offset + 3]; + } + return 0; + } + + /** + * Returns the size of a give value type. + */ + public static int getTypeLen(int formatType) { + return formatType & 0xF; + } + + /** + * Convert a signed byte to an unsigned int. + */ + private static int unsignedByteToInt(byte b) { + return b & 0xFF; + } + + /** + * Convert signed bytes to a 16-bit unsigned int. + */ + private static int unsignedBytesToInt(byte b0, byte b1) { + return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)); + } + + /** + * Convert signed bytes to a 24-bit unsigned int. + */ + private static int unsignedBytesToInt(byte b0, byte b1, byte b2) { + return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)) + (unsignedByteToInt(b2) << 16); + } + + /** + * Convert signed bytes to a 32-bit unsigned int. + */ + private static int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) { + return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8)) + (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24); + } + + /** + * Convert an unsigned integer value to a two's-complement encoded + * signed value. + */ + private static int unsignedToSigned(int unsigned, int size) { + if ((unsigned & (1 << size - 1)) != 0) { + unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1))); + } + return unsigned; + } + + /** + * Convert an integer into the signed bits of a given length. + */ + private static int intToSignedBits(int i, int size) { + if (i < 0) { + i = (1 << size - 1) + (i & ((1 << size - 1) - 1)); + } + return i; + } + + public static int decodeUuid16(final byte[] data, final int start) { + final int b1 = data[start] & 0xff; + final int b2 = data[start + 1] & 0xff; + + return (b2 << 8 | b1) & 0xFFFF; + } + + public static int decodeUuid32(final byte[] data, final int start) { + final int b1 = data[start] & 0xff; + final int b2 = data[start + 1] & 0xff; + final int b3 = data[start + 2] & 0xff; + final int b4 = data[start + 3] & 0xff; + + return b4 << 24 | b3 << 16 | b2 << 8 | b1; + } + + public static int intOrThrow(final Integer i) { + if (i == null) + throw new NullPointerException(); + return i; + } + + public static byte[] base64Decode(String s) { + return Base64.decode(s, Base64.DEFAULT); + } + + public static String base64Encode(byte[] b) { + return Base64.encodeToString(b, Base64.DEFAULT).trim(); + } + + public static String base64Encode(String s) { + return base64Encode(setByteArrayValue(s)); + } + + private static byte[] setByteArrayValue(String hexString) { + int len = hexString.length(); + byte[] bytes = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + + Character.digit(hexString.charAt(i + 1), 16)); + } + return bytes; + } + + public static String decodeUri(final byte[] serviceData, final int start, final int length) { + if (start < 0 || serviceData.length < start + length) + return null; + + final StringBuilder uriBuilder = new StringBuilder(); + int offset = 0; + if (offset < length) { + byte b = serviceData[start + offset++]; + String scheme = URI_SCHEMES.get(b); + if (scheme != null) { + uriBuilder.append(scheme); + if (URLUtil.isNetworkUrl(scheme)) { + return decodeUrl(serviceData, start + offset, length - 1, uriBuilder); + } else if ("urn:uuid:".equals(scheme)) { + return decodeUrnUuid(serviceData, start + offset, uriBuilder); + } + } + Log.w(TAG, "decodeUri unknown Uri scheme code=" + b); + } + return null; + } + + private static String decodeUrl(final byte[] serviceData, final int start, final int length, final StringBuilder urlBuilder) { + int offset = 0; + while (offset < length) { + byte b = serviceData[start + offset++]; + String code = URL_CODES.get(b); + if (code != null) { + urlBuilder.append(code); + } else { + urlBuilder.append((char) b); + } + } + return urlBuilder.toString(); + } + + private static String decodeUrnUuid(final byte[] serviceData, final int offset, final StringBuilder urnBuilder) { + ByteBuffer bb = ByteBuffer.wrap(serviceData); + // UUIDs are ordered as byte array, which means most significant first + bb.order(ByteOrder.BIG_ENDIAN); + long mostSignificantBytes, leastSignificantBytes; + try { + bb.position(offset); + mostSignificantBytes = bb.getLong(); + leastSignificantBytes = bb.getLong(); + } catch (BufferUnderflowException e) { + Log.w(TAG, "decodeUrnUuid BufferUnderflowException!"); + return null; + } + UUID uuid = new UUID(mostSignificantBytes, leastSignificantBytes); + urnBuilder.append(uuid.toString()); + return urnBuilder.toString(); + } + + /** + * Creates the Uri string with embedded expansion codes. + * + * @param uri to be encoded + * @return the Uri string with expansion codes. + */ + public static byte[] encodeUri(String uri) { + if (uri.length() == 0) { + return new byte[0]; + } + ByteBuffer bb = ByteBuffer.allocate(uri.length()); + // UUIDs are ordered as byte array, which means most significant first + bb.order(ByteOrder.BIG_ENDIAN); + int position = 0; + + // Add the byte code for the scheme or return null if none + Byte schemeCode = encodeUriScheme(uri); + if (schemeCode == null) { + return null; + } + String scheme = URI_SCHEMES.get(schemeCode); + bb.put(schemeCode); + position += scheme.length(); + + if (URLUtil.isNetworkUrl(scheme)) { + return encodeUrl(uri, position, bb); + } else if ("urn:uuid:".equals(scheme)) { + return encodeUrnUuid(uri, position, bb); + } + return null; + } + private static Byte encodeUriScheme(String uri) { + String lowerCaseUri = uri.toLowerCase(Locale.ENGLISH); + for (int i = 0; i < URI_SCHEMES.size(); i++) { + // get the key and value. + int key = URI_SCHEMES.keyAt(i); + String value = URI_SCHEMES.valueAt(i); + if (lowerCaseUri.startsWith(value)) { + return (byte) key; + } + } + return null; + } + + private static byte[] encodeUrl(String url, int position, ByteBuffer bb) { + while (position < url.length()) { + byte expansion = findLongestExpansion(url, position); + if (expansion >= 0) { + bb.put(expansion); + position += URL_CODES.get(expansion).length(); + } else { + bb.put((byte) url.charAt(position++)); + } + } + return byteBufferToArray(bb); + } + + private static byte[] encodeUrnUuid(String urn, int position, ByteBuffer bb) { + String uuidString = urn.substring(position, urn.length()); + UUID uuid; + try { + uuid = UUID.fromString(uuidString); + } catch (IllegalArgumentException e) { + Log.w(TAG, "encodeUrnUuid invalid urn:uuid format - " + urn); + return null; + } + // UUIDs are ordered as byte array, which means most significant first + bb.order(ByteOrder.BIG_ENDIAN); + bb.putLong(uuid.getMostSignificantBits()); + bb.putLong(uuid.getLeastSignificantBits()); + return byteBufferToArray(bb); + } + + private static byte[] byteBufferToArray(ByteBuffer bb) { + byte[] bytes = new byte[bb.position()]; + bb.rewind(); + bb.get(bytes, 0, bytes.length); + return bytes; + } + + /** + * Finds the longest expansion from the uri at the current position. + * + * @param uriString the Uri + * @param pos start position + * @return an index in URI_MAP or 0 if none. + */ + private static byte findLongestExpansion(String uriString, int pos) { + byte expansion = -1; + int expansionLength = 0; + for (int i = 0; i < URL_CODES.size(); i++) { + // get the key and value. + int key = URL_CODES.keyAt(i); + String value = URL_CODES.valueAt(i); + if (value.length() > expansionLength && uriString.startsWith(value, pos)) { + expansion = (byte) key; + expansionLength = value.length(); + } + } + return expansion; + } + + public static byte[] toByteArray(String hexString) { + int len = hexString.length(); + byte[] bytes = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + + Character.digit(hexString.charAt(i + 1), 16)); + } + return bytes; + } + + public static int decodeUint16BigEndian(final byte[] data, final int start) { + final int b1 = data[start] & 0xff; + final int b2 = data[start + 1] & 0xff; + + return b1 << 8 | b2; + } + + /** + * This method returns the Uint32 value encoded with Big Endian. + */ + public static long decodeUint32BigEndian(final byte[] data, final int start) { + final int b1 = data[start] & 0xff; + final int b2 = data[start + 1] & 0xff; + final int b3 = data[start + 2] & 0xff; + final int b4 = data[start + 3] & 0xff; + + return (b1 << 24 | b2 << 16 | b3 << 8 | b4) & 0xFFFFFFFFL; + } + + public static float decode88FixedPointNotation(final byte[] data, final int start) { + return data[start] + (float) (data[start + 1] & 0xFF) / 256.f; + } + + public static String randomUid(int len) { + byte[] buf = new byte[len]; + new Random().nextBytes(buf); + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < len; i++) { + stringBuilder.append(String.format("%02x", buf[i])); + } + return stringBuilder.toString(); + } + + public static byte[] aes128Encrypt(byte[] data, SecretKeySpec keySpec) { + Cipher cipher; + try { + // Ignore the "ECB encryption should not be used" warning. We use exactly one block so + // the difference between ECB and CBC is just an IV or not. In addition our blocks are + // always different since they have a monotonic timestamp. Most importantly, our blocks + // aren't sensitive. Decrypting them means means knowing the beacon time and its rotation + // period. If due to ECB an attacker could find out that the beacon broadcast the same + // block a second time, all it could infer is that for some reason the clock of the beacon + // reset, which is not very helpful + cipher = Cipher.getInstance("AES/ECB/NoPadding"); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + Log.e(TAG, "Error constructing cipher instance", e); + return null; + } + + try { + cipher.init(Cipher.ENCRYPT_MODE, keySpec); + } catch (InvalidKeyException e) { + Log.e(TAG, "Error initializing cipher instance", e); + return null; + } + + byte[] ret; + try { + ret = cipher.doFinal(data); + } catch (IllegalBlockSizeException | BadPaddingException e) { + Log.e(TAG, "Error executing cipher", e); + return null; + } + + return ret; + } + + public static byte[] aes128decrypt(byte[] data, SecretKeySpec keySpec) { + Cipher cipher; + try { + // Ignore the "ECB encryption should not be used" warning. We use exactly one block so + // the difference between ECB and CBC is just an IV or not. In addition our blocks are + // always different since they have a monotonic timestamp. Most importantly, our blocks + // aren't sensitive. Decrypting them means means knowing the beacon time and its rotation + // period. If due to ECB an attacker could find out that the beacon broadcast the same + // block a second time, all it could infer is that for some reason the clock of the beacon + // reset, which is not very helpful + cipher = Cipher.getInstance("AES/ECB/NoPadding"); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + Log.e(TAG, "Error constructing cipher instance", e); + return null; + } + + try { + cipher.init(Cipher.DECRYPT_MODE, keySpec); + } catch (InvalidKeyException e) { + Log.e(TAG, "Error initializing cipher instance", e); + return null; + } + + byte[] ret; + try { + ret = cipher.doFinal(data); + } catch (IllegalBlockSizeException | BadPaddingException e) { + Log.e(TAG, "Error executing cipher", e); + return null; + } + + return ret; + } + + public static String parse(final byte[] bytes, final int offset, final int length, final String unit) { + final String notNullUnit = unit == null ? "" : " " + unit; + + switch (length) { + case 1: + return String.valueOf(ParserUtils.getIntValue(bytes, offset, BluetoothGattCharacteristic.FORMAT_SINT8)) + notNullUnit; + case 2: + return String.valueOf(ParserUtils.getIntValue(bytes, offset, BluetoothGattCharacteristic.FORMAT_SINT16)) + notNullUnit; + case 3: + return String.valueOf(ParserUtils.getIntValue(bytes, offset, ParserUtils.FORMAT_SINT24)) + notNullUnit; + case 4: + return String.valueOf(ParserUtils.getIntValue(bytes, offset, BluetoothGattCharacteristic.FORMAT_SINT32)) + notNullUnit; + case 16: + return ParserUtils.bytesToHex(bytes, offset, length, true); + } + return "Invalid data syntax: " + ParserUtils.bytesToHex(bytes, offset, length, true); + } +} \ No newline at end of file diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetBoldTextView.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetBoldTextView.java new file mode 100644 index 0000000..2074ad0 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetBoldTextView.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.widget; + +import android.content.Context; +import android.graphics.Typeface; +import android.util.AttributeSet; +import android.widget.TextView; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +public class TrebuchetBoldTextView extends TextView { + + public TrebuchetBoldTextView(Context context) { + super(context); + + init(); + } + + public TrebuchetBoldTextView(Context context, AttributeSet attrs) { + super(context, attrs); + + init(); + } + + public TrebuchetBoldTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + init(); + } + + private void init() { + if (!isInEditMode()) { + final Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), getContext().getString(R.string.font_path)); + setTypeface(typeface); + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetSwitch.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetSwitch.java new file mode 100644 index 0000000..4224c06 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetSwitch.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.widget; + +import android.content.Context; +import android.graphics.Typeface; +import android.util.AttributeSet; +import android.widget.Switch; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +public class TrebuchetSwitch extends Switch { + + public TrebuchetSwitch(Context context) { + super(context); + + init(); + } + + public TrebuchetSwitch(Context context, AttributeSet attrs) { + super(context, attrs); + + init(); + } + + public TrebuchetSwitch(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + init(); + } + + private void init() { + if (!isInEditMode()) { + final Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), getContext().getString(R.string.normal_font_path)); + setTypeface(typeface); + } + } +} diff --git a/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetTextView.java b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetTextView.java new file mode 100644 index 0000000..bd7de24 --- /dev/null +++ b/app/src/main/java/no/nordicsemi/android/nrfbeacon/nearby/widget/TrebuchetTextView.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package no.nordicsemi.android.nrfbeacon.nearby.widget; + +import android.content.Context; +import android.graphics.Typeface; +import android.util.AttributeSet; +import android.widget.TextView; + +import no.nordicsemi.android.nrfbeacon.nearby.R; + +public class TrebuchetTextView extends TextView { + + public TrebuchetTextView(Context context) { + super(context); + + init(); + } + + public TrebuchetTextView(Context context, AttributeSet attrs) { + super(context, attrs); + + init(); + } + + public TrebuchetTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + init(); + } + + private void init() { + if (!isInEditMode()) { + final Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), getContext().getString(R.string.normal_font_path)); + setTypeface(typeface); + } + } +} diff --git a/app/src/main/res/animator/connect_animator.xml b/app/src/main/res/animator/connect_animator.xml new file mode 100644 index 0000000..29600a1 --- /dev/null +++ b/app/src/main/res/animator/connect_animator.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/tab_text_color.xml b/app/src/main/res/color/tab_text_color.xml new file mode 100644 index 0000000..57c34d7 --- /dev/null +++ b/app/src/main/res/color/tab_text_color.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/text.xml b/app/src/main/res/color/text.xml new file mode 100644 index 0000000..9de63dc --- /dev/null +++ b/app/src/main/res/color/text.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/app/src/main/res/color/text_color_primary.xml b/app/src/main/res/color/text_color_primary.xml new file mode 100644 index 0000000..d335c9e --- /dev/null +++ b/app/src/main/res/color/text_color_primary.xml @@ -0,0 +1,27 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/text_secondary.xml b/app/src/main/res/color/text_secondary.xml new file mode 100644 index 0000000..0c5d29d --- /dev/null +++ b/app/src/main/res/color/text_secondary.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/app/src/main/res/drawable-hdpi/ic_eddystone.png b/app/src/main/res/drawable-hdpi/ic_eddystone.png new file mode 100644 index 0000000000000000000000000000000000000000..ad85b3dff27f7568b880705e6fdd899a76ffe156 GIT binary patch literal 712 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$a>cu_bxCyDx`7I;J! zGcbq?fiPqG{7WEx>?NMQuIvw(nE5Rv_Il~rFfcHMdb&7yy1eD{z5bLBIa7o;!cO*jfIoo|4?P(!UpP{0WP0y4tpUN|D7(AG^pd`_O3# zE4MG5a(G#$T{IW#E{{q%jeaIgIO0#%4bZFftrW>vxX6a<%FzIz)XmQt6PD|;zB;J3 z3#c}>On9vgSIYUt4&Q9Jme}+xbU3xxLHygZ>z;@7^-8zTw_wPNoZw;THc6Kx? zzID8N$SitZ^TJwl<|}W7lQft9S#5Lp=hK3j)_c;Y8J#^NUR*uzpycby1+MF3Z{?V2 z3mTq1Gr42O-Y1_$PpJLUzkJ4Kp7gx6d5=U_sQ(L|muRoB>4f1}r!|{rS&`cK609Ky;kpYi>oE z(jyC{chS7h8?XHhKXfj~tXfL&yWWR?Yv;SaYBIj~`lpoOnCZ>6e% zgM ASpWb4 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_feature.png b/app/src/main/res/drawable-hdpi/ic_feature.png new file mode 100644 index 0000000000000000000000000000000000000000..6784181fd76a7897b4aa29263e6a99665d360e39 GIT binary patch literal 2424 zcmai0dpHvcAD&5Ri(GO^?wQCnMZ4Hs!*V}zoy*SQh^W?~mCG20R>PWH4jLkt9COKC zF$zh@R9H2ObBqW>bB*JC&vX9!zUOLsl z^x(eoY^GZF?J&;HI|2XzOaDV5Kwg3T{_ix}+Tzk}_P2-ef8@9;^#$-a;FT8vcZlj! z8J3!%FugFWTX68n!TZ?wB7v2aj@y_oTbK30r>V@?v)cEr�H49B8o8xX#DyrOQ;R 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_menu_settings.png b/app/src/main/res/drawable-hdpi/ic_menu_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..97ded33b5558a0efbd7812296a52325b4170076e GIT binary patch literal 460 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/stat_sys_beacon.png b/app/src/main/res/drawable-hdpi/stat_sys_beacon.png new file mode 100644 index 0000000000000000000000000000000000000000..a906d3237750308c61e7391537e5df2970f655aa GIT binary patch literal 1185 zcmV;S1YY}zP)bo4!5=3noT@A&#w<% zPu$IUbnR>u^oIlIT=)Il_x1c=uKRx<>3{o=S(xk%fGkiELa3BfDXCggjig~ohe8O+ zq!R)vB{fP~B7NC^L~-NiC9EB`uRQUs7$fPa


cl@3educXru@-0no&omQbEy@8Ux6Or z4d9%K>d6K#2Cx@sEf$NpXwDkoHQ-1@qSraL*^@G@}rc*)cOZ+gQYfz?rR-v%7^ z*g=!~D<=wt!fbo0&7myvcYA*!(-Kr*%UYGQ3sg3&j`f~Yvewo*=mh^+9PeKU&r970k&;i_&_Q_GW zHd&=Jz`YjD?o<{|Wg{aadAB1y_I?5!2X@CgHWr~Ki`rmxOf*@G27$H4W&kgk#d=$4?tSCoE9-Nw$7G|LV7VPi8SE%f*H5W?W82xYU`n(gUoG@0`1fsL-R{gSpy`d-p;V|yiSF*abVN76P)*-{<~AryelGa%Fx zIpCyYBNz8I#wz0O&REu;a2jn}5w*T!S<$zWjHb$fhphZ#*+;;vDgBGZUccM@c%P-E z19)z9?;WO)RL03WUs9E%Ly~$!2!((3A69<=1Y(4a+IAPV00000NkvXXu0mjfTDu~H literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/stat_sys_nrf_beacon.png b/app/src/main/res/drawable-hdpi/stat_sys_nrf_beacon.png new file mode 100644 index 0000000000000000000000000000000000000000..f5d081478d0d10d07088436f22fea912f58f28ec GIT binary patch literal 842 zcmV-Q1GW5#P)u5Rs0f0zU>05IN=0j1@dZjre1L*t-H3vU+7fNCXsbr8vDh}D_hvpfr!Wk2 zlc;x6kQ^BJU+4VaoH_sb&%m-QQq(o-8|w5t&!6g)xLGyHh?rjB)Aj-F1-$sLrLWRo%qFd- zVCsO*xGV!L11$snuYuG{)GOx8)J+4d1?~qn0OtaOz(HW$k^!lMc@d8R*8<0YBfyuy z&%mK2^H5O~Bf#UpFz^Ae8Q2>U2TH&(UknwC*r&75I<=)f6A=@Dz*WE~@G@|Lx>fx` z{SElMn}-6pOkH0pE&3|3sw*R6C^xEuIS+UNxD|L5*q-(_0rw@`4Dc!NHZa-kt$tBw zO6BTtbwYhe{kBrZsy@-hGkesNMN!W&mow|B4!S`8BnR@-y)KsXuYUVcA z*x0Ggm0%vpwePpv?JG;`?ooHEAF8i)1KOa@s;Bbls6VRDrP0&lv+6!|O+|mB+EyRT z{$r{4)Y#ZqpW3h9ksfa67ul!2+O;6dBsE+K`hMV4Y3vVRA|fp54FMlzO@3p>&+EYU zhgUMZinvb|p9nw!%bm#c&7q&l8+E7Y&mlj>cK|32lW2lF>- zKz&#}p|0(8I{oUKd00l4>N;4L-r1zCR1c_6XJWiF=kBgcf=vOvs2){Ut2brPUz2mk z@`Sc(^j4|&syFl$RNb$BlkMl#-*dB#YSAS&T!6EWuzCk{Y>6lpJabG@Nu@^ z1@_kH90pDRXII95Xfn{FTX~UV+cI09mhZB7BRB)1o|WauDDV^T67YRbvvsfJZxkmK U@6&yB@c;k-07*qoM6N<$f;$(NQ~&?~ literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-land-xhdpi/background_image.jpg b/app/src/main/res/drawable-land-xhdpi/background_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f8dfa38cd2bf3be58bca2f4b383ffee008a41c0d GIT binary patch literal 27426 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 BPP_mB literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-land-xhdpi/nordic_logo.png b/app/src/main/res/drawable-land-xhdpi/nordic_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..24a9d4e768cf261deeb29285d700189cfb0e8262 GIT binary patch literal 55949 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

UQElolSp#ifm`q#_|LDG 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/beacon_sw1.png b/app/src/main/res/drawable-xhdpi/beacon_sw1.png new file mode 100644 index 0000000000000000000000000000000000000000..f6e188c00ce96f7711360499d2590e4e65eb99f8 GIT binary patch literal 74909 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-v21/button.xml b/app/src/main/res/drawable-v21/button.xml new file mode 100644 index 0000000..650eb91 --- /dev/null +++ b/app/src/main/res/drawable-v21/button.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/app_drive.png b/app/src/main/res/drawable-xhdpi/app_drive.png new file mode 100644 index 0000000000000000000000000000000000000000..e64055116744ecb47f713503a8408cfb0d142507 GIT binary patch literal 2573 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/app_google_play.png b/app/src/main/res/drawable-xhdpi/app_google_play.png new file mode 100644 index 0000000000000000000000000000000000000000..14e0258a971aeb3bbcd3b55c7db2e515c7f52528 GIT binary patch literal 2247 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 Kr=j3;`~L;S=31fv literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/beacon_sample.png b/app/src/main/res/drawable-xhdpi/beacon_sample.png new file mode 100644 index 0000000000000000000000000000000000000000..23370610a5521ce1113d6f8ab6333075777b063f GIT binary patch literal 182055 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