├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── BluefruitLEConnect_Android.iml ├── README.md ├── androidSupportLibrary └── androidSupportLibrary.iml ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── help │ │ ├── app_help.html │ │ ├── beacon_help.html │ │ ├── colorpicker_help.html │ │ ├── controller_help.html │ │ ├── info_help.html │ │ ├── licenses.html │ │ ├── neopixel_help.html │ │ ├── pinio_help.html │ │ └── uart_help.html │ └── neopixel │ │ ├── NeopixelBoards.json │ │ ├── NeopixelDefaultPalette.json │ │ ├── NeopixelTypes.json │ │ └── Neopixel_Arduino.zip │ ├── java │ └── com │ │ └── adafruit │ │ └── bluefruit │ │ └── le │ │ └── connect │ │ ├── app │ │ ├── BeaconActivity.java │ │ ├── ColorPickerActivity.java │ │ ├── CommonHelpActivity.java │ │ ├── ControllerActivity.java │ │ ├── IBeaconFragment.java │ │ ├── InfoActivity.java │ │ ├── MainActivity.java │ │ ├── MainHelpActivity.java │ │ ├── PadActivity.java │ │ ├── PinIOActivity.java │ │ ├── URIBeaconFragment.java │ │ ├── UartActivity.java │ │ ├── UartDataChunk.java │ │ ├── UartInterfaceActivity.java │ │ ├── UriBeaconUtils.java │ │ ├── neopixel │ │ │ ├── NeopixelActivity.java │ │ │ ├── NeopixelBoard.java │ │ │ ├── NeopixelBoardSelectorActivity.java │ │ │ ├── NeopixelBoardTypeActivity.java │ │ │ ├── NeopixelColorPickerActivity.java │ │ │ └── NeopixelHelpActivity.java │ │ ├── settings │ │ │ ├── ConnectedSettingsActivity.java │ │ │ ├── MqttUartSettingsActivity.java │ │ │ ├── MqttUartSettingsCodeReaderActivity.java │ │ │ ├── PreferencesFragment.java │ │ │ ├── SettingsActivity.java │ │ │ └── barcode │ │ │ │ ├── BarcodeGraphic.java │ │ │ │ ├── BarcodeGraphicTracker.java │ │ │ │ ├── BarcodeTrackerFactory.java │ │ │ │ ├── CameraSource.java │ │ │ │ ├── CameraSourcePreview.java │ │ │ │ └── GraphicOverlay.java │ │ ├── shortener │ │ │ ├── BitlyShortenerAsyncTask.java │ │ │ └── ShortenerAsyncTask.java │ │ └── update │ │ │ ├── ApplicationFilesFragmentDialog.java │ │ │ ├── DfuService.java │ │ │ ├── DownloadTask.java │ │ │ ├── FirmwareUpdater.java │ │ │ ├── NotificationActivity.java │ │ │ ├── ProgressFragmentDialog.java │ │ │ └── ReleasesParser.java │ │ ├── ble │ │ ├── BleDevicesScanner.java │ │ ├── BleGattExecutor.java │ │ ├── BleManager.java │ │ ├── BleUtils.java │ │ ├── KnownUUIDs.java │ │ └── StandardUUIDs.java │ │ ├── mqtt │ │ ├── MqttManager.java │ │ └── MqttSettings.java │ │ ├── ui │ │ ├── keyboard │ │ │ ├── CustomEditTextFormatter.java │ │ │ └── CustomKeyboard.java │ │ ├── tabs │ │ │ ├── SlidingTabLayout.java │ │ │ └── SlidingTabStrip.java │ │ └── utils │ │ │ ├── DialogUtils.java │ │ │ ├── ExpandableHeightExpandableListView.java │ │ │ ├── ExpandableHeightListView.java │ │ │ ├── MetricsUtils.java │ │ │ └── TwoDimensionScrollView.java │ │ └── utils │ │ ├── FileUtils.java │ │ └── LegacyCompatFileProvider.java │ └── res │ ├── drawable-hdpi │ ├── ic_expand_less_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ ├── ic_rotate_right_white_36dp.png │ ├── ic_search_black_18dp.png │ ├── ic_select_all_white_36dp.png │ ├── ic_select_all_white_48dp.png │ ├── sym_keyboard_delete_holo_dark.png │ └── sym_keyboard_return_holo_dark.png │ ├── drawable-mdpi │ ├── ic_cancel_black_18dp.png │ ├── ic_expand_less_black_24dp.png │ ├── ic_expand_more_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ ├── ic_rotate_right_white_36dp.png │ ├── ic_search_black_18dp.png │ ├── ic_select_all_white_36dp.png │ ├── ic_select_all_white_48dp.png │ ├── signalstrength0.png │ ├── signalstrength1.png │ ├── signalstrength2.png │ ├── signalstrength3.png │ ├── signalstrength4.png │ ├── sym_keyboard_delete_holo_dark.png │ └── sym_keyboard_return_holo_dark.png │ ├── drawable-xhdpi │ ├── adaflower.png │ ├── adafruitlogo2012.png │ ├── ic_cancel_black_18dp.png │ ├── ic_expand_less_black_24dp.png │ ├── ic_expand_more_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ ├── ic_rotate_right_white_36dp.png │ ├── ic_search_black_18dp.png │ ├── ic_select_all_white_36dp.png │ ├── ic_select_all_white_48dp.png │ ├── pad_arrow_button_down.png │ ├── pad_arrow_button_left.png │ ├── pad_arrow_button_right.png │ ├── pad_arrow_button_up.png │ ├── pad_button_exit.png │ ├── pad_button_numbers_1.png │ ├── pad_button_numbers_2.png │ ├── pad_button_numbers_3.png │ ├── pad_button_numbers_4.png │ ├── sym_keyboard_delete_holo_dark.png │ └── sym_keyboard_return_holo_dark.png │ ├── drawable-xxhdpi │ ├── ic_cancel_black_18dp.png │ ├── ic_close_black_18dp.png │ ├── ic_expand_less_black_24dp.png │ ├── ic_expand_more_black_24dp.png │ ├── ic_info_outline_menu.png │ ├── ic_more_vert_black_24dp.png │ ├── ic_refresh_black_24dp.png │ ├── ic_refresh_menu.png │ ├── ic_rotate_right_white_36dp.png │ ├── ic_search_black_18dp.png │ ├── ic_select_all_white_36dp.png │ ├── ic_select_all_white_48dp.png │ ├── ic_settings_white_24dp.png │ ├── ic_sync_black_24dp.png │ ├── ic_sync_white_24dp.png │ ├── mqtt_connected.png │ ├── mqtt_connecting1.png │ ├── mqtt_connecting2.png │ ├── mqtt_connecting3.png │ ├── mqtt_disconnected.png │ ├── sym_keyboard_delete_holo_dark.png │ └── sym_keyboard_return_holo_dark.png │ ├── drawable-xxxhdpi │ ├── ic_cancel_black_18dp.png │ ├── ic_expand_less_black_24dp.png │ ├── ic_expand_more_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ ├── ic_pie_chart_outlined_white_28dp.png │ ├── ic_rotate_right_white_36dp.png │ ├── ic_search_black_18dp.png │ ├── ic_select_all_white_36dp.png │ ├── ic_select_all_white_48dp.png │ └── ic_settings_white_28dp.png │ ├── drawable │ ├── border_gray.xml │ ├── border_white.xml │ ├── neopixel_led.xml │ ├── neopixel_palettecolor.xml │ ├── roundedborders_blue.xml │ ├── roundedborders_gray.xml │ └── roundedbutton.xml │ ├── layout │ ├── activity_beacon.xml │ ├── activity_color_picker.xml │ ├── activity_commonhelp.xml │ ├── activity_connected_settings.xml │ ├── activity_controller.xml │ ├── activity_info.xml │ ├── activity_main.xml │ ├── activity_mainhelp.xml │ ├── activity_mqttsettings.xml │ ├── activity_mqttsettingscodereader.xml │ ├── activity_neopixel.xml │ ├── activity_neopixel_boardselector.xml │ ├── activity_neopixel_boardtype.xml │ ├── activity_neopixelhelp.xml │ ├── activity_pad.xml │ ├── activity_pin_io.xml │ ├── activity_uart.xml │ ├── fragment_ibeacon.xml │ ├── fragment_uribeacon.xml │ ├── layout_application_files_dialog.xml │ ├── layout_connected_settings_item_release.xml │ ├── layout_controller_interface_title.xml │ ├── layout_controller_streamitem_child.xml │ ├── layout_controller_streamitem_title.xml │ ├── layout_info_item_characteristic.xml │ ├── layout_info_item_descriptor.xml │ ├── layout_info_item_service.xml │ ├── layout_neopixel_led.xml │ ├── layout_neopixel_list_item.xml │ ├── layout_neopixel_palette_item.xml │ ├── layout_pinio_item_child.xml │ ├── layout_pinio_item_title.xml │ ├── layout_scan_item_child.xml │ ├── layout_scan_item_title.xml │ └── layout_uart_datachunkitem.xml │ ├── menu │ ├── menu_beacon.xml │ ├── menu_color_picker.xml │ ├── menu_controller.xml │ ├── menu_info.xml │ ├── menu_main.xml │ ├── menu_mqtt.xml │ ├── menu_neopixel.xml │ ├── menu_pad.xml │ ├── menu_pin_io.xml │ ├── menu_scan_filters_name.xml │ └── menu_uart.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-land │ └── fraction.xml │ ├── values-v21 │ └── styles.xml │ ├── values-w820dp │ └── dimens.xml │ ├── values │ ├── colors.xml │ ├── dimens.xml │ ├── fraction.xml │ ├── strings.xml │ └── styles.xml │ ├── xml-land │ └── keyboard_binary.xml │ └── xml │ ├── keyboard_binary.xml │ ├── keyboard_decimal.xml │ ├── keyboard_hexadecimal.xml │ ├── preferences.xml │ └── provider_paths.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── license.txt └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | BuildConfig.java 8 | R.java 9 | dFULibrary/build 10 | app-release.apk 11 | manifest-merger-release-report.txt 12 | app/release 13 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /BluefruitLEConnect_Android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Bluefruit LE Connect for Android - DEPRECATED 2 | ================================ 3 | 4 | This repository is no longer supported or maintained - for the latest version of this app go to - https://github.com/adafruit/Bluefruit_LE_Connect_Android_v2 5 | 6 | Android port of Adafruit's Bluefruit LE Connect app for iOS. 7 | 8 | This application works with the following Adafruit breakouts: 9 | 10 | - [Bluefruit LE Friend](https://www.adafruit.com/product/2267) 11 | - [Bluefruit LE UART Friend](https://www.adafruit.com/product/2479) 12 | - [Bluefruit LE SPI Friend](https://www.adafruit.com/product/2633) 13 | - [Bluefruit LE Shield](https://www.adafruit.com/products/2746) 14 | - [Bluefruit LE Micro](https://www.adafruit.com/product/2661) 15 | - [Feather 32u4 Bluefruit LE](https://www.adafruit.com/product/2829) 16 | - [Feather M0 Bluefruit LE](https://www.adafruit.com/products/2995) 17 | 18 | Bluefruit LE Connect enables the exchange of information between your Bluefruit LE breakout and your BLE enabled Android device (Android 4.4 and higher required). 19 | 20 | The application also enables [over the air updates](https://learn.adafruit.com/introducing-the-adafruit-bluefruit-le-uart-friend/dfu-updates) to keep your Bluefruit module up to date with the latest [Bluefruit LE firmware](https://github.com/adafruit/Adafruit_BluefruitLE_Firmware). 21 | 22 | ## License 23 | 24 | Unless otherwise specified, all files produced by Adafruit are covered by an [MIT license](https://github.com/adafruit/Bluefruit_LE_Connect_Android/blob/master/license.txt). 25 | 26 | Files produced by Nordic Semiconductors are covered by their own license terms, as detailed in the file headers and appropriate folders. Please carefully review the license requirements before using this source code in your own application. 27 | -------------------------------------------------------------------------------- /androidSupportLibrary/androidSupportLibrary.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | buildToolsVersion '27.0.3' 6 | 7 | defaultConfig { 8 | applicationId "com.adafruit.bluefruit.le.connect" 9 | minSdkVersion 19 10 | targetSdkVersion 25 11 | versionCode 20 12 | versionName "2.3.1" 13 | } 14 | 15 | useLibrary 'org.apache.http.legacy' // TODO: remove Apache library and use HttpURLConnection (Apache is deprecated since Android 6.0) 16 | 17 | aaptOptions { 18 | noCompress "zip" 19 | } 20 | 21 | buildTypes { 22 | release { 23 | minifyEnabled true 24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 25 | } 26 | } 27 | } 28 | 29 | repositories { 30 | maven { url "https://repo.eclipse.org/content/repositories/paho-releases/" } 31 | maven { url "https://s3.amazonaws.com/repo.commonsware.com" } 32 | google() 33 | } 34 | 35 | dependencies { 36 | implementation fileTree(dir: 'libs', include: ['*.jar']) 37 | implementation 'no.nordicsemi.android:dfu:1.0.4' 38 | implementation(group: 'org.eclipse.paho', name: 'org.eclipse.paho.android.service', version: '1.0.2') { 39 | exclude module: 'support-v4' 40 | } 41 | implementation 'com.android.support:appcompat-v7:27.1.0' 42 | implementation 'com.larswerkman:HoloColorPicker:1.4' 43 | implementation 'com.android.support:design:27.1.0' 44 | 45 | implementation 'com.google.android.gms:play-services-analytics:11.6.2' 46 | implementation 'com.google.android.gms:play-services-location:11.6.2' 47 | implementation 'com.google.android.gms:play-services-vision:11.6.2' 48 | 49 | implementation 'com.commonsware.cwac:provider:0.5.1' 50 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/antonio/Development/_androidsdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | -keep class * extends java.util.ListResourceBundle { 20 | protected Object[][] getContents(); 21 | } 22 | 23 | -keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { 24 | public static final *** NULL; 25 | } 26 | 27 | -keepnames @com.google.android.gms.common.annotation.KeepName class * 28 | -keepclassmembernames class * { 29 | @com.google.android.gms.common.annotation.KeepName *; 30 | } 31 | 32 | -keepnames class * implements android.os.Parcelable { 33 | public static final ** CREATOR; 34 | } 35 | 36 | # Custom Proguard settings 37 | -keep class * extends android.app.Activity 38 | -assumenosideeffects class android.util.Log { 39 | public static boolean isLoggable(java.lang.String, int); 40 | public static int v(...); 41 | public static int i(...); 42 | public static int w(...); 43 | public static int d(...); 44 | public static int e(...); 45 | } 46 | 47 | # Nordic DFU library 48 | -keep class no.nordicsemi.android.dfu.** { *; } 49 | 50 | # Paho library logger 51 | -keep class org.eclipse.paho.client.mqttv3.logging.JSR47Logger { 52 | *; 53 | } 54 | 55 | # Avoid warnings for old code in Paho 1.0.2 on Android Studio 2 56 | -keep class org.eclipse.paho.client.mqttv3.persist.** { *; } 57 | -dontwarn org.eclipse.paho.client.mqttv3.persist.** 58 | -keepattributes Exceptions, Signature, InnerClasses -------------------------------------------------------------------------------- /app/src/main/assets/help/app_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Configure Bluefruit LE using instructions found here: 5 | https://www.adafruit.com/bluefruitle 6 |
7 |
8 | 9 | Drag the table down and release to clear the list of found peripherals and begin scanning 10 |
11 |
12 | Tap a row in the table to view a peripheral's advertisement data. 13 |
14 |
15 | Each peripheral's Received Signal Strength (RSSI) is displayed to the left of its name. 16 |
17 |
18 | Tap a row's connect button to connect the corresponding device in one of the available 19 | modes: 20 |
21 |
22 | 23 | 24 | 42 | 43 |
44 | Note - If a peripheral does not offer the UART service, 45 | tapping Connect will automatically enter Info mode 46 |
47 |
48 | 49 | Privacy policy: 50 |
51 | https://www.adafruit.com/appprivacy 52 |
53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/assets/help/beacon_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Instructions: 4 |
5 |
6 |
  • Tap the Message field at the bottom of the screen.
  • 7 |
    8 | 9 |
  • Enter the ASCII string you want to send.
  • 10 |
    11 | 12 |
  • Send a message by pressing the keyboard's Done button.
  • 13 |
    14 | 15 |
  • Use the ASCII/Hex control above the main console view to control the display format of messages. 16 |
  • 17 |
    18 | 19 |
  • Use the Copy button to copy the contents of the console to the clipboard.
  • 20 |
    21 | 22 |
  • Use the Clear button to clear the console's contents. 23 |
  • 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/assets/help/colorpicker_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

    The Color Picker send a color's RGB values to Bluefruit LE. This can be used to control the state of RGB LEDs such as Neopixels.

    4 |
    5 |
  • Touch the color wheel to choose desired color
  • 6 |
    7 |
  • Press Send to send the chosen color's red, green, and blue values to Bluefruit via UART in the following format:
  • 8 | Format: [ ‘!’ ] [ ‘C’ ] [ float r ] [ float g ] [ float b ] 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/assets/help/controller_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

    The Controller module streams sensor data from your iOS device to Bluefruit LE over UART at a frequency of 10Hz. Activation of a switch will begin sending relevant data. Each 4 | packet sent begins with single byte char “!” (0x21) followed by a single byte char initial, and sensor data encoded as float values of 4 byte length

    5 |
    6 |
  • Quaternion sends Android Device Motion data to describe device attitude. This data is derived from Accelerometer, Gyro, and Magnetometer readings.
  • 7 | Format: [ ‘!’ ] [ ‘Q’ ] [ float x ] [ float y ] [ float z ] [ float w ] 8 |
    9 |
    10 |
  • Accelerometer sends raw accelerometer data 11 | Format: [ ‘!’ ] [ ‘A’ ] [ float x ] [ float y ] [ float z ] 12 |
    13 |
    14 |
  • Gyro sends raw gyroscope data as:
  • 15 | Format: [ ‘!’ ] [ ‘G’ ] [ float x ] [ float y ] [ float z ] 16 |
    17 |
    18 |
  • Magnetometer sends raw magnetometer data which is uncalibrated and does not account for interference from source device.
  • 19 | Format: [ ‘!’ ] [ ‘M’ ] [ float x ] [ float y ] [ float z ] 20 |
    21 |
    22 |
  • Location sends GPS data and requires user permission before initial use.
  • 23 | Format: [ ‘!’ ] [ ‘L’ ] [ float latitude ] [ float longitude ] [ float altitude ] 24 |
    25 |
    26 | The Control Pad function provides a familiar momentary button interface for common control scenarios. Data is sent on the press and release of each button. Each packet consists of 27 | 4 bytes, each representing a char value. The first two chars identify the packet as a button message, the third specifies a button, and the fourth signifies either a press or 28 | release. Example: 29 | 30 | Button 4 pressed: [ ‘!’ ] [ ‘B’ ] [ ‘4’ ] [ ‘1’ ] 31 | Button 4 released: [ ‘!’ ] [ ‘B’ ] [ ‘4’ ] [ ‘0’ ] 32 |
    33 |
    34 | Note: Any activated sensor data streams will continue while using the Control Pad. 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/assets/help/info_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
  • Each section of the table represents one of the peripheral's services followed by its relevant 4 | characteristics. 5 |
  • 6 |
    7 | 8 |
  • If a service or characteristic uses a predefined UUID, a standardized name is displayed. 9 | Otherwise the UUID value is shown. 10 |
  • 11 |
    12 | 13 |
  • If a characteristic contains a readable value, that value is displayed at the bottom of the 14 | characteristic's table row 15 |
  • 16 |
    17 | 18 | -------------------------------------------------------------------------------- /app/src/main/assets/help/licenses.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

    Firmware Update based on Nordic DFU Library

    8 | 9 |

    Copyright (c) 2015, Nordic Semiconductor All rights reserved.

    10 | 11 |

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

    12 | 13 |

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

    14 | 15 |

    * 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.

    16 | 17 |

    * Neither the name of Android-DFU-Library nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

    18 | 19 |

    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.

    20 | 21 | 22 |
    23 |
    24 | 25 | 26 | 27 |

    Color picker based on HoloColorPicker by Lars Werkman.

    28 | 29 |

    Copyright 2012 Lars Werkman

    30 | 31 |

    Licensed under the Apache License, Version 2.0 (the "License"); 32 | you may not use this file except in compliance with the License. 33 | You may obtain a copy of the License at

    34 | 35 |

    http://www.apache.org/licenses/LICENSE-2.0

    36 | 37 |

    Unless required by applicable law or agreed to in writing, software 38 | distributed under the License is distributed on an "AS IS" BASIS, 39 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 40 | See the License for the specific language governing permissions and 41 | limitations under the License.

    42 | 43 |
    44 |
    45 | 46 | 47 | 48 |

    LegacyCompatFileProvider by CommonsWare.

    49 | 50 |

    Copyright 2015 CommonsWare, LLC

    51 | 52 |

    Licensed under the Apache License, Version 2.0 (the "License"); 53 | you may not use this file except in compliance with the License. 54 | You may obtain a copy of the License at

    55 | 56 |

    http://www.apache.org/licenses/LICENSE-2.0

    57 | 58 |

    Unless required by applicable law or agreed to in writing, software 59 | distributed under the License is distributed on an "AS IS" BASIS, 60 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 61 | See the License for the specific language governing permissions and 62 | limitations under the License.

    63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/assets/help/neopixel_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | To use the NeoPixel application: 5 |
    6 |
  • Export the Bluefruit LE Connect Neopixel sketch from this app using the export icon
  • 7 |
    8 |
  • Open the exported sketch on the Arduino IDE and run it
  • 9 |
    10 |
  • Connect to your Bluefruit module and switch to the NeoPixel utility
  • 11 |
    12 |
  • Click the 'gear' icon and set your board size (8x4, 1x8, etc.)
  • 13 |
    14 |
  • Click the Connect button in the Bluefruit LE Connect app
  • 15 |
    16 |
  • Select a color and tap individual pixels to set them
  • 17 |
    18 |
  • Adjust overall brightness as desired using the Brightness slider
  • 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/assets/help/pinio_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Instructions: 4 |
    5 |
    6 |
  • Tap a row in the table corresponding to the Arduino pin you want to control.
  • 7 |
    8 | 9 |
  • Select a pin mode: 10 | 16 |
  • 17 |
    18 | 19 |
  • Set an Output pin's state using the Low/High control.
  • 20 |
    21 | 22 |
  • Set a PWM pin's output value using the slider control.
  • 23 |
    24 | 25 |
  • Once finished setting a pin's mode or state, you can close it by tapping the empty space near it's top - or by selecting another row. 26 |
  • 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/assets/help/uart_help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Instructions: 4 |
    5 |
    6 |
  • Tap the Message field at the bottom of the screen.
  • 7 |
    8 | 9 |
  • Enter the ASCII string you want to send.
  • 10 |
    11 | 12 |
  • Send a message by pressing the keyboard's Done button.
  • 13 |
    14 | 15 |
  • Use the ASCII/Hex control above the main console view to control the display format of 16 | messages. 17 |
  • 18 |
    19 | 20 |
  • Use the Copy button to copy the contents of the console to the clipboard.
  • 21 |
    22 | 23 |
  • Use the Clear button to clear the console's contents. 24 |
  • 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/assets/neopixel/NeopixelBoards.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "height": 4, 4 | "stride": 8, 5 | "width": 8, 6 | "components": 3, 7 | "name": "8x4" 8 | }, 9 | { 10 | "height": 8, 11 | "stride": 8, 12 | "width": 8, 13 | "components": 3, 14 | "name": "8x8" 15 | }, 16 | { 17 | "height": 1, 18 | "stride": 8, 19 | "width": 8, 20 | "components": 3, 21 | "name": "1x8" 22 | } 23 | ] -------------------------------------------------------------------------------- /app/src/main/assets/neopixel/NeopixelDefaultPalette.json: -------------------------------------------------------------------------------- 1 | [ 2 | "FF0000", 3 | "FF8000", 4 | "FFFF00", 5 | "80FF00", 6 | "00FF00", 7 | "00FF80", 8 | "00FFFF", 9 | "0080FF", 10 | "0000FF", 11 | "7F00FF", 12 | "FF00FF", 13 | "FF007F", 14 | "808080", 15 | "000000", 16 | "FFFFFF" 17 | ] -------------------------------------------------------------------------------- /app/src/main/assets/neopixel/NeopixelTypes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "value": 82, 4 | "name": "GRB 800kHz" 5 | }, 6 | { 7 | "value": 210, 8 | "name": "GRBW 800kHz" 9 | } 10 | ] -------------------------------------------------------------------------------- /app/src/main/assets/neopixel/Neopixel_Arduino.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/assets/neopixel/Neopixel_Arduino.zip -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/CommonHelpActivity.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.v7.app.ActionBar; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.webkit.WebView; 8 | 9 | import com.adafruit.bluefruit.le.connect.R; 10 | 11 | public class CommonHelpActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_commonhelp); 17 | 18 | setupHelp(); 19 | } 20 | 21 | protected void setupHelp() { 22 | // Title 23 | String title = getIntent().getExtras().getString("title"); 24 | ActionBar actionBar = getSupportActionBar(); 25 | if (actionBar != null) { 26 | actionBar.setTitle(title); 27 | } 28 | 29 | // Text 30 | String asset = getIntent().getExtras().getString("help"); 31 | WebView infoWebView = (WebView) findViewById(R.id.infoWebView); 32 | if (infoWebView != null) { 33 | infoWebView.setBackgroundColor(Color.TRANSPARENT); 34 | infoWebView.loadUrl("file:///android_asset/help/" + asset); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/MainHelpActivity.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.webkit.WebView; 7 | import android.widget.TextView; 8 | 9 | import com.adafruit.bluefruit.le.connect.BuildConfig; 10 | import com.adafruit.bluefruit.le.connect.R; 11 | 12 | 13 | public class MainHelpActivity extends AppCompatActivity { 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_mainhelp); 19 | 20 | TextView versionTextView = (TextView) findViewById(R.id.versionTextView); 21 | if (versionTextView != null) { 22 | versionTextView.setText("v" + BuildConfig.VERSION_NAME); 23 | } 24 | 25 | WebView infoWebView = (WebView) findViewById(R.id.infoWebView); 26 | if (infoWebView != null) { 27 | infoWebView.setBackgroundColor(Color.TRANSPARENT); 28 | infoWebView.loadUrl("file:///android_asset/help/app_help.html"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/UartDataChunk.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app; 2 | 3 | class UartDataChunk { 4 | static final int TRANSFERMODE_TX = 0; 5 | static final int TRANSFERMODE_RX = 1; 6 | 7 | private long mTimestamp; // in millis 8 | private int mMode; 9 | private byte[] mData; 10 | 11 | UartDataChunk(long timestamp, int mode, byte[] bytes) { 12 | mTimestamp = timestamp; 13 | mMode = mode; 14 | mData = bytes; 15 | } 16 | 17 | long getTimestamp() { 18 | return mTimestamp; 19 | } 20 | 21 | public int getMode() { 22 | return mMode; 23 | } 24 | 25 | public byte[] getData() { 26 | return mData; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/UriBeaconUtils.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app; 2 | 3 | import com.adafruit.bluefruit.le.connect.ble.BleUtils; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | import java.util.Arrays; 7 | 8 | class UriBeaconUtils { 9 | 10 | private static String getSchemeFromPrefix(byte schemePrefix) { 11 | switch (schemePrefix) { 12 | case 0: 13 | return "http://www."; 14 | case 1: 15 | return "https://www."; 16 | case 2: 17 | return "http://"; 18 | case 3: 19 | return "https://"; 20 | case 4: 21 | return "urn:uuid:"; 22 | default: 23 | return null; 24 | } 25 | } 26 | 27 | private static String getUrlEncodingFromByte(byte value) { 28 | switch (value) { 29 | case 0: 30 | return ".com/"; 31 | case 1: 32 | return ".org/"; 33 | case 2: 34 | return ".edu/"; 35 | case 3: 36 | return ".net/"; 37 | case 4: 38 | return ".info/"; 39 | case 5: 40 | return ".biz/"; 41 | case 6: 42 | return ".gov/"; 43 | case 7: 44 | return ".com/"; 45 | case 8: 46 | return ".org/"; 47 | case 9: 48 | return ".edu/"; 49 | case 10: 50 | return ".net/"; 51 | case 11: 52 | return ".info/"; 53 | case 12: 54 | return ".biz/"; 55 | case 13: 56 | return ".gov/"; 57 | default: 58 | return null; 59 | } 60 | } 61 | 62 | static String getUriFromAdvertisingPacket(byte[] scanRecord) { 63 | byte schemeByte = scanRecord[10]; 64 | String scheme = UriBeaconUtils.getSchemeFromPrefix(schemeByte); 65 | 66 | String url = ""; 67 | if (schemeByte == 0x04) // Special case for urn:uuid 68 | { 69 | byte[] urlBytes = Arrays.copyOfRange(scanRecord, 11, 11 + 16); 70 | url = BleUtils.getUuidStringFromByteArray(urlBytes); 71 | } else { 72 | final int length = scanRecord[4] - 6; // 6 fixed fields bytes (uri length is total lenght-6) 73 | byte[] urlBytes = Arrays.copyOfRange(scanRecord, 11, 11 + length); 74 | 75 | try { 76 | url = new String(urlBytes, "UTF-8"); 77 | } catch (UnsupportedEncodingException e) { 78 | e.printStackTrace(); 79 | } 80 | 81 | for (int i = urlBytes.length - 1; i >= 0; i--) // Go backwards because we are replacing single characters with strings that will change the url lenght 82 | { 83 | String urlEncoding = getUrlEncodingFromByte(urlBytes[i]); 84 | if (urlEncoding != null) { 85 | url = new StringBuffer(url).insert(i, urlEncoding).toString(); 86 | } 87 | } 88 | } 89 | 90 | String text = scheme + url; 91 | return text; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/neopixel/NeopixelBoard.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.neopixel; 2 | 3 | 4 | import android.content.Context; 5 | 6 | import com.adafruit.bluefruit.le.connect.utils.FileUtils; 7 | 8 | import org.json.JSONArray; 9 | import org.json.JSONException; 10 | import org.json.JSONObject; 11 | 12 | import java.io.File; 13 | 14 | public class NeopixelBoard { 15 | static final short kDefaultType = 82; 16 | 17 | String name; 18 | byte width, height; 19 | byte components; 20 | byte stride; 21 | short type; 22 | 23 | public NeopixelBoard(String name, byte width, byte height, byte components, byte stride, short type) { 24 | this.name = name; 25 | this.width = width; 26 | this.height = height; 27 | this.components = components; 28 | this.stride = stride; 29 | this.type = type; 30 | } 31 | 32 | public NeopixelBoard(Context context, int standardIndex, short type) { 33 | 34 | String boardsJsonString = FileUtils.readAssetsFile("neopixel" + File.separator + "NeopixelBoards.json", context.getAssets()); 35 | try { 36 | JSONArray boardsArray = new JSONArray(boardsJsonString); 37 | JSONObject boardJson = boardsArray.getJSONObject(standardIndex); 38 | 39 | name = boardJson.getString("name"); 40 | width = (byte) boardJson.getInt("width"); 41 | height = (byte) boardJson.getInt("height"); 42 | components = (byte) boardJson.getInt("components"); 43 | stride = (byte) boardJson.getInt("stride"); 44 | this.type = type; 45 | 46 | } catch (JSONException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/neopixel/NeopixelBoardTypeActivity.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.neopixel; 2 | 3 | import android.content.Intent; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.util.Log; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.widget.Button; 13 | import android.widget.EditText; 14 | 15 | import com.adafruit.bluefruit.le.connect.utils.FileUtils; 16 | import com.adafruit.bluefruit.le.connect.R; 17 | 18 | import org.json.JSONArray; 19 | import org.json.JSONException; 20 | import org.json.JSONObject; 21 | 22 | import java.io.File; 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | public class NeopixelBoardTypeActivity extends AppCompatActivity { 27 | // Log 28 | private final static String TAG = NeopixelBoardTypeActivity.class.getSimpleName(); 29 | 30 | // Result return 31 | public static final String kActivityParameter_CurrentType = "kActivityParameter_CurrentType"; 32 | public static final String kActivityResult_BoardTypeResultKey = "kActivityResult_BoardTypeResultKey"; 33 | 34 | // UI 35 | private EditText mValueEditText; 36 | 37 | // Data 38 | private class NeopixelType { 39 | public String name; 40 | public short value; 41 | } 42 | private List mDefaultTypes; 43 | private short mCurrentType; 44 | 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | setContentView(R.layout.activity_neopixel_boardtype); 49 | 50 | mCurrentType = getIntent().getShortExtra(kActivityParameter_CurrentType, NeopixelBoard.kDefaultType); 51 | 52 | // Read standard board types data 53 | String boardsJsonString = FileUtils.readAssetsFile("neopixel" + File.separator + "NeopixelTypes.json", getAssets()); 54 | try { 55 | mDefaultTypes = new ArrayList<>(); 56 | JSONArray boardsArray = new JSONArray(boardsJsonString); 57 | for (int i = 0; i < boardsArray.length(); i++) { 58 | JSONObject boardJsonObject = boardsArray.getJSONObject(i); 59 | NeopixelType type = new NeopixelType(); 60 | type.name = boardJsonObject.getString("name"); 61 | type.value = (short)boardJsonObject.getInt("value"); 62 | 63 | mDefaultTypes.add(type); 64 | } 65 | } catch (JSONException e) { 66 | Log.e(TAG, "Error decoding default boards"); 67 | } 68 | 69 | // UI 70 | mValueEditText = (EditText) findViewById(R.id.valueEditText); 71 | mValueEditText.setText(String.valueOf(mCurrentType)); 72 | 73 | RecyclerView standardSizesRecyclerView = (RecyclerView) findViewById(R.id.standardTypesRecyclerView); 74 | if (standardSizesRecyclerView != null) { 75 | standardSizesRecyclerView.setHasFixedSize(true); 76 | standardSizesRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); 77 | RecyclerView.Adapter standardBoardSizesAdapter = new StandardBoardTypesAdapter(); 78 | standardSizesRecyclerView.setAdapter(standardBoardSizesAdapter); 79 | } 80 | 81 | } 82 | 83 | public void onClickSetValue(View view) { 84 | String valueString = String.valueOf(mValueEditText.getText()); 85 | short value = NeopixelBoard.kDefaultType; 86 | try { 87 | value = Short.parseShort(valueString); 88 | } catch (Exception e) { 89 | Log.d(TAG, "Cannot parse value"); 90 | } 91 | mCurrentType = value; 92 | 93 | Intent output = new Intent(); 94 | output.putExtra(kActivityResult_BoardTypeResultKey, mCurrentType); 95 | setResult(RESULT_OK, output); 96 | finish(); 97 | } 98 | 99 | // region BoardTypesAdapter 100 | public class StandardBoardTypesAdapter extends RecyclerView.Adapter { 101 | 102 | public class ViewHolder extends RecyclerView.ViewHolder { 103 | public Button mItem; 104 | public View mCheckboxView; 105 | 106 | public ViewHolder(ViewGroup view) { 107 | super(view); 108 | mItem = (Button) view.findViewById(R.id.itemView); 109 | mCheckboxView = view.findViewById(R.id.itemCheckBox); 110 | } 111 | } 112 | 113 | @Override 114 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 115 | ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_neopixel_list_item, parent, false); 116 | final ViewHolder viewHolder = new ViewHolder(view); 117 | return viewHolder; 118 | } 119 | 120 | @Override 121 | public void onBindViewHolder(ViewHolder holder, int position) { 122 | 123 | final NeopixelType type = mDefaultTypes.get(position); 124 | holder.mItem.setText(type.name); 125 | final boolean isCurrentType = type.value == mCurrentType; 126 | holder.mCheckboxView.setVisibility(isCurrentType ? View.VISIBLE: View.GONE); 127 | 128 | holder.mItem.setOnClickListener(new View.OnClickListener() { 129 | @Override 130 | public void onClick(View v) { 131 | 132 | mCurrentType = type.value; 133 | mValueEditText.setText(String.valueOf(mCurrentType)); 134 | notifyDataSetChanged(); 135 | } 136 | }); 137 | } 138 | 139 | @Override 140 | public int getItemCount() { 141 | return mDefaultTypes.size(); 142 | } 143 | } 144 | 145 | // endregion 146 | } 147 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/neopixel/NeopixelColorPickerActivity.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.neopixel; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.TextView; 10 | 11 | import com.adafruit.bluefruit.le.connect.R; 12 | import com.larswerkman.holocolorpicker.ColorPicker; 13 | import com.larswerkman.holocolorpicker.SaturationBar; 14 | import com.larswerkman.holocolorpicker.ValueBar; 15 | 16 | public class NeopixelColorPickerActivity extends AppCompatActivity implements ColorPicker.OnColorChangedListener { 17 | 18 | // Result return 19 | public static final String kActivityParameter_SelectedColorKey = "kActivityParameter_SelectedColorKey"; 20 | public static final String kActivityResult_SelectedColorResultKey = "kActivityResult_SelectedColorResultKey"; 21 | 22 | // UI 23 | private ColorPicker mColorPicker; 24 | private View mRgbColorView; 25 | private TextView mRgbTextView; 26 | 27 | private int mSelectedColor; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | // setContentView(R.layout.activity_neopixel_colorpicker); 33 | setContentView(R.layout.activity_color_picker); 34 | 35 | Intent intent = getIntent(); 36 | mSelectedColor = intent.getIntExtra(kActivityParameter_SelectedColorKey, Color.WHITE); 37 | 38 | // UI 39 | mRgbColorView = findViewById(R.id.rgbColorView); 40 | mRgbTextView = (TextView) findViewById(R.id.rgbTextView); 41 | 42 | SaturationBar mSaturationBar = (SaturationBar) findViewById(R.id.saturationbar); 43 | ValueBar mValueBar = (ValueBar) findViewById(R.id.valuebar); 44 | mColorPicker = (ColorPicker) findViewById(R.id.colorPicker); 45 | if (mColorPicker != null) { 46 | mColorPicker.addSaturationBar(mSaturationBar); 47 | mColorPicker.addValueBar(mValueBar); 48 | mColorPicker.setOnColorChangedListener(this); 49 | 50 | mColorPicker.setOldCenterColor(mSelectedColor); 51 | mColorPicker.setColor(mSelectedColor); 52 | } 53 | onColorChanged(mSelectedColor); 54 | 55 | Button sendButton = (Button) findViewById(R.id.sendButton); 56 | sendButton.setText(R.string.neopixel_colorpicker_setcolor); 57 | 58 | } 59 | 60 | @Override 61 | public void onColorChanged(int color) { 62 | // Save selected color 63 | mSelectedColor = color; 64 | 65 | // Update UI 66 | mRgbColorView.setBackgroundColor(color); 67 | 68 | final int r = (color >> 16) & 0xFF; 69 | final int g = (color >> 8) & 0xFF; 70 | final int b = (color >> 0) & 0xFF; 71 | final String text = String.format(getString(R.string.colorpicker_rgbformat), r, g, b); 72 | mRgbTextView.setText(text); 73 | 74 | } 75 | 76 | public void onClickSend(View view) { 77 | Intent output = new Intent(); 78 | output.putExtra(kActivityResult_SelectedColorResultKey, mSelectedColor); 79 | setResult(RESULT_OK, output); 80 | finish(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/neopixel/NeopixelHelpActivity.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.neopixel; 2 | 3 | import android.content.Intent; 4 | import android.content.res.AssetManager; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.support.v4.content.FileProvider; 8 | import android.util.Log; 9 | import android.view.View; 10 | 11 | import com.adafruit.bluefruit.le.connect.R; 12 | import com.adafruit.bluefruit.le.connect.app.CommonHelpActivity; 13 | 14 | import java.io.File; 15 | import java.io.FileOutputStream; 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | 19 | public class NeopixelHelpActivity extends CommonHelpActivity { 20 | 21 | // Constants 22 | private static final String AUTHORITY = "com.adafruit.bluefruit.le.connect.fileprovider"; // Same as the authority field on the manifest provider 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_neopixelhelp); 28 | 29 | setupHelp(); 30 | } 31 | 32 | public void onClickExportSketch(View view) { 33 | exportSketch(); 34 | } 35 | 36 | private void exportSketch() { 37 | 38 | // Copy file from assets to FilesDir 39 | String filename = "Neopixel_Arduino.zip"; 40 | File file = new File(getFilesDir(), filename); 41 | AssetManager assets = getResources().getAssets(); 42 | try { 43 | copy(assets.open("neopixel" + File.separator + filename), file); 44 | } catch (IOException e) { 45 | Log.e("FileProvider", "Exception copying from assets", e); 46 | } 47 | 48 | // Export uri 49 | Uri uri = FileProvider.getUriForFile(this, AUTHORITY, file); 50 | 51 | if (uri != null) { 52 | Intent intentShareFile = new Intent(Intent.ACTION_SEND); 53 | intentShareFile.setType("application/zip"); 54 | 55 | intentShareFile.putExtra(Intent.EXTRA_STREAM, uri); 56 | 57 | intentShareFile.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.neopixel_help_export_subject)); 58 | intentShareFile.putExtra(Intent.EXTRA_TEXT, getString(R.string.neopixel_help_export_text)); 59 | intentShareFile.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // to avoid the android.os.FileUriExposedException on api 24+ 60 | startActivity(Intent.createChooser(intentShareFile, getString(R.string.neopixel_help_export_chooser_title))); 61 | } 62 | } 63 | 64 | private static void copy(InputStream in, File dst) throws IOException { 65 | FileOutputStream out = new FileOutputStream(dst); 66 | byte[] buf = new byte[1024]; 67 | int len; 68 | 69 | while ((len = in.read(buf)) > 0) { 70 | out.write(buf, 0, len); 71 | } 72 | 73 | in.close(); 74 | out.close(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/settings/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.settings; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | 6 | 7 | public class SettingsActivity extends AppCompatActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | 13 | getFragmentManager().beginTransaction().replace(android.R.id.content, new PreferencesFragment()).commit(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/settings/barcode/BarcodeGraphic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.adafruit.bluefruit.le.connect.app.settings.barcode; 17 | 18 | import android.graphics.Canvas; 19 | import android.graphics.Color; 20 | import android.graphics.Paint; 21 | import android.graphics.RectF; 22 | 23 | import com.google.android.gms.vision.barcode.Barcode; 24 | 25 | /** 26 | * Graphic instance for rendering barcode position, size, and ID within an associated graphic 27 | * overlay view. 28 | */ 29 | public class BarcodeGraphic extends GraphicOverlay.Graphic { 30 | 31 | private int mId; 32 | 33 | private static final int COLOR_CHOICES[] = { 34 | Color.BLUE, 35 | Color.CYAN, 36 | Color.GREEN 37 | }; 38 | 39 | private static int mCurrentColorIndex = 0; 40 | 41 | private Paint mRectPaint; 42 | private Paint mTextPaint; 43 | private volatile Barcode mBarcode; 44 | 45 | BarcodeGraphic(GraphicOverlay overlay) { 46 | super(overlay); 47 | 48 | mCurrentColorIndex = (mCurrentColorIndex + 1) % COLOR_CHOICES.length; 49 | final int selectedColor = COLOR_CHOICES[mCurrentColorIndex]; 50 | 51 | mRectPaint = new Paint(); 52 | mRectPaint.setColor(selectedColor); 53 | mRectPaint.setStyle(Paint.Style.STROKE); 54 | mRectPaint.setStrokeWidth(4.0f); 55 | 56 | mTextPaint = new Paint(); 57 | mTextPaint.setColor(selectedColor); 58 | mTextPaint.setTextSize(36.0f); 59 | } 60 | 61 | public int getId() { 62 | return mId; 63 | } 64 | 65 | public void setId(int id) { 66 | this.mId = id; 67 | } 68 | 69 | public Barcode getBarcode() { 70 | return mBarcode; 71 | } 72 | 73 | /** 74 | * Updates the barcode instance from the detection of the most recent frame. Invalidates the 75 | * relevant portions of the overlay to trigger a redraw. 76 | */ 77 | void updateItem(Barcode barcode) { 78 | mBarcode = barcode; 79 | postInvalidate(); 80 | } 81 | 82 | /** 83 | * Draws the barcode annotations for position, size, and raw value on the supplied canvas. 84 | */ 85 | @Override 86 | public void draw(Canvas canvas) { 87 | Barcode barcode = mBarcode; 88 | if (barcode == null) { 89 | return; 90 | } 91 | 92 | // Draws the bounding box around the barcode. 93 | RectF rect = new RectF(barcode.getBoundingBox()); 94 | rect.left = translateX(rect.left); 95 | rect.top = translateY(rect.top); 96 | rect.right = translateX(rect.right); 97 | rect.bottom = translateY(rect.bottom); 98 | canvas.drawRect(rect, mRectPaint); 99 | 100 | // Draws a label at the bottom of the barcode indicate the barcode value that was detected. 101 | //canvas.drawText(barcode.rawValue, rect.left, rect.bottom, mTextPaint); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/settings/barcode/BarcodeGraphicTracker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.adafruit.bluefruit.le.connect.app.settings.barcode; 17 | 18 | import com.google.android.gms.vision.Detector; 19 | import com.google.android.gms.vision.Tracker; 20 | import com.google.android.gms.vision.barcode.Barcode; 21 | 22 | /** 23 | * Generic tracker which is used for tracking or reading a barcode (and can really be used for 24 | * any type of item). This is used to receive newly detected items, add a graphical representation 25 | * to an overlay, update the graphics as the item changes, and remove the graphics when the item 26 | * goes away. 27 | */ 28 | public class BarcodeGraphicTracker extends Tracker { 29 | 30 | public interface BarcodeTrackerListener { 31 | void onCodeScanned(String contents); 32 | } 33 | 34 | 35 | private GraphicOverlay mOverlay; 36 | private BarcodeGraphic mGraphic; 37 | private BarcodeTrackerListener mListener; 38 | 39 | BarcodeGraphicTracker(GraphicOverlay overlay, BarcodeGraphic graphic, BarcodeGraphicTracker.BarcodeTrackerListener listener) { 40 | mOverlay = overlay; 41 | mGraphic = graphic; 42 | mListener = listener; 43 | } 44 | 45 | /** 46 | * Start tracking the detected item instance within the item overlay. 47 | */ 48 | @Override 49 | public void onNewItem(int id, Barcode item) { 50 | mGraphic.setId(id); 51 | } 52 | 53 | /** 54 | * Update the position/characteristics of the item within the overlay. 55 | */ 56 | @Override 57 | public void onUpdate(Detector.Detections detectionResults, Barcode item) { 58 | mOverlay.add(mGraphic); 59 | mGraphic.updateItem(item); 60 | if (mListener != null) { 61 | mListener.onCodeScanned(item.rawValue); 62 | } 63 | } 64 | 65 | /** 66 | * Hide the graphic when the corresponding object was not detected. This can happen for 67 | * intermediate frames temporarily, for example if the object was momentarily blocked from 68 | * view. 69 | */ 70 | @Override 71 | public void onMissing(Detector.Detections detectionResults) { 72 | mOverlay.remove(mGraphic); 73 | } 74 | 75 | /** 76 | * Called when the item is assumed to be gone for good. Remove the graphic annotation from 77 | * the overlay. 78 | */ 79 | @Override 80 | public void onDone() { 81 | mOverlay.remove(mGraphic); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/settings/barcode/BarcodeTrackerFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.adafruit.bluefruit.le.connect.app.settings.barcode; 17 | 18 | import com.google.android.gms.vision.MultiProcessor; 19 | import com.google.android.gms.vision.Tracker; 20 | import com.google.android.gms.vision.barcode.Barcode; 21 | 22 | /** 23 | * Factory for creating a tracker and associated graphic to be associated with a new barcode. The 24 | * multi-processor uses this factory to create barcode trackers as needed -- one for each barcode. 25 | */ 26 | public class BarcodeTrackerFactory implements MultiProcessor.Factory { 27 | private GraphicOverlay mGraphicOverlay; 28 | public BarcodeGraphicTracker.BarcodeTrackerListener mListener; 29 | 30 | public BarcodeTrackerFactory(GraphicOverlay barcodeGraphicOverlay, BarcodeGraphicTracker.BarcodeTrackerListener listener) { 31 | mGraphicOverlay = barcodeGraphicOverlay; 32 | mListener = listener; 33 | } 34 | 35 | @Override 36 | public Tracker create(Barcode barcode) { 37 | BarcodeGraphic graphic = new BarcodeGraphic(mGraphicOverlay); 38 | return new BarcodeGraphicTracker(mGraphicOverlay, graphic, mListener); 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/shortener/BitlyShortenerAsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.shortener; 2 | 3 | // TODO: remove Apache library and use HttpURLConnection (Apache is deprecated since Android Marshmallow) http://developer.android.com/preview/behavior-changes.html#behavior-apache-http-client 4 | 5 | import org.apache.http.HttpEntity; 6 | import org.apache.http.HttpResponse; 7 | import org.apache.http.client.HttpClient; 8 | import org.apache.http.client.methods.HttpGet; 9 | import org.apache.http.impl.client.DefaultHttpClient; 10 | import org.apache.http.util.EntityUtils; 11 | 12 | import java.io.IOException; 13 | import java.io.UnsupportedEncodingException; 14 | import java.net.URLEncoder; 15 | 16 | public class BitlyShortenerAsyncTask extends ShortenerAsyncTask { 17 | 18 | // Constants 19 | private static final String kBitlyApiKey = "abcdefghijklmnopqr1234567890"; // The previous key wasnt valid either but folks kept bugging us over it. 20 | 21 | 22 | public BitlyShortenerAsyncTask(ShortenerListener listener) { 23 | super(listener); 24 | } 25 | 26 | @Override 27 | protected String doInBackground(String... urls) { 28 | try { 29 | String originalUrl = urls[0]; 30 | String url = bitlyShorteningEndPoint(originalUrl); 31 | 32 | HttpGet httpGet = new HttpGet(url); 33 | HttpClient httpclient = new DefaultHttpClient(); 34 | HttpResponse response = httpclient.execute(httpGet); 35 | 36 | final int status = response.getStatusLine().getStatusCode(); 37 | if (status >= 200 && status < 300) { 38 | HttpEntity entity = response.getEntity(); 39 | String data = EntityUtils.toString(entity); 40 | return data; 41 | } 42 | 43 | 44 | } catch (IOException e) { 45 | e.printStackTrace(); 46 | } 47 | return null; 48 | } 49 | 50 | private String bitlyShorteningEndPoint(String uri) throws UnsupportedEncodingException { 51 | String encodedUri = URLEncoder.encode(uri, "UTF-8"); 52 | return String.format("https://api-ssl.bitly.com/v3/shorten?access_token=%s&longUrl=%s&format=txt", kBitlyApiKey, encodedUri); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/shortener/ShortenerAsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.shortener; 2 | 3 | import android.os.AsyncTask; 4 | 5 | public class ShortenerAsyncTask extends AsyncTask { 6 | 7 | public interface ShortenerListener { 8 | void onUriShortened(String shortenedUri); 9 | } 10 | 11 | private ShortenerListener mListener; 12 | 13 | public ShortenerAsyncTask(ShortenerListener listener) { 14 | mListener = listener; 15 | } 16 | 17 | @Override 18 | protected String doInBackground(String... urls) { 19 | 20 | // Default implementation: no shortening 21 | String originalUrl = urls[0]; 22 | 23 | return originalUrl; 24 | } 25 | 26 | protected void onPostExecute(String result) { 27 | if (mListener != null) { 28 | mListener.onUriShortened(result); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/update/ApplicationFilesFragmentDialog.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.update; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.app.Dialog; 6 | import android.app.DialogFragment; 7 | import android.content.DialogInterface; 8 | import android.net.Uri; 9 | import android.os.Bundle; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.widget.TextView; 13 | import android.widget.Toast; 14 | 15 | import com.adafruit.bluefruit.le.connect.R; 16 | 17 | import java.io.File; 18 | 19 | public class ApplicationFilesFragmentDialog extends DialogFragment { 20 | // UI 21 | private String mMessage; 22 | private TextView mHexTextView; 23 | private TextView mIniTextView; 24 | private AlertDialog mDialog; 25 | private int mFileType; 26 | 27 | // Data 28 | public interface ApplicationFilesDialogListener { 29 | void onApplicationFilesDialogDoneClick(); 30 | 31 | void onApplicationFilesDialogCancelClick(); 32 | } 33 | 34 | ApplicationFilesDialogListener mListener; 35 | Uri mHexUri, mIniUri; 36 | 37 | @Override 38 | public void onAttach(Activity activity) { 39 | super.onAttach(activity); 40 | // Verify that the host activity implements the callback interface 41 | try { 42 | // Instantiate the NoticeDialogListener so we can send events to the host 43 | mListener = (ApplicationFilesDialogListener) activity; 44 | } catch (ClassCastException e) { 45 | // The activity doesn't implement the interface, throw exception 46 | throw new ClassCastException(activity.toString() + " must implement ApplicationFilesDialogListener"); 47 | } 48 | } 49 | 50 | @Override 51 | public Dialog onCreateDialog(Bundle savedInstanceState) { 52 | setRetainInstance(true); 53 | 54 | LayoutInflater inflater = getActivity().getLayoutInflater(); 55 | View contentView = inflater.inflate(R.layout.layout_application_files_dialog, null); 56 | mHexTextView = (TextView) contentView.findViewById(R.id.hexFileTextView); 57 | mIniTextView = (TextView) contentView.findViewById(R.id.iniFileTextView); 58 | 59 | mMessage = getArguments().getString("message"); 60 | mFileType = getArguments().getInt("fileType"); 61 | 62 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 63 | builder.setView(contentView); 64 | builder.setMessage(mMessage) 65 | .setPositiveButton(R.string.firmware_customfile_dialog_done, new DialogInterface.OnClickListener() { 66 | public void onClick(DialogInterface dialog, int id) { 67 | if (getHexUri() == null) { 68 | Toast.makeText(getActivity(), R.string.firmware_customfile_hexundefined, Toast.LENGTH_LONG).show(); 69 | } 70 | 71 | mListener.onApplicationFilesDialogDoneClick(); 72 | } 73 | }) 74 | .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 75 | public void onClick(DialogInterface dialog, int id) { 76 | mListener.onApplicationFilesDialogCancelClick(); 77 | } 78 | }); 79 | mDialog = builder.create(); 80 | 81 | updateUI(); 82 | 83 | return mDialog; 84 | } 85 | 86 | @Override 87 | public void onDestroyView() { 88 | Dialog dialog = getDialog(); 89 | 90 | // Work around bug: http://code.google.com/p/android/issues/detail?id=17423 91 | if ((dialog != null) && getRetainInstance()) 92 | dialog.setDismissMessage(null); 93 | 94 | super.onDestroyView(); 95 | } 96 | 97 | private String filenameFromUri(Uri uri) { 98 | String name = ""; 99 | 100 | if (uri != null) { 101 | File file = new File(uri.getPath()); 102 | name = file.getName(); 103 | } 104 | return name; 105 | } 106 | 107 | public void setHexFilename(Uri uri) { 108 | mHexUri = uri; 109 | updateUI(); 110 | } 111 | 112 | public void setIniFilename(Uri uri) { 113 | mIniUri = uri; 114 | updateUI(); 115 | } 116 | 117 | private void updateUI() { 118 | String hexName = filenameFromUri(mHexUri); 119 | mHexTextView.setText(hexName); 120 | String iniName = filenameFromUri(mIniUri); 121 | mIniTextView.setText(iniName); 122 | 123 | } 124 | 125 | public Uri getHexUri() { 126 | return mHexUri; 127 | } 128 | 129 | public Uri getIniUri() { 130 | return mIniUri; 131 | } 132 | 133 | public int getFileType() { 134 | return mFileType; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/update/DfuService.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.update; 2 | 3 | import no.nordicsemi.android.dfu.DfuBaseService; 4 | import android.app.Activity; 5 | 6 | public class DfuService extends DfuBaseService { 7 | 8 | @Override 9 | protected Class getNotificationTarget() { 10 | /* 11 | * As a target activity the NotificationActivity is returned, not the MainActivity. This is because the notification must create a new task: 12 | * 13 | * intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 14 | * 15 | * when user press it. Using NotificationActivity we can check whether the new activity is a root activity (that means no other activity was open before) 16 | * or that there is other activity already open. In the later case the notificationActivity will just be closed. System will restore the previous activity from 17 | * this application - the MainActivity. However if nRF Beacon has been closed during upload and user click the notification a NotificationActivity will 18 | * be launched as a root activity. It will create and start the MainActivity and finish itself. 19 | * 20 | * This method may be used to restore the target activity in case the application was closed or is open. It may also be used to recreate an activity history (see NotificationActivity). 21 | */ 22 | return NotificationActivity.class; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/update/DownloadTask.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.update; 2 | 3 | import android.content.Context; 4 | import android.net.Uri; 5 | import android.os.AsyncTask; 6 | import android.os.PowerManager; 7 | import android.util.Log; 8 | 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.net.HttpURLConnection; 13 | import java.net.URL; 14 | 15 | 16 | class DownloadTask extends AsyncTask { 17 | // Constants 18 | private final static String TAG = DownloadTask.class.getSimpleName(); 19 | 20 | // Data 21 | private Context mContext; 22 | private PowerManager.WakeLock mWakeLock; 23 | private DownloadTaskListener mListener; 24 | private int mOperationId; 25 | private String mUrlAddress; 26 | private Object mTag; 27 | 28 | DownloadTask(Context context, DownloadTaskListener listener, int operationId) { 29 | mContext = context; 30 | mListener = listener; 31 | mOperationId = operationId; 32 | } 33 | 34 | @Override 35 | protected ByteArrayOutputStream doInBackground(String... sUrl) { 36 | InputStream input = null; 37 | ByteArrayOutputStream output = null; 38 | HttpURLConnection connection = null; 39 | try { 40 | mUrlAddress = sUrl[0]; 41 | 42 | int fileLength = 0; 43 | Uri uri = Uri.parse(sUrl[0]); 44 | String uriScheme = uri.getScheme(); 45 | //Log.d(TAG, "Downloading from "+uriScheme); 46 | boolean shouldBeConsideredAsInputStream = (uriScheme.equalsIgnoreCase("file") || uriScheme.equalsIgnoreCase("content")); 47 | if (shouldBeConsideredAsInputStream) { 48 | input = mContext.getContentResolver().openInputStream(uri); 49 | } else { 50 | URL url = new URL(mUrlAddress); 51 | connection = (HttpURLConnection) url.openConnection(); 52 | connection.connect(); 53 | 54 | // expect HTTP 200 OK, so we don't mistakenly save error report instead of the file 55 | if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) { 56 | return null; 57 | } 58 | 59 | // this will be useful to display download percentage might be -1: server did not report the length 60 | fileLength = connection.getContentLength(); 61 | 62 | // download the file 63 | input = connection.getInputStream(); 64 | } 65 | // Log.d(TAG, "\tFile size: "+fileLength); 66 | 67 | // download the file 68 | output = new ByteArrayOutputStream(); 69 | 70 | byte data[] = new byte[4096]; 71 | long total = 0; 72 | int count; 73 | while ((count = input.read(data)) != -1) { 74 | // allow canceling 75 | if (isCancelled()) { 76 | input.close(); 77 | return null; 78 | } 79 | total += count; 80 | 81 | // publishing the progress.... 82 | if (fileLength > 0) {// only if total length is known 83 | publishProgress((int) (total * 100 / fileLength)); 84 | } 85 | output.write(data, 0, count); 86 | } 87 | 88 | } catch (Exception e) { 89 | Log.w(TAG, "Error DownloadTask " + e); 90 | return null; 91 | } finally { 92 | try { 93 | if (output != null) { 94 | output.close(); 95 | } 96 | if (input != null) { 97 | input.close(); 98 | } 99 | } catch (IOException ignored) { 100 | } 101 | 102 | if (connection != null) { 103 | connection.disconnect(); 104 | } 105 | } 106 | return output; 107 | } 108 | 109 | @Override 110 | protected void onPreExecute() { 111 | super.onPreExecute(); 112 | // take CPU lock to prevent CPU from going off if the user presses the power button during download 113 | PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 114 | mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName()); 115 | mWakeLock.acquire(); 116 | } 117 | 118 | @Override 119 | protected void onProgressUpdate(Integer... progress) { 120 | super.onProgressUpdate(progress); 121 | 122 | mListener.onDownloadProgress(mOperationId, progress[0]); 123 | } 124 | 125 | @Override 126 | protected void onPostExecute(ByteArrayOutputStream result) { 127 | mWakeLock.release(); 128 | 129 | mListener.onDownloadCompleted(mOperationId, mUrlAddress, result); 130 | } 131 | 132 | static interface DownloadTaskListener { 133 | void onDownloadProgress(int operationId, int progress); 134 | 135 | void onDownloadCompleted(int operationId, String url, ByteArrayOutputStream result); 136 | } 137 | 138 | public Object getTag() { 139 | return mTag; 140 | } 141 | 142 | public void setTag(Object tag) { 143 | this.mTag = tag; 144 | } 145 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/update/NotificationActivity.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.update; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | 7 | import com.adafruit.bluefruit.le.connect.app.MainActivity; 8 | 9 | public class NotificationActivity extends Activity { 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | 14 | // If this activity is the root activity of the task, the app is not running 15 | if (isTaskRoot()) { 16 | // Start the app before finishing 17 | final Intent parentIntent = new Intent(this, MainActivity.class); 18 | parentIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 19 | /* 20 | final Intent startAppIntent = new Intent(this, DfuActivity.class); 21 | startAppIntent.putExtras(getIntent().getExtras()); 22 | startActivities(new Intent[] { parentIntent, startAppIntent }); 23 | */ 24 | startActivity(parentIntent); 25 | } 26 | 27 | // Now finish, which will drop the user in to the activity that was at the top 28 | // of the task stack 29 | finish(); 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/app/update/ProgressFragmentDialog.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.app.update; 2 | 3 | 4 | import android.app.Dialog; 5 | import android.app.DialogFragment; 6 | import android.app.ProgressDialog; 7 | import android.content.DialogInterface; 8 | import android.os.Bundle; 9 | 10 | public class ProgressFragmentDialog extends DialogFragment { 11 | private ProgressDialog mDialog; 12 | private DialogInterface.OnCancelListener mCancelListener; 13 | 14 | private String mMessage; 15 | private int mProgress; 16 | private boolean mIndeterminate; 17 | 18 | @Override 19 | public Dialog onCreateDialog(Bundle savedInstanceState) { 20 | setRetainInstance(true); 21 | 22 | mMessage = getArguments().getString("message"); 23 | 24 | mDialog = new ProgressDialog(getActivity()); 25 | mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 26 | mDialog.setMax(100); 27 | mDialog.setCanceledOnTouchOutside(false); 28 | mDialog.setCancelable(true); 29 | 30 | updateUI(); 31 | 32 | return mDialog; 33 | } 34 | 35 | @Override 36 | public void onDestroyView() 37 | { 38 | Dialog dialog = getDialog(); 39 | 40 | // Work around bug: http://code.google.com/p/android/issues/detail?id=17423 41 | if ((dialog != null) && getRetainInstance()) 42 | dialog.setDismissMessage(null); 43 | 44 | super.onDestroyView(); 45 | } 46 | 47 | @Override 48 | public void onCancel(DialogInterface dialog) { // to avoid problems with setting oncancellistener after dialog has been created 49 | if (mCancelListener != null) { 50 | mCancelListener.onCancel(dialog); 51 | } 52 | 53 | super.onCancel(dialog); 54 | } 55 | 56 | 57 | public void setOnCancelListener(DialogInterface.OnCancelListener listener) { 58 | mCancelListener = listener; 59 | } 60 | 61 | /* 62 | public ProgressDialog getDialog() { 63 | return mDialog; 64 | } 65 | */ 66 | 67 | public void setMessage(String message) { 68 | mMessage = message; 69 | mDialog.setMessage(message); 70 | } 71 | 72 | public void setProgress(int progress) { 73 | mProgress = progress; 74 | mDialog.setProgress(progress); 75 | } 76 | 77 | public void setIndeterminate(boolean indeterminate) { 78 | mIndeterminate = indeterminate; 79 | mDialog.setIndeterminate(indeterminate); 80 | } 81 | 82 | private void updateUI() { 83 | mDialog.setMessage(mMessage); 84 | mDialog.setProgress(mProgress); 85 | mDialog.setIndeterminate(mIndeterminate); 86 | } 87 | 88 | 89 | } 90 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/ble/KnownUUIDs.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.ble; 2 | 3 | 4 | import com.adafruit.bluefruit.le.connect.app.UartInterfaceActivity; 5 | 6 | import java.util.Collections; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | public class KnownUUIDs extends StandardUUIDs { 11 | 12 | // Service UUIDs 13 | private static final Map sServiceUUIDs; 14 | 15 | static { 16 | Map aMap = new HashMap<>(); 17 | 18 | aMap.put("0000febb-0000-1000-8000-00805f9b34fb".toUpperCase(), "Adafruit Unified Sensor"); 19 | aMap.put(UartInterfaceActivity.UUID_SERVICE.toUpperCase(), "Nordic UART"); 20 | aMap.put("00001530-1212-efde-1523-785feabcd123".toUpperCase(), "Nordic Device Firmware Update Service"); 21 | aMap.put("ee0c2080-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone-URL Config Service"); 22 | aMap.put("8D53DC1D-1DB7-4CD3-868B-8A527460AA84".toUpperCase(), "Newtmgr Service"); 23 | 24 | sServiceUUIDs = Collections.unmodifiableMap(aMap); 25 | } 26 | 27 | // Characteristic UUIDs 28 | private static final Map sCharacteristicUUIDs; 29 | 30 | static { 31 | Map aMap = new HashMap<>(); 32 | 33 | // Unified 34 | aMap.put("B71E0102-7E57-4AFE-EB1E-5CA1AB1E1DEA".toUpperCase(), "Static Sensor Info"); 35 | aMap.put("B71E0103-7E57-4AFE-EB1E-5CA1AB1E1DEA".toUpperCase(), "Dynamic Sensor Info"); 36 | aMap.put("b71e0104-7e57-4afe-eb1e-5ca1ab1e1dea".toUpperCase(), "Sensor Data"); 37 | aMap.put("00002a24-0000-1000-8000-00805f9b34fb".toUpperCase(), "Model Number"); 38 | aMap.put("00001530-1212-efde-1523-785feabcd123".toUpperCase(), "Nordic Device Firmware Update Service"); 39 | 40 | // DFU 41 | aMap.put("00001532-1212-efde-1523-785feabcd123".toUpperCase(), "DFU Packet"); 42 | aMap.put("00001531-1212-efde-1523-785feabcd123".toUpperCase(), "DFU Control Point"); 43 | aMap.put("00001534-1212-efde-1523-785feabcd123".toUpperCase(), "DFU Version"); 44 | 45 | // Uart 46 | aMap.put(UartInterfaceActivity.UUID_RX.toUpperCase(), "RX Buffer"); 47 | aMap.put(UartInterfaceActivity.UUID_TX.toUpperCase(), "TX Buffer"); 48 | aMap.put(UartInterfaceActivity.UUID_DFU.toUpperCase(), "DFU Service"); 49 | 50 | // Eddystone 51 | aMap.put("ee0c2081-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone Lock State"); 52 | aMap.put("ee0c2082-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone Lock"); 53 | aMap.put("ee0c2083-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone Unlock"); 54 | aMap.put("ee0c2084-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone URI Data"); 55 | aMap.put("ee0c2085-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone Flags"); 56 | aMap.put("ee0c2086-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone Adv. TX Power Levels"); 57 | aMap.put("ee0c2087-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone TX Power Mode"); 58 | aMap.put("ee0c2088-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone Beacon Period"); 59 | aMap.put("ee0c2089-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone Reset"); 60 | aMap.put("ee0c2090-8786-40ba-ab96-99b91ac981d8".toUpperCase(), "Eddystone (Reserved)"); 61 | 62 | // Newtmgr 63 | aMap.put("DA2E7828-FBCE-4E01-AE9E-261174997C48".toUpperCase(), "Newtmgr Characteristic"); 64 | 65 | sCharacteristicUUIDs = Collections.unmodifiableMap(aMap); 66 | } 67 | 68 | // Descriptors UUIDs 69 | private static final Map sDescriptorUUIDs; 70 | 71 | static { 72 | Map aMap = new HashMap<>(); 73 | 74 | sDescriptorUUIDs = Collections.unmodifiableMap(aMap); 75 | } 76 | 77 | 78 | // Public Getters 79 | public static String getServiceName(String uuid) { 80 | String result; 81 | 82 | uuid = uuid.toUpperCase(); // To avoid problems with lowercase/uppercase 83 | result = sServiceUUIDs.get(uuid); 84 | if (result == null) { 85 | result = StandardUUIDs.getServiceName(uuid); 86 | } 87 | 88 | return result; 89 | } 90 | 91 | public static String getCharacteristicName(String uuid) { 92 | String result; 93 | 94 | uuid = uuid.toUpperCase(); // To avoid problems with lowercase/uppercase 95 | result = sCharacteristicUUIDs.get(uuid); 96 | if (result == null) { 97 | result = StandardUUIDs.getCharacteristicName(uuid); 98 | } 99 | 100 | return result; 101 | } 102 | 103 | public static String getDescriptorName(String uuid) { 104 | String result; 105 | 106 | uuid = uuid.toUpperCase(); // To avoid problems with lowercase/uppercase 107 | result = sDescriptorUUIDs.get(uuid); 108 | if (result == null) { 109 | result = StandardUUIDs.getDescriptorName(uuid); 110 | } 111 | 112 | return result; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/ui/keyboard/CustomEditTextFormatter.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.ui.keyboard; 2 | 3 | import android.text.Editable; 4 | import android.text.TextUtils; 5 | import android.text.TextWatcher; 6 | import android.widget.EditText; 7 | 8 | public class CustomEditTextFormatter { 9 | 10 | public static void attachToEditText(final EditText editText, final int maxNumCharacters, final String separator, final int groupCharactersCount) { 11 | editText.addTextChangedListener(new TextWatcher() { 12 | @Override 13 | public void onTextChanged(CharSequence s, int start, int before, int count) { 14 | } 15 | 16 | @Override 17 | public void beforeTextChanged(CharSequence s, int start, int count, 18 | int after) { 19 | } 20 | 21 | @Override 22 | public void afterTextChanged(Editable s) { 23 | String text = s.toString(); 24 | 25 | String newText = formatText(text, maxNumCharacters, separator, groupCharactersCount); 26 | 27 | if (!text.equals(newText)) { 28 | editText.setText(newText); 29 | editText.setSelection(newText.length()); 30 | } 31 | } 32 | }); 33 | } 34 | 35 | public static String formatText(String text, int maxNumCharacters, String separator, int groupCharactersCount) { 36 | // Split the string into character groups 37 | String mergedText = text.replaceAll(separator, ""); 38 | 39 | if (mergedText.length() > maxNumCharacters) { 40 | mergedText = mergedText.substring(0, maxNumCharacters); 41 | } 42 | 43 | String[] characterGroups = splitStringEvery(mergedText, groupCharactersCount); 44 | String newText = TextUtils.join(separator, characterGroups); 45 | 46 | return newText; 47 | } 48 | 49 | 50 | private static String[] splitStringEvery(String s, int interval) { // based on: http://stackoverflow.com/questions/12295711/split-a-string-at-every-nth-position 51 | int arrayLength = (int) Math.ceil(((s.length() / (double) interval))); 52 | String[] result = new String[arrayLength]; 53 | 54 | int j = 0; 55 | int lastIndex = result.length - 1; 56 | for (int i = 0; i < lastIndex; i++) { 57 | result[i] = s.substring(j, j + interval); 58 | j += interval; 59 | } 60 | if (lastIndex >= 0) { 61 | result[lastIndex] = s.substring(j); 62 | } 63 | 64 | return result; 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/ui/utils/DialogUtils.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.ui.utils; 2 | 3 | import android.app.Dialog; 4 | import android.view.WindowManager; 5 | 6 | public class DialogUtils { 7 | 8 | // Prevent dialog dismiss when orientation changes 9 | // http://stackoverflow.com/questions/7557265/prevent-dialog-dismissal-on-screen-rotation-in-android 10 | public static void keepDialogOnOrientationChanges(Dialog dialog){ 11 | WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); 12 | lp.copyFrom(dialog.getWindow().getAttributes()); 13 | lp.width = WindowManager.LayoutParams.WRAP_CONTENT; 14 | lp.height = WindowManager.LayoutParams.WRAP_CONTENT; 15 | dialog.getWindow().setAttributes(lp); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/ui/utils/ExpandableHeightExpandableListView.java: -------------------------------------------------------------------------------- 1 | // Based on ExpandedHeightGridView from http://stackoverflow.com/questions/8481844/gridview-height-gets-cut 2 | 3 | package com.adafruit.bluefruit.le.connect.ui.utils; 4 | 5 | import android.content.Context; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ExpandableListView; 10 | import android.widget.ScrollView; 11 | 12 | public class ExpandableHeightExpandableListView extends ExpandableListView { 13 | 14 | private boolean mExpanded = false; 15 | 16 | public ExpandableHeightExpandableListView(Context context) { 17 | super(context); 18 | } 19 | 20 | public ExpandableHeightExpandableListView(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | public ExpandableHeightExpandableListView(Context context, AttributeSet attrs, int defStyle) { 25 | super(context, attrs, defStyle); 26 | } 27 | 28 | public boolean isExpanded() { 29 | return mExpanded; 30 | } 31 | 32 | @Override 33 | public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 34 | // HACK! TAKE THAT ANDROID! 35 | if (isExpanded()) { 36 | // Calculate entire height by providing a very large height hint. 37 | // View.MEASURED_SIZE_MASK represents the largest height possible. 38 | int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST); 39 | super.onMeasure(widthMeasureSpec, expandSpec); 40 | 41 | ViewGroup.LayoutParams params = getLayoutParams(); 42 | params.height = getMeasuredHeight(); 43 | } else { 44 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 45 | } 46 | } 47 | 48 | public void setExpanded(boolean expanded) { 49 | mExpanded = expanded; 50 | } 51 | 52 | 53 | public void scrollToGroup(int groupPosition, View view, ScrollView parentScrollView){ 54 | final float baseY = getY(); 55 | final float currentGroupPosY = baseY + view.getY(); 56 | final int currentScrollY = parentScrollView.getScrollY(); 57 | final View nextGroupView = findViewWithTag(groupPosition+1); 58 | 59 | if (currentScrollY > currentGroupPosY) { 60 | parentScrollView.smoothScrollTo(parentScrollView.getScrollX(), view.getTop()); 61 | } 62 | else if (nextGroupView != null) { 63 | final float nextGroupPosY = baseY + nextGroupView.getY(); 64 | if (currentScrollY + parentScrollView.getHeight() < nextGroupPosY) { 65 | parentScrollView.smoothScrollTo(0, nextGroupView.getBottom()); 66 | } 67 | } 68 | else { 69 | parentScrollView.smoothScrollTo(parentScrollView.getScrollX(), getBottom()-parentScrollView.getHeight()); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/ui/utils/ExpandableHeightListView.java: -------------------------------------------------------------------------------- 1 | // Based on ExpandedHeightGridView from http://stackoverflow.com/questions/8481844/gridview-height-gets-cut 2 | 3 | package com.adafruit.bluefruit.le.connect.ui.utils; 4 | 5 | import android.content.Context; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ListView; 10 | import android.widget.ScrollView; 11 | 12 | public class ExpandableHeightListView extends ListView { 13 | 14 | boolean mExpanded = false; 15 | 16 | public ExpandableHeightListView(Context context) { 17 | super(context); 18 | } 19 | 20 | public ExpandableHeightListView(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | public ExpandableHeightListView(Context context, AttributeSet attrs, int defStyle) { 25 | super(context, attrs, defStyle); 26 | } 27 | 28 | public boolean isExpanded() { 29 | return mExpanded; 30 | } 31 | 32 | @Override 33 | public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 34 | // HACK! TAKE THAT ANDROID! 35 | if (isExpanded()) { 36 | // Calculate entire height by providing a very large height hint. 37 | // View.MEASURED_SIZE_MASK represents the largest height possible. 38 | int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST); 39 | super.onMeasure(widthMeasureSpec, expandSpec); 40 | 41 | ViewGroup.LayoutParams params = getLayoutParams(); 42 | params.height = getMeasuredHeight(); 43 | } else { 44 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 45 | } 46 | } 47 | 48 | public void setExpanded(boolean expanded) { 49 | mExpanded = expanded; 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/ui/utils/MetricsUtils.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.ui.utils; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.util.DisplayMetrics; 6 | 7 | // http://stackoverflow.com/questions/4605527/converting-pixels-to-dp 8 | public class MetricsUtils { 9 | 10 | public static float convertPixelsToDp(final Context context, final float px) { 11 | if (context != null) { 12 | return px / context.getResources().getDisplayMetrics().density; 13 | } else { 14 | return 0f; 15 | } 16 | } 17 | 18 | public static float convertDpToPixel(final Context context, final float dp) { 19 | if (context != null) { 20 | return dp * context.getResources().getDisplayMetrics().density; 21 | } else { 22 | return 0f; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.adafruit.bluefruit.le.connect.utils; 2 | 3 | import android.content.res.AssetManager; 4 | import android.os.Environment; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.OutputStream; 11 | 12 | public class FileUtils { 13 | 14 | public static String readAssetsFile(String filename, AssetManager assetManager) { 15 | String result = null; 16 | 17 | try { 18 | InputStream is = assetManager.open(filename); 19 | int size = is.available(); 20 | 21 | byte[] buffer = new byte[size]; 22 | is.read(buffer); 23 | is.close(); 24 | 25 | result = new String(buffer, "UTF-8"); 26 | 27 | } catch (IOException e) { 28 | e.printStackTrace(); 29 | } 30 | 31 | return result; 32 | } 33 | 34 | public static String copyAssetFile(AssetManager assetManager, String inputFilename, String outputFilename) { 35 | 36 | String outPath = null; 37 | 38 | try { 39 | InputStream input = assetManager.open(inputFilename); 40 | 41 | // Create new file to copy into. 42 | outPath = Environment.getExternalStorageDirectory() + java.io.File.separator + outputFilename; 43 | File outFile = new File(outPath); 44 | OutputStream output = new FileOutputStream(outFile); 45 | copyFile(input, output); 46 | input.close(); 47 | output.flush(); 48 | output.close(); 49 | 50 | } catch (IOException e) { 51 | e.printStackTrace(); 52 | } 53 | 54 | return outPath; 55 | } 56 | 57 | private static void copyFile(InputStream in, OutputStream out) throws IOException { 58 | byte[] buffer = new byte[1024]; 59 | int read; 60 | while ((read = in.read(buffer)) != -1) { 61 | out.write(buffer, 0, read); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adafruit/bluefruit/le/connect/utils/LegacyCompatFileProvider.java: -------------------------------------------------------------------------------- 1 | /*** 2 | Copyright (c) 2015 CommonsWare, LLC 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 | use this file except in compliance with the License. You may obtain a copy 5 | of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required 6 | by applicable law or agreed to in writing, software distributed under the 7 | License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 8 | OF ANY KIND, either express or implied. See the License for the specific 9 | language governing permissions and limitations under the License. 10 | 11 | Covered in detail in the book _The Busy Coder's Guide to Android Development_ 12 | https://commonsware.com/Android 13 | */ 14 | 15 | package com.adafruit.bluefruit.le.connect.utils; 16 | 17 | import android.database.Cursor; 18 | import android.net.Uri; 19 | import android.support.v4.content.FileProvider; 20 | 21 | import com.commonsware.cwac.provider.LegacyCompatCursorWrapper; 22 | 23 | public class LegacyCompatFileProvider extends FileProvider { 24 | @Override 25 | public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 26 | return (new LegacyCompatCursorWrapper(super.query(uri, projection, selection, selectionArgs, sortOrder))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-hdpi/ic_expand_less_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-hdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_rotate_right_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-hdpi/ic_rotate_right_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_search_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-hdpi/ic_search_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_select_all_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-hdpi/ic_select_all_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_select_all_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-hdpi/ic_select_all_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/sym_keyboard_delete_holo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-hdpi/sym_keyboard_delete_holo_dark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/sym_keyboard_return_holo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-hdpi/sym_keyboard_return_holo_dark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_cancel_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/ic_cancel_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/ic_expand_less_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/ic_expand_more_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_rotate_right_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/ic_rotate_right_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_search_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/ic_search_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_select_all_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/ic_select_all_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_select_all_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/ic_select_all_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/signalstrength0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/signalstrength0.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/signalstrength1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/signalstrength1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/signalstrength2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/signalstrength2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/signalstrength3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/signalstrength3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/signalstrength4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/signalstrength4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/sym_keyboard_delete_holo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/sym_keyboard_delete_holo_dark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/sym_keyboard_return_holo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-mdpi/sym_keyboard_return_holo_dark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/adaflower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/adaflower.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/adafruitlogo2012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/adafruitlogo2012.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_cancel_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/ic_cancel_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/ic_expand_less_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/ic_expand_more_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_rotate_right_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/ic_rotate_right_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_search_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/ic_search_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_select_all_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/ic_select_all_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_select_all_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/ic_select_all_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_arrow_button_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_arrow_button_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_arrow_button_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_arrow_button_left.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_arrow_button_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_arrow_button_right.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_arrow_button_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_arrow_button_up.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_button_exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_button_exit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_button_numbers_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_button_numbers_1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_button_numbers_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_button_numbers_2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_button_numbers_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_button_numbers_3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pad_button_numbers_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/pad_button_numbers_4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/sym_keyboard_delete_holo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/sym_keyboard_delete_holo_dark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/sym_keyboard_return_holo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xhdpi/sym_keyboard_return_holo_dark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_cancel_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_cancel_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_close_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_close_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_expand_less_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_expand_more_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_info_outline_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_info_outline_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_refresh_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_refresh_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_refresh_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_refresh_menu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_rotate_right_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_rotate_right_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_search_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_search_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_select_all_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_select_all_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_select_all_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_select_all_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_sync_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/ic_sync_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/mqtt_connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/mqtt_connected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/mqtt_connecting1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/mqtt_connecting1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/mqtt_connecting2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/mqtt_connecting2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/mqtt_connecting3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/mqtt_connecting3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/mqtt_disconnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/mqtt_disconnected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sym_keyboard_delete_holo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/sym_keyboard_delete_holo_dark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sym_keyboard_return_holo_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxhdpi/sym_keyboard_return_holo_dark.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_cancel_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_cancel_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_expand_less_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_expand_more_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_pie_chart_outlined_white_28dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_pie_chart_outlined_white_28dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_rotate_right_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_rotate_right_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_search_black_18dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_search_black_18dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_select_all_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_select_all_white_36dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_select_all_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_select_all_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_settings_white_28dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Bluefruit_LE_Connect_Android/5443af2742840b715d5f52197230525b762790a1/app/src/main/res/drawable-xxxhdpi/ic_settings_white_28dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/border_gray.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/border_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/neopixel_led.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/neopixel_palettecolor.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/roundedborders_blue.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/roundedborders_gray.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/roundedbutton.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_beacon.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 18 | 19 | 23 | 24 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_color_picker.xml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 16 | 17 | 22 | 23 | 28 | 29 | 34 | 35 | 40 | 41 | 48 | 49 | 53 | 54 | 55 | 60 | 61 | 66 | 67 | 68 |