├── samples
├── android
│ ├── app
│ │ ├── .gitignore
│ │ ├── src
│ │ │ └── main
│ │ │ │ ├── res
│ │ │ │ ├── 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
│ │ │ │ │ ├── colors.xml
│ │ │ │ │ ├── dimens.xml
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── drawable
│ │ │ │ │ └── back.xml
│ │ │ │ ├── values-w820dp
│ │ │ │ │ └── dimens.xml
│ │ │ │ └── layout
│ │ │ │ │ ├── request_button.xml
│ │ │ │ │ ├── activity_bad_elf_device_list.xml
│ │ │ │ │ └── activity_bad_elf_device_data.xml
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── bad_elf
│ │ │ │ └── gpssample
│ │ │ │ ├── BadElfDeviceListActivity.java
│ │ │ │ └── BadElfDeviceDataActivity.java
│ │ ├── proguard-rules.pro
│ │ ├── build.gradle
│ │ └── app.iml
│ ├── badelfgps
│ │ ├── .gitignore
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ ├── src
│ │ │ └── main
│ │ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── bad_elf
│ │ │ │ │ └── badelfgps
│ │ │ │ │ ├── BadElfRemoteController.java
│ │ │ │ │ ├── BadElfGpsConnectionObserver.java
│ │ │ │ │ ├── BadElfDevice.java
│ │ │ │ │ ├── BadElfRemoteControlServer.java
│ │ │ │ │ └── BadElfGpsConnection.java
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── res
│ │ │ │ └── values
│ │ │ │ └── strings.xml
│ │ └── badelfgps.iml
│ ├── .gradle
│ │ ├── vcsWorkingDirs
│ │ │ └── gc.properties
│ │ ├── 4.4
│ │ │ ├── fileChanges
│ │ │ │ └── last-build.bin
│ │ │ ├── fileHashes
│ │ │ │ ├── fileHashes.bin
│ │ │ │ ├── fileHashes.lock
│ │ │ │ └── resourceHashesCache.bin
│ │ │ ├── javaCompile
│ │ │ │ ├── taskJars.bin
│ │ │ │ ├── jarAnalysis.bin
│ │ │ │ ├── javaCompile.lock
│ │ │ │ ├── taskHistory.bin
│ │ │ │ └── classAnalysis.bin
│ │ │ ├── fileContent
│ │ │ │ └── fileContent.lock
│ │ │ └── taskHistory
│ │ │ │ ├── taskHistory.bin
│ │ │ │ └── taskHistory.lock
│ │ ├── 4.6
│ │ │ ├── fileChanges
│ │ │ │ └── last-build.bin
│ │ │ ├── fileHashes
│ │ │ │ ├── fileHashes.bin
│ │ │ │ ├── fileHashes.lock
│ │ │ │ └── resourceHashesCache.bin
│ │ │ └── taskHistory
│ │ │ │ ├── taskHistory.bin
│ │ │ │ └── taskHistory.lock
│ │ └── buildOutputCleanup
│ │ │ ├── cache.properties
│ │ │ ├── outputFiles.bin
│ │ │ └── buildOutputCleanup.lock
│ ├── settings.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── .idea
│ │ ├── caches
│ │ │ └── build_file_checksums.ser
│ │ ├── modules.xml
│ │ ├── libraries
│ │ │ ├── Gradle__junit_junit_4_12_jar.xml
│ │ │ ├── Gradle__org_hamcrest_hamcrest_core_1_3_jar.xml
│ │ │ ├── Gradle__com_android_support_support_annotations_24_0_0_jar.xml
│ │ │ ├── Gradle__com_android_support_appcompat_v7_24_0_0.xml
│ │ │ ├── Gradle__com_android_support_support_vector_drawable_24_0_0.xml
│ │ │ ├── Gradle__com_android_support_animated_vector_drawable_24_0_0.xml
│ │ │ └── Gradle__com_android_support_support_v4_24_0_0.xml
│ │ ├── runConfigurations.xml
│ │ ├── gradle.xml
│ │ ├── misc.xml
│ │ └── codeStyles
│ │ │ └── Project.xml
│ ├── local.properties
│ ├── build.gradle
│ ├── gradle.properties
│ ├── android.iml
│ ├── gradlew.bat
│ └── gradlew
└── ios
│ ├── obj-c
│ └── EADemo
│ │ ├── .DS_Store
│ │ ├── EADemo.xcodeproj
│ │ ├── xcuserdata
│ │ │ └── bretth.xcuserdatad
│ │ │ │ ├── xcdebugger
│ │ │ │ └── Breakpoints_v2.xcbkptlist
│ │ │ │ └── xcschemes
│ │ │ │ └── xcschememanagement.plist
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ ├── xcuserdata
│ │ │ │ └── bretth.xcuserdatad
│ │ │ │ │ └── UserInterfaceState.xcuserstate
│ │ │ └── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── EADemo.xcscheme
│ │ ├── EADemo
│ │ ├── AppDelegate.h
│ │ ├── main.m
│ │ ├── RootViewController.h
│ │ ├── EADSessionTransferViewController.h
│ │ ├── EADSessionController.h
│ │ ├── Base.lproj
│ │ │ └── LaunchScreen.storyboard
│ │ ├── Info.plist
│ │ ├── Assets.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.m
│ │ ├── EADSessionTransferViewController.m
│ │ ├── EADSessionController.m
│ │ └── RootViewController.m
│ │ ├── LICENSE.txt
│ │ └── README.md
│ └── swift
│ ├── BadElfSampleGnssApp
│ ├── .DS_Store
│ ├── BadElfSampleGnssApp
│ │ ├── Assets.xcassets
│ │ │ ├── Contents.json
│ │ │ ├── AccentColor.colorset
│ │ │ │ └── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ └── ContentView.swift
│ ├── BadElfSampleGnssApp.xcodeproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcuserdata
│ │ │ │ └── bretth.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── xcuserdata
│ │ │ └── bretth.xcuserdatad
│ │ │ │ ├── xcschemes
│ │ │ │ └── xcschememanagement.plist
│ │ │ │ └── xcdebugger
│ │ │ │ └── Breakpoints_v2.xcbkptlist
│ │ └── project.pbxproj
│ └── README.md
│ └── old
│ ├── GPS Sample.xcodeproj
│ ├── xcuserdata
│ │ ├── ericberman.xcuserdatad
│ │ │ ├── xcdebugger
│ │ │ │ └── Breakpoints_v2.xcbkptlist
│ │ │ └── xcschemes
│ │ │ │ └── xcschememanagement.plist
│ │ └── bretth.xcuserdatad
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcuserdata
│ │ ├── bretth.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── ericberman.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── GPS Sample
│ ├── Info.plist
│ ├── Base.lproj
│ └── LaunchScreen.storyboard
│ ├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Views
│ ├── AccessoryViewController.swift
│ ├── DetectionTableViewController.swift
│ └── ConfigurationViewController.swift
│ └── Controllers
│ └── SessionController.swift
├── arcgis-tools
└── BadElfToolboxForArcGIS.tbx
├── README.md
├── .github
└── ISSUE_TEMPLATE.md
└── LICENSE
/samples/android/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/samples/android/.gradle/vcsWorkingDirs/gc.properties:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/fileChanges/last-build.bin:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/samples/android/.gradle/4.6/fileChanges/last-build.bin:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/samples/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':badelfgps'
2 |
--------------------------------------------------------------------------------
/samples/android/.gradle/buildOutputCleanup/cache.properties:
--------------------------------------------------------------------------------
1 | #Wed Mar 06 19:02:09 MST 2019
2 | gradle.version=4.6
3 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/ios/obj-c/EADemo/.DS_Store
--------------------------------------------------------------------------------
/arcgis-tools/BadElfToolboxForArcGIS.tbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/arcgis-tools/BadElfToolboxForArcGIS.tbx
--------------------------------------------------------------------------------
/samples/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/ios/swift/BadElfSampleGnssApp/.DS_Store
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/fileHashes/fileHashes.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/fileHashes/fileHashes.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/fileHashes/fileHashes.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/fileHashes/fileHashes.lock
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/javaCompile/taskJars.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/javaCompile/taskJars.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/4.6/fileHashes/fileHashes.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.6/fileHashes/fileHashes.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/4.6/fileHashes/fileHashes.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.6/fileHashes/fileHashes.lock
--------------------------------------------------------------------------------
/samples/android/.idea/caches/build_file_checksums.ser:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.idea/caches/build_file_checksums.ser
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/fileContent/fileContent.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/fileContent/fileContent.lock
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/javaCompile/jarAnalysis.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/javaCompile/jarAnalysis.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/javaCompile/javaCompile.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/javaCompile/javaCompile.lock
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/javaCompile/taskHistory.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/javaCompile/taskHistory.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/taskHistory/taskHistory.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/taskHistory/taskHistory.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/taskHistory/taskHistory.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/taskHistory/taskHistory.lock
--------------------------------------------------------------------------------
/samples/android/.gradle/4.6/taskHistory/taskHistory.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.6/taskHistory/taskHistory.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/4.6/taskHistory/taskHistory.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.6/taskHistory/taskHistory.lock
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/javaCompile/classAnalysis.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/javaCompile/classAnalysis.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/buildOutputCleanup/outputFiles.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/buildOutputCleanup/outputFiles.bin
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/samples/android/.gradle/4.4/fileHashes/resourceHashesCache.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.4/fileHashes/resourceHashesCache.bin
--------------------------------------------------------------------------------
/samples/android/.gradle/4.6/fileHashes/resourceHashesCache.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/4.6/fileHashes/resourceHashesCache.bin
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/samples/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo.xcodeproj/xcuserdata/bretth.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample.xcodeproj/xcuserdata/ericberman.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo.xcodeproj/project.xcworkspace/xcuserdata/bretth.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/ios/obj-c/EADemo/EADemo.xcodeproj/project.xcworkspace/xcuserdata/bretth.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample.xcodeproj/project.xcworkspace/xcuserdata/bretth.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/ios/swift/old/GPS Sample.xcodeproj/project.xcworkspace/xcuserdata/bretth.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/drawable/back.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample.xcodeproj/project.xcworkspace/xcuserdata/ericberman.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/ios/swift/old/GPS Sample.xcodeproj/project.xcworkspace/xcuserdata/ericberman.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/samples/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Mar 06 19:01:26 MST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
7 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 | Bad Elf Gps Sample
10 |
11 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp.xcodeproj/project.xcworkspace/xcuserdata/bretth.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BadElf/gps-sdk/HEAD/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp.xcodeproj/project.xcworkspace/xcuserdata/bretth.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | */
6 |
7 | @import UIKit;
8 |
9 | @interface AppDelegate : UIResponder
10 |
11 | @property (strong, nonatomic) UIWindow *window;
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/samples/android/local.properties:
--------------------------------------------------------------------------------
1 | ## This file must *NOT* be checked into Version Control Systems,
2 | # as it contains information specific to your local configuration.
3 | #
4 | # Location of the SDK. This is only used by Gradle.
5 | # For customization when using a Version Control System, please read the
6 | # header note.
7 | #Wed Aug 29 09:06:18 MST 2018
8 | sdk.dir=/Users/bretth/Library/Android/sdk
9 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/main.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | */
6 |
7 | #import
8 | #import "AppDelegate.h"
9 |
10 | int main(int argc, char * argv[]) {
11 | @autoreleasepool {
12 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/RootViewController.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | View controller for watching the device come and go
7 | */
8 |
9 |
10 | @import UIKit;
11 | @import ExternalAccessory;
12 |
13 | @class EADSessionController;
14 |
15 | @interface RootViewController : UITableViewController
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/EADSessionTransferViewController.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | View controller to allow transferring data to and from an accessory form the UI.
7 | */
8 |
9 |
10 | @import UIKit;
11 | @import ExternalAccessory;
12 |
13 | @interface EADSessionTransferViewController : UIViewController
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample.xcodeproj/xcuserdata/bretth.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | GPS Sample.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample.xcodeproj/xcuserdata/ericberman.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | GPS Sample.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/samples/android/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp.xcodeproj/xcuserdata/bretth.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | BadElfSampleGnssApp.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UISupportedExternalAccessoryProtocols
6 |
7 | com.bad-elf.gnss
8 | com.bad-elf.gps
9 |
10 | UIBackgroundModes
11 |
12 | external-accessory
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/samples/android/.idea/libraries/Gradle__junit_junit_4_12_jar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // BadElfSampleGnssApp
4 | //
5 | // Created by Brett Hackleman on 12/3/25.
6 | //
7 |
8 | //import SwiftUI
9 | //
10 | //struct ContentView: View {
11 | // var body: some View {
12 | // VStack {
13 | // Image(systemName: "globe")
14 | // .imageScale(.large)
15 | // .foregroundStyle(.tint)
16 | // Text("Hello, world!")
17 | // }
18 | // .padding()
19 | // }
20 | //}
21 | //
22 | //#Preview {
23 | // ContentView()
24 | //}
25 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/layout/request_button.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/samples/android/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/samples/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | google()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.2.0'
10 |
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/samples/android/.idea/libraries/Gradle__org_hamcrest_hamcrest_core_1_3_jar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 24
5 |
6 | defaultConfig {
7 | minSdkVersion 15
8 | targetSdkVersion 24
9 | versionCode 1
10 | versionName "1.0"
11 | }
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 | }
17 | }
18 | }
19 |
20 | dependencies {
21 | compile fileTree(dir: 'libs', include: ['*.jar'])
22 | testCompile 'junit:junit:4.12'
23 | compile 'com.android.support:appcompat-v7:24.0.0'
24 | }
25 |
--------------------------------------------------------------------------------
/samples/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\dev\sdk/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 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/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 C:\dev\sdk/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 |
--------------------------------------------------------------------------------
/samples/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 |
6 | defaultConfig {
7 | applicationId "com.bad_elf.gpssample"
8 | minSdkVersion 15
9 | targetSdkVersion 24
10 | versionCode 1
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | compile fileTree(include: ['*.jar'], dir: 'libs')
23 | testCompile 'junit:junit:4.12'
24 | compile 'com.android.support:appcompat-v7:24.0.0'
25 | compile project(':badelfgps')
26 | }
27 |
--------------------------------------------------------------------------------
/samples/android/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo.xcodeproj/xcuserdata/bretth.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | EADemo.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 | EADemo.xcscheme_^#shared#^_
13 |
14 | orderHint
15 | 0
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | 30EBAADA1CFFA0950073732B
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Bad Elf GPS SDK
6 | =================
7 |
8 | 
9 | 
10 |
11 | Bad Elf is excited to provide developers with the protocol information and sample code to communicate with Bad Elf GNSS/GPS accessories across many platforms.
12 |
13 | For more details, head over to the [Wiki](https://github.com/BadElf/gps-sdk/wiki).
14 |
15 | ## Need Help?
16 | If you find bugs or need more support, please send an email to [support@bad-elf.com](mailto:support@bad-elf.com).
17 |
18 | ## License
19 | This project is license under the terms of the BSD-New License. See LICENSE file.
20 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | },
8 | {
9 | "appearances" : [
10 | {
11 | "appearance" : "luminosity",
12 | "value" : "dark"
13 | }
14 | ],
15 | "idiom" : "universal",
16 | "platform" : "ios",
17 | "size" : "1024x1024"
18 | },
19 | {
20 | "appearances" : [
21 | {
22 | "appearance" : "luminosity",
23 | "value" : "tinted"
24 | }
25 | ],
26 | "idiom" : "universal",
27 | "platform" : "ios",
28 | "size" : "1024x1024"
29 | }
30 | ],
31 | "info" : {
32 | "author" : "xcode",
33 | "version" : 1
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### New Issue Checklist
2 |
3 | - [ ] Updated to Bad Elf firmware to latest version.
4 | - [ ] Updated platform to latest compatible version.
5 | - [ ] Browsed open/resolved tickets to find similar issue.
6 |
7 | ### Issue Description
8 |
9 | ##### Complete output from your IDE, including the stack trace, if available.
10 |
11 | ```
12 | INSERT CONSOLE OUTPUT HERE
13 | ```
14 |
15 | ### ENVIRONMENT
16 | Please fill out the complete configuration of your setup below. This will help Bad Elf Engineers reproduce and resolve your issue faster.
17 |
18 | Bad Elf Model:
19 | ```
20 | # INSERT MODEL HERE
21 | ```
22 | Firmware Version:
23 | ```
24 | # INSERT FIRMWARE VERSION HERE
25 | ```
26 | Platform:
27 | ```
28 | # INSERT PLATFORM VERSION HERE (I.E iOS 9.3.3)
29 | ```
30 | Protocol String:
31 | ```
32 | # INSERT THE PROTOCOL STRING USED HERE
33 | ```
--------------------------------------------------------------------------------
/samples/android/.idea/libraries/Gradle__com_android_support_support_annotations_24_0_0_jar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/src/main/java/com/bad_elf/badelfgps/BadElfRemoteController.java:
--------------------------------------------------------------------------------
1 | package com.bad_elf.badelfgps;
2 |
3 | import java.util.List;
4 | import com.bad_elf.badelfgps.BadElfRemoteControlServer;
5 |
6 | public class BadElfRemoteController {
7 |
8 | public static final String TAG = "BadElfRemoteController";
9 |
10 | private List badElfDevices;
11 | private BadElfRemoteControlServer server;
12 | private BadElfDevice selectedDevice;
13 |
14 |
15 | public void start() {
16 | server = new BadElfRemoteControlServer();
17 | }
18 |
19 | public void stop() {
20 |
21 | }
22 |
23 | public void setDeviceList(List badElfDevices) {
24 | this.badElfDevices = badElfDevices;
25 | }
26 |
27 | public void setSelectedDevice(BadElfDevice device) {
28 | this.selectedDevice = device;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/samples/android/.idea/libraries/Gradle__com_android_support_appcompat_v7_24_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/samples/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/samples/android/android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/samples/android/.idea/libraries/Gradle__com_android_support_support_vector_drawable_24_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/samples/android/.idea/libraries/Gradle__com_android_support_animated_vector_drawable_24_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/samples/android/.idea/libraries/Gradle__com_android_support_support_v4_24_0_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
12 |
13 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/src/main/java/com/bad_elf/badelfgps/BadElfGpsConnectionObserver.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | * See LICENSE.txt for this sample's licensing information
4 | *
5 | */
6 |
7 | package com.bad_elf.badelfgps;
8 |
9 | /**
10 | * Implement this interface to receive callbacks from BadElfGpsConnection and BadElfGpsService
11 | */
12 | public interface BadElfGpsConnectionObserver {
13 |
14 | /**
15 | * This is called by BadElfGpsConnection when it has bound to the BadElfService.
16 | *
17 | * After this method is called the other methods of BadElfGpsConnection can be called.
18 | */
19 | void onReady();
20 |
21 | /**
22 | * This is called by BadElfService when the connection state changes.
23 | *
24 | * @param newState the new connection state
25 | */
26 | void onStateChanged(final BadElfService.State newState);
27 |
28 | /**
29 | * This is called by BadElfService when data is received from the Bad Elf Device
30 | *
31 | * @param data the received data
32 | */
33 | void onDataReceived(final byte[] data);
34 | }
35 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/EADSessionController.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | Provides an interface for communication with an EASession. Also the delegate for the EASession input and output stream objects.
7 | */
8 |
9 | @import Foundation;
10 | @import ExternalAccessory;
11 |
12 | #define DEMO_APP_NAME @"EADemo_22222"
13 |
14 | extern NSString *EADSessionDataReceivedNotification;
15 |
16 | // NOTE: EADSessionController is not threadsafe, calling methods from different threads will lead to unpredictable results
17 | @interface EADSessionController : NSObject
18 |
19 | + (EADSessionController *)sharedController;
20 |
21 | - (void)setupControllerForAccessory:(EAAccessory *)accessory withProtocolString:(NSString *)protocolString;
22 |
23 | - (BOOL)openSession;
24 | - (void)closeSession;
25 |
26 | - (void)writeData:(NSData *)data;
27 |
28 | - (NSUInteger)readBytesAvailable;
29 | - (NSData *)readData:(NSUInteger)bytesToRead;
30 |
31 | @property (nonatomic, readonly) EAAccessory *accessory;
32 | @property (nonatomic, readonly) NSString *protocolString;
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 | BadElfGpsLibrary
10 |
11 | Disconnect
12 | Connect
13 |
14 | State:
15 | Idle
16 | Connecting
17 | Connected
18 | Disconnecting
19 |
20 | Include Satellites
21 | No Satellites
22 | %1$d Hz
23 |
24 | Device does not support Bluetooth
25 | Bluetooth is not enabled
26 | No Paired Bad Elf Bluetooth Devices
27 |
28 |
29 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/layout/activity_bad_elf_device_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
19 |
20 |
21 |
28 |
29 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016, Bad Elf
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of gps-sdk nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedExternalAccessoryProtocols
34 |
35 | com.bad-elf.gps
36 |
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 |
41 | UISupportedInterfaceOrientations~ipad
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationPortraitUpsideDown
45 | UIInterfaceOrientationLandscapeLeft
46 | UIInterfaceOrientationLandscapeRight
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | EADemo_2
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.2
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | UIBackgroundModes
28 |
29 | external-accessory
30 |
31 | UILaunchStoryboardName
32 | LaunchScreen
33 | UIMainStoryboardFile
34 | Main
35 | UIRequiredDeviceCapabilities
36 |
37 | armv7
38 |
39 | UISupportedExternalAccessoryProtocols
40 |
41 | com.bad-elf.gnss
42 | com.bad-elf.gps
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 |
48 | UISupportedInterfaceOrientations~ipad
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationPortraitUpsideDown
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/samples/android/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
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 |
--------------------------------------------------------------------------------
/samples/android/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
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 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | */
6 |
7 | #import "AppDelegate.h"
8 |
9 | @interface AppDelegate ()
10 |
11 | @end
12 |
13 | @implementation AppDelegate
14 |
15 |
16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
17 | // Override point for customization after application launch.
18 | return YES;
19 | }
20 |
21 | - (void)applicationWillResignActive:(UIApplication *)application {
22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
24 | }
25 |
26 | - (void)applicationDidEnterBackground:(UIApplication *)application {
27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
29 | }
30 |
31 | - (void)applicationWillEnterForeground:(UIApplication *)application {
32 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
33 | }
34 |
35 | - (void)applicationDidBecomeActive:(UIApplication *)application {
36 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
37 | }
38 |
39 | - (void)applicationWillTerminate:(UIApplication *)application {
40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | AppDelegate
7 | */
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool
18 | {
19 | // Override point for customization after application launch.
20 | return true
21 | }
22 |
23 | func applicationWillResignActive(_: UIApplication) {
24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | func applicationDidEnterBackground(_: UIApplication) {
29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | func applicationWillEnterForeground(_: UIApplication) {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | func applicationDidBecomeActive(_: UIApplication) {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | func applicationWillTerminate(_: UIApplication) {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample/Views/AccessoryViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | View controller that shows the MFi detected accessory information (i.e. model, serial number and firmware revision)
7 | */
8 |
9 | import UIKit
10 |
11 | class AccessoryViewController: UITableViewController {
12 |
13 | let sessionController = SessionController.sharedController
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 |
18 | title = sessionController._accessory?.modelNumber
19 | }
20 |
21 | override func didReceiveMemoryWarning() {
22 | super.didReceiveMemoryWarning()
23 | // Dispose of any resources that can be recreated.
24 | }
25 |
26 | // MARK: - Table view data source
27 |
28 | override func numberOfSections(in tableView: UITableView) -> Int {
29 | return 1
30 | }
31 |
32 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
33 | return 5
34 | }
35 |
36 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
37 | let cell = tableView.dequeueReusableCell(withIdentifier: "AccessoryCell", for: indexPath as IndexPath)
38 |
39 | // Configure the cell...
40 |
41 | switch indexPath.row {
42 | case 0:
43 | cell.textLabel?.text = "Name"
44 | cell.detailTextLabel?.text = sessionController._accessory?.name
45 | case 1:
46 | cell.textLabel?.text = "Model #"
47 | cell.detailTextLabel?.text = sessionController._accessory?.modelNumber
48 | case 2:
49 | cell.textLabel?.text = "Serial #"
50 | cell.detailTextLabel?.text = sessionController._accessory?.serialNumber
51 | case 3:
52 | cell.textLabel?.text = "Hardware"
53 | cell.detailTextLabel?.text = sessionController._accessory?.hardwareRevision
54 | case 4:
55 | cell.textLabel?.text = "Firmware"
56 | cell.detailTextLabel?.text = sessionController._accessory?.firmwareRevision
57 |
58 | default:
59 | cell.textLabel?.text = ""
60 | cell.detailTextLabel?.text = ""
61 | }
62 |
63 | return cell
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Sample code project: EADemo
2 | Version: 2.1
3 |
4 | IMPORTANT: This Apple software is supplied to you by Apple
5 | Inc. ("Apple") in consideration of your agreement to the following
6 | terms, and your use, installation, modification or redistribution of
7 | this Apple software constitutes acceptance of these terms. If you do
8 | not agree with these terms, please do not use, install, modify or
9 | redistribute this Apple software.
10 |
11 | In consideration of your agreement to abide by the following terms, and
12 | subject to these terms, Apple grants you a personal, non-exclusive
13 | license, under Apple's copyrights in this original Apple software (the
14 | "Apple Software"), to use, reproduce, modify and redistribute the Apple
15 | Software, with or without modifications, in source and/or binary forms;
16 | provided that if you redistribute the Apple Software in its entirety and
17 | without modifications, you must retain this notice and the following
18 | text and disclaimers in all such redistributions of the Apple Software.
19 | Neither the name, trademarks, service marks or logos of Apple Inc. may
20 | be used to endorse or promote products derived from the Apple Software
21 | without specific prior written permission from Apple. Except as
22 | expressly stated in this notice, no other rights or licenses, express or
23 | implied, are granted by Apple herein, including but not limited to any
24 | patent rights that may be infringed by your derivative works or by other
25 | works in which the Apple Software may be incorporated.
26 |
27 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE
28 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
29 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
30 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
31 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
32 |
33 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
34 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
37 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
38 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
39 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
40 | POSSIBILITY OF SUCH DAMAGE.
41 |
42 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
43 |
--------------------------------------------------------------------------------
/samples/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/java/com/bad_elf/gpssample/BadElfDeviceListActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | * See LICENSE.txt for this sample's licensing information
4 | *
5 | */
6 |
7 | package com.bad_elf.gpssample;
8 |
9 | import android.support.v7.app.AppCompatActivity;
10 |
11 | import android.content.Intent;
12 | import android.os.Bundle;
13 | import android.util.Log;
14 | import android.view.View;
15 | import android.widget.AdapterView;
16 | import android.widget.ArrayAdapter;
17 | import android.widget.ListView;
18 | import android.widget.TextView;
19 |
20 | import com.bad_elf.badelfgps.BadElfDevice;
21 | import com.bad_elf.badelfgps.BadElfRemoteController;
22 |
23 | import java.util.List;
24 |
25 | /**
26 | * This Activity displays any paired Bad Elf Devices and lets the user select one to connect with.
27 | */
28 | public class BadElfDeviceListActivity extends AppCompatActivity {
29 | private static final String TAG = "BadElfDeviceListActvty";
30 | private static BadElfRemoteController remoteController;
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_bad_elf_device_list);
36 |
37 | final ListView listView = (ListView) findViewById(R.id.listView);
38 |
39 | try {
40 | List badElfDevices = BadElfDevice.getPairedBadElfDevices(this);
41 | final ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, badElfDevices);
42 |
43 | listView.setAdapter(adapter);
44 | listView.setOnItemClickListener(listener);
45 |
46 | remoteController = new BadElfRemoteController();
47 | remoteController.setDeviceList(badElfDevices);
48 | remoteController.start();
49 | } catch (RuntimeException e) {
50 | // Errors: Bluetooth not enabled or no paired Bad Elf Devices
51 | final TextView errorMessage = (TextView) findViewById(R.id.ErrorMessage);
52 | listView.setVisibility(View.GONE);
53 | errorMessage.setText(e.getMessage());
54 | errorMessage.setVisibility(View.VISIBLE);
55 | }
56 |
57 |
58 | }
59 |
60 |
61 | /**
62 | * Called when the user clicks on a Bad Elf Device
63 | *
64 | * Starts the BadElfDeviceDataActivity
65 | *
66 | */
67 | private AdapterView.OnItemClickListener listener = new AdapterView.OnItemClickListener() {
68 | @Override
69 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
70 | BadElfDevice badElfDevice = (BadElfDevice) parent.getItemAtPosition(position);
71 | Log.d(TAG, "Clicked " + badElfDevice.toString());
72 | Intent deviceDataIntent = new Intent(BadElfDeviceListActivity.this, BadElfDeviceDataActivity.class);
73 | deviceDataIntent.putExtra(BadElfDevice.TAG, badElfDevice);
74 | startActivity(deviceDataIntent);
75 | }
76 | };
77 |
78 | }
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo.xcodeproj/xcshareddata/xcschemes/EADemo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/README.md:
--------------------------------------------------------------------------------
1 | # BadElfSampleGnssApp (Swift)
2 | =============================
3 |
4 | This sample iOS app demonstrates how to configure detect, connect, and configure our modern and legacy GNSS receivers for NMEA streaming.
5 |
6 | It was 90% generated by Gemini using the prompt below, which was refined over 10-15 iterations. Some manual edits were then made to get the sample to compile in Xcode, and further changes were made after testing with real HW.
7 |
8 | ### Prompt for Gemini
9 |
10 | Build a sample iOS app called BadElfGnssSampleApp written in Swift and SwiftUI that meets the following requirements:
11 |
12 | 1. Uses the EAAccessory framework to detect and automatically open communications with an external GNSS receiver
13 | 2. The receiver supports the “com.bad-elf.gnss” and/or "com.bad-elf.gps" protocol strings. If available on the EAAccessory, the first protocol should be used. If not, the second protocol can be used and the app should set isLegacy flag.
14 | 3. The app should open an EASession on the first GNSS receiver it finds, and stay connected to that receiver until it disconnects, at which point it can connect to the next receiver it finds.
15 | 4. Once the EASession is open, the receiver will start streaming data in NMEA format.
16 | 5. The data stream may also include unknown binary packets or corrupted NMEA messages, so the parser should be fault tolerant and validate the NMEA sentence checksums before parsing them.
17 | 6. Incoming NMEA messages will start with the $ character, and end with a CR, LF, or CR/LF sequence.
18 | 7. Incoming bytes should be stored in a buffer. When processing the buffer for valid NMEA sentences, discard any leading bytes that aren’t the $ character. Then find the next CR, LF, indicating the end of the sentence. If another $ is found before a CR or LF, discard the bytes up to that point and try again.
19 | 8. When parsing NMEA messages with comma separated values, it is valid for some fields to be empty, so you can’t simply split the string based on the comma character.
20 | 9. When the EASession output stream is open for writing, the app should send a configuration message once and set a flag indicating isConfigured.
21 | 10. If the accessory was not marked as isLegacy, the configuration message will be the string below, with a NMEA checksum and CR/LF appended after replacing the values for APP\_NAME, APP\_BUNDLE\_ID, and APP\_VERSION at runtime from NSBundle:
22 |
23 | $PBEJS,{"method":"session","params":{"appName":"APP\_NAME","appId":"APP\_BUNDLE\_ID","appVersion":"APP\_VERSION","msgs":"NMEA"}}"
24 |
25 | 11. If the accessory was marked as isLegacy, the app should send a binary configuration message via EASession to get NMEA messages flowing. The binary packet is defined as the following bytes in hex format: (24 be 00 11 05 01 02 05 31 01 32 04 33 01 64 0d 0a)
26 | 12. From the GGA sentence, the app should parse the following GPS parameters: timestamp, latitude, longitude, altitude, and fix type.
27 | 13. From the RMC sentence, the app should parse the timestamp, speed, course, and date.
28 | 14. From the GST sentence, the app should parse the latitude and longitude error estimates and compute the horizontal accuracy in meters using Patagream theorem. Use fields 6 and 7 for the input values.
29 | 15. If the GGA, RMC, and GST sentences do not have matching timestamps, the data from all three sentences should be discarded.
30 | 16. The app UI should be modern and clean, with simple icons, displaying the following:
31 | 1. receiver model name, serial number, and connection status
32 | 2. Realtime GPS parameters: timestamp, horizontal accuracy, and fix type
33 | 3. A toggle button, enabled by default, that enables or disables the auto-connect behavior. This button should be located at the bottom of the screen.
34 | 17. If needed, make sure to import the Combine library and objects should conform to ObservableObject protocol if needed.
35 | 18. Don’t use EAAccessoryManager.shared() for anything except EAAccessoryManager.shared().connectedAccessories and EAAccessoryManager.shared().registerForLocalNotifications(). Don’t make any references to the field areNotificationsEnabled.
36 | 19. Instead of using a timer, perform the auto-connect logic when EAAccessory events are fired, the app launches, or the app comes to the foreground or becomes active.
37 | 20. Instead of DGPS, use the term SBAS.
38 | 21. Put all the swift code in a single file
39 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/src/main/java/com/bad_elf/badelfgps/BadElfDevice.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | * See LICENSE.txt for this sample's licensing information
4 | *
5 | */
6 |
7 | package com.bad_elf.badelfgps;
8 |
9 | import android.bluetooth.BluetoothAdapter;
10 | import android.bluetooth.BluetoothDevice;
11 | import android.content.Context;
12 | import android.os.Parcel;
13 | import android.os.Parcelable;
14 | import android.util.Log;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 | import java.util.Locale;
19 | import java.util.Set;
20 |
21 | /**
22 | * This class represents a Bad Elf GPS device.
23 | *
24 | * It is a wrapper around an android BluetoothDevice.
25 | *
26 | */
27 | public class BadElfDevice implements Parcelable {
28 |
29 | public static final String TAG = "BadElfDevice";
30 |
31 | /**
32 | * Gets paired Bad Elf Devices
33 | *
34 | * @param context Context just needed to get error messages
35 | *
36 | * @return A List of paired BadElfDevices
37 | *
38 | * @throws UnsupportedOperationException if this android device does not support bluetooth
39 | * @throws IllegalStateException if Bluetooth is not enabled or if there are no paired Bad Elf
40 | * Devices
41 | */
42 | public static List getPairedBadElfDevices(Context context){
43 |
44 | BluetoothAdapter bluetoothAdapter;
45 |
46 | bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
47 | if (bluetoothAdapter == null) {
48 | throw new UnsupportedOperationException(context.getString(R.string.badElfGpsErrorNoBluetooth));
49 | }
50 | if (!bluetoothAdapter.isEnabled()) {
51 | throw new IllegalStateException(context.getString(R.string.badElfGpsErrorBluetoothDisabled));
52 | }
53 |
54 | List result = new ArrayList<>();
55 |
56 | Set pairedDevices = bluetoothAdapter.getBondedDevices();
57 | Log.d(TAG,String.format(Locale.US,"Found %d pairedDevices",pairedDevices.size()));
58 |
59 | for (BluetoothDevice device : pairedDevices) {
60 | if( device.getName().startsWith("Bad Elf") ) {
61 | result.add(new BadElfDevice(device));
62 | }
63 |
64 | Log.d(TAG,String.format(Locale.US,"Name: %s", device.getName()));
65 | Log.d(TAG,String.format(Locale.US,"\tAddress: %s", device.getAddress()));
66 | Log.d(TAG,String.format(Locale.US,"\tClass: %s", device.getBluetoothClass().toString()));
67 | Log.d(TAG,String.format(Locale.US,"\tType: %d", device.getType()));
68 | }
69 |
70 | if(result.isEmpty()){
71 | throw new IllegalStateException(context.getString(R.string.badElfGpsErrorNoPairedDevices));
72 | }
73 |
74 | return result;
75 |
76 | }
77 |
78 |
79 | private BluetoothDevice device;
80 |
81 | /**
82 | * Get the wrapped Bluetooth device
83 | *
84 | * @return The BluetoothDevice
85 | */
86 | protected BluetoothDevice getDevice(){
87 | return device;
88 | }
89 |
90 | /**
91 | * Construct a BadElfDevice
92 | *
93 | * The constructor is private so only the static method getPairedDevices can call it.
94 | *
95 | * @param device A paired Bad Elf BluetoothDevice
96 | */
97 | private BadElfDevice(BluetoothDevice device){
98 | this.device = device;
99 | }
100 |
101 | /**
102 | * This is used by BadElfDeviceList to display the device name
103 | *
104 | * @return device name
105 | */
106 | @Override
107 | public String toString(){
108 | return device.getName();
109 | }
110 |
111 | /**
112 | * The following four methods implement the Parcelable interface so that BadElfDevice instances
113 | * can be passed through an Intent.
114 | */
115 |
116 | @Override
117 | public int describeContents() {
118 | return 0;
119 | }
120 |
121 | @Override
122 | public void writeToParcel(Parcel dest, int flags) {
123 | dest.writeParcelable(this.device, flags);
124 | }
125 |
126 | protected BadElfDevice(Parcel in) {
127 | this.device = in.readParcelable(BluetoothDevice.class.getClassLoader());
128 | }
129 |
130 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
131 | @Override
132 | public BadElfDevice createFromParcel(Parcel source) {
133 | return new BadElfDevice(source);
134 | }
135 |
136 | @Override
137 | public BadElfDevice[] newArray(int size) {
138 | return new BadElfDevice[size];
139 | }
140 | };
141 | }
142 |
--------------------------------------------------------------------------------
/samples/ios/swift/BadElfSampleGnssApp/BadElfSampleGnssApp.xcodeproj/xcuserdata/bretth.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
21 |
22 |
23 |
25 |
37 |
38 |
39 |
41 |
53 |
54 |
55 |
57 |
69 |
70 |
71 |
73 |
85 |
86 |
87 |
89 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/res/layout/activity_bad_elf_device_data.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
19 |
20 |
31 |
32 |
44 |
45 |
52 |
53 |
54 |
55 |
64 |
65 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
90 |
91 |
92 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample/Views/DetectionTableViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | Table View controller that lists the detected MFi accessories and opens sessions for them.
7 | */
8 |
9 | import UIKit
10 | import ExternalAccessory
11 |
12 | class DetectionTableViewController: UITableViewController {
13 |
14 | var sessionController: SessionController!
15 | var accessoryList: [EAAccessory]?
16 | var selectedAccessory: EAAccessory?
17 |
18 | override func viewDidLoad() {
19 | super.viewDidLoad()
20 | }
21 |
22 | override func viewWillAppear(_ animated: Bool) {
23 |
24 | NotificationCenter.default.addObserver(self, selector: #selector(accessoryDidConnect), name: NSNotification.Name.EAAccessoryDidConnect, object: nil)
25 | NotificationCenter.default.addObserver(self, selector: #selector(accessoryDidDisconnect), name: NSNotification.Name.EAAccessoryDidDisconnect, object: nil)
26 | EAAccessoryManager.shared().registerForLocalNotifications()
27 |
28 | sessionController = SessionController.sharedController
29 | accessoryList = EAAccessoryManager.shared().connectedAccessories
30 |
31 | super.viewWillAppear(animated)
32 | }
33 |
34 | override func viewWillDisappear(_ animated: Bool) {
35 |
36 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name.EAAccessoryDidConnect, object: nil)
37 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name.EAAccessoryDidDisconnect, object: nil)
38 |
39 | super.viewWillDisappear(animated)
40 | }
41 |
42 | override func didReceiveMemoryWarning() {
43 | super.didReceiveMemoryWarning()
44 | // Dispose of any resources that can be recreated.
45 | }
46 |
47 | // MARK: - Table view data source
48 |
49 | override func numberOfSections(in tableView: UITableView) -> Int {
50 | return 1
51 | }
52 |
53 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
54 | return accessoryList!.count
55 | }
56 |
57 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
58 | let cell = tableView.dequeueReusableCell(withIdentifier: "AccessoryCell", for: indexPath as IndexPath)
59 |
60 | // Configure the cell...
61 |
62 | var accessoryName = accessoryList?[indexPath.row].name
63 | if accessoryName == nil || accessoryName == "" {
64 | accessoryName = "Unknown Accessory"
65 | }
66 |
67 | cell.textLabel?.text = accessoryName
68 |
69 | return cell
70 | }
71 |
72 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
73 | selectedAccessory = accessoryList![indexPath.row]
74 |
75 | sessionController.setupController(forAccessory: selectedAccessory!, withProtocolString: (selectedAccessory?.protocolStrings[0])!)
76 |
77 | performSegue(withIdentifier: "showAccessoryConfig", sender: nil)
78 |
79 | tableView.deselectRow(at: indexPath as IndexPath, animated: true)
80 | }
81 |
82 |
83 | // MARK: - Navigation
84 |
85 | // In a storyboard-based application, you will often want to do a little preparation before navigation
86 | func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
87 | // Get the new view controller using segue.destinationViewController.
88 | // Pass the selected object to the new view controller.
89 | }
90 |
91 | // MARK: - EAAccessoryNotification Handlers
92 |
93 | @objc func accessoryDidConnect(notificaton: NSNotification) {
94 | let connectedAccessory = notificaton.userInfo![EAAccessoryKey]
95 | accessoryList?.append(connectedAccessory as! EAAccessory)
96 |
97 | let indexPath = NSIndexPath(row: (accessoryList!.count - 1), section: 0)
98 | tableView.insertRows(at: [indexPath as IndexPath], with: .automatic)
99 | }
100 |
101 | @objc func accessoryDidDisconnect(notification: NSNotification) {
102 | let disconnectedAccessory = notification.userInfo![EAAccessoryKey]
103 |
104 | if selectedAccessory != nil && (disconnectedAccessory as AnyObject).connectionID == selectedAccessory?.connectionID {
105 |
106 | }
107 |
108 | var disconnectedAccessoryIndex = 0
109 | for accessory in accessoryList! {
110 | if (disconnectedAccessory as AnyObject).connectionID == accessory.connectionID {
111 | break
112 | }
113 | disconnectedAccessoryIndex += 1
114 | }
115 |
116 | if disconnectedAccessoryIndex < (accessoryList?.count ?? 0) {
117 | accessoryList?.remove(at: disconnectedAccessoryIndex)
118 | let indexPath = NSIndexPath(row: disconnectedAccessoryIndex, section: 0)
119 | tableView.deleteRows(at: [indexPath as IndexPath], with: .right)
120 | } else {
121 | print("Could not find disconnected accessories in list")
122 | }
123 |
124 | if accessoryList?.count == 0 {
125 |
126 | }
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/src/main/java/com/bad_elf/badelfgps/BadElfRemoteControlServer.java:
--------------------------------------------------------------------------------
1 | package com.bad_elf.badelfgps;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.IOException;
6 | import java.io.OutputStream;
7 | import java.io.PrintStream;
8 | import java.net.InetAddress;
9 | import java.net.NetworkInterface;
10 | import java.net.ServerSocket;
11 | import java.net.Socket;
12 | import java.net.SocketException;
13 | import java.util.Enumeration;
14 | import java.util.Locale;
15 |
16 | public class BadElfRemoteControlServer {
17 |
18 | public static final String TAG = "BadElfRemoteControlServer";
19 |
20 | //MainActivity activity;
21 | ServerSocket serverSocket;
22 | String message = "";
23 | static final int socketServerPORT = 8080;
24 |
25 | public BadElfRemoteControlServer() {
26 | //this.activity = activity;
27 | Thread socketServerThread = new Thread(new SocketServerThread());
28 | socketServerThread.start();
29 | }
30 |
31 | public int getPort() {
32 | return socketServerPORT;
33 | }
34 |
35 | public void onDestroy() {
36 | if (serverSocket != null) {
37 | try {
38 | serverSocket.close();
39 | } catch (IOException e) {
40 | // TODO Auto-generated catch block
41 | e.printStackTrace();
42 | }
43 | }
44 | }
45 |
46 | private class SocketServerThread extends Thread {
47 |
48 | public static final String TAG = "BadElfRemoteControlServer.SocketServerThread";
49 |
50 | int count = 0;
51 |
52 | @Override
53 | public void run() {
54 | try {
55 | // create ServerSocket using specified port
56 | serverSocket = new ServerSocket(socketServerPORT);
57 | Log.d(TAG, String.format(Locale.US,"Starting ServerSocket on %s port %d...",getIpAddress(), socketServerPORT));
58 |
59 | while (true) {
60 | // block the call until connection is created and return
61 | // Socket object
62 | Socket socket = serverSocket.accept();
63 | count++;
64 | Log.d(TAG, "Got connection from: " + socket.getInetAddress() + ":" + socket.getPort());
65 |
66 | SocketServerReplyThread socketServerReplyThread =
67 | new SocketServerReplyThread(socket, count);
68 | socketServerReplyThread.run();
69 |
70 | }
71 | } catch (IOException e) {
72 | // TODO Auto-generated catch block
73 | e.printStackTrace();
74 | }
75 | }
76 | }
77 |
78 | private class SocketServerReplyThread extends Thread {
79 |
80 | private Socket hostThreadSocket;
81 | int cnt;
82 |
83 | SocketServerReplyThread(Socket socket, int c) {
84 | hostThreadSocket = socket;
85 | cnt = c;
86 | }
87 |
88 | @Override
89 | public void run() {
90 | OutputStream outputStream;
91 | String msgReply = "Hello from Server, you are #" + cnt;
92 |
93 | try {
94 | outputStream = hostThreadSocket.getOutputStream();
95 | PrintStream printStream = new PrintStream(outputStream);
96 | printStream.print(msgReply);
97 | printStream.close();
98 |
99 |
100 |
101 |
102 |
103 | message += "replayed: " + msgReply + "\n";
104 |
105 | // activity.runOnUiThread(new Runnable() {
106 | //
107 | // @Override
108 | // public void run() {
109 | // activity.msg.setText(message);
110 | // }
111 | // });
112 |
113 | } catch (IOException e) {
114 | // TODO Auto-generated catch block
115 | e.printStackTrace();
116 | message += "Something wrong! " + e.toString() + "\n";
117 | }
118 |
119 | // activity.runOnUiThread(new Runnable() {
120 | //
121 | // @Override
122 | // public void run() {
123 | // activity.msg.setText(message);
124 | // }
125 | // });
126 | }
127 |
128 | }
129 |
130 | public String getIpAddress() {
131 | String ip = "";
132 | try {
133 | Enumeration enumNetworkInterfaces = NetworkInterface
134 | .getNetworkInterfaces();
135 | while (enumNetworkInterfaces.hasMoreElements()) {
136 | NetworkInterface networkInterface = enumNetworkInterfaces
137 | .nextElement();
138 | Enumeration enumInetAddress = networkInterface
139 | .getInetAddresses();
140 | while (enumInetAddress.hasMoreElements()) {
141 | InetAddress inetAddress = enumInetAddress
142 | .nextElement();
143 |
144 | if (inetAddress.isSiteLocalAddress()) {
145 | ip += "Server running at : "
146 | + inetAddress.getHostAddress();
147 | }
148 | }
149 | }
150 |
151 | } catch (SocketException e) {
152 | // TODO Auto-generated catch block
153 | e.printStackTrace();
154 | ip += "Something Wrong! " + e.toString() + "\n";
155 | }
156 | return ip;
157 | }
158 | }
--------------------------------------------------------------------------------
/samples/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample/Controllers/SessionController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | Controller for managing connected accessory and communicating with the accessory via NSInput & NSOutput streams.
7 | */
8 |
9 | import UIKit
10 | import ExternalAccessory
11 |
12 | class SessionController: NSObject, EAAccessoryDelegate, StreamDelegate {
13 |
14 | static let sharedController = SessionController()
15 | var _accessory: EAAccessory?
16 | var _session: EASession?
17 | var _protocolString: String?
18 | var _writeData: NSMutableData?
19 | var _readData: NSMutableData?
20 | var _dataAsString: NSString?
21 |
22 | // MARK: Controller Setup
23 |
24 | func setupController(forAccessory accessory: EAAccessory, withProtocolString protocolString: String) {
25 | _accessory = accessory
26 | _protocolString = protocolString
27 | }
28 |
29 | // MARK: Opening & Closing Sessions
30 |
31 | func openSession() -> Bool {
32 | _accessory?.delegate = self
33 | _session = EASession(accessory: _accessory!, forProtocol: _protocolString!)
34 |
35 | if _session != nil {
36 | _session?.inputStream?.delegate = self
37 | _session?.inputStream?.schedule(in: RunLoop.current, forMode: RunLoop.Mode.default)
38 | _session?.inputStream?.open()
39 |
40 | _session?.outputStream?.delegate = self
41 | _session?.outputStream?.schedule(in: RunLoop.current, forMode: RunLoop.Mode.default)
42 | _session?.outputStream?.open()
43 | } else {
44 | print("Failed to create session")
45 | }
46 |
47 | return _session != nil
48 | }
49 |
50 | func closeSession() {
51 |
52 | _session?.inputStream?.close()
53 | _session?.inputStream?.remove(from: RunLoop.current, forMode: RunLoop.Mode.default)
54 | _session?.inputStream?.delegate = nil
55 |
56 | _session?.outputStream?.close()
57 | _session?.outputStream?.remove(from: RunLoop.current, forMode: RunLoop.Mode.default)
58 | _session?.outputStream?.delegate = nil
59 |
60 | _session = nil
61 | _writeData = nil
62 | _readData = nil
63 | }
64 |
65 | // MARK: Write & Read Data
66 |
67 | func writeData(data: NSData) {
68 | if _writeData == nil {
69 | _writeData = NSMutableData()
70 | }
71 |
72 | _writeData?.append(data as Data)
73 | self.writeData()
74 | }
75 |
76 | func readData(bytesToRead: Int) -> NSData {
77 |
78 | var data: NSData?
79 | if _readData?.length ?? 0 >= bytesToRead {
80 | let range = NSMakeRange(0, bytesToRead)
81 | data = _readData?.subdata(with: range) as NSData?
82 | _readData?.replaceBytes(in: range, withBytes: nil, length: 0)
83 | }
84 |
85 | return data!
86 | }
87 |
88 | func readBytesAvailable() -> Int {
89 | return (_readData?.length)!
90 | }
91 |
92 | // MARK: - Helpers
93 | func updateReadData() {
94 | let bufferSize = 1024
95 | var buffer = [UInt8](repeating: 0, count: bufferSize)
96 |
97 | while _session?.inputStream?.hasBytesAvailable == true {
98 | let bytesRead = _session?.inputStream?.read(&buffer, maxLength: bufferSize)
99 | if _readData == nil {
100 | _readData = NSMutableData()
101 | }
102 | _readData?.append(buffer, length: bytesRead!)
103 | _dataAsString = String(bytes: buffer, encoding: String.Encoding.nonLossyASCII) as NSString?
104 | NotificationCenter.default.post(name: NSNotification.Name(rawValue: "BESessionDataReceivedNotification"), object: nil)
105 | }
106 | }
107 |
108 | private func writeData() {
109 | while _session?.outputStream?.hasSpaceAvailable == true && _writeData?.length ?? 0 > 0 {
110 | var buffer = [UInt8](repeating: 0, count: _writeData!.length)
111 | _writeData?.getBytes(&buffer, length: (_writeData?.length)!)
112 | let bytesWritten = _session?.outputStream?.write(&buffer, maxLength: _writeData!.length)
113 | if bytesWritten == -1 {
114 | print("Write Error")
115 | return
116 | } else if bytesWritten ?? 0 > 0 {
117 | _writeData?.replaceBytes(in: NSMakeRange(0, bytesWritten!), withBytes: nil, length: 0)
118 | }
119 | }
120 | }
121 |
122 | // MARK: - EAAcessoryDelegate
123 |
124 | func accessoryDidDisconnect(_ accessory: EAAccessory) {
125 | // Accessory diconnected from iOS, updating accordingly
126 | }
127 |
128 | // MARK: - NSStreamDelegateEventExtensions
129 |
130 | func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
131 | switch eventCode {
132 | // case Stream.Event.None:
133 | // break
134 | case Stream.Event.openCompleted:
135 | break
136 | case Stream.Event.hasBytesAvailable:
137 | // Read Data
138 | updateReadData()
139 | break
140 | case Stream.Event.hasSpaceAvailable:
141 | // Write Data
142 | self.writeData()
143 | break
144 | case Stream.Event.errorOccurred:
145 | break
146 | case Stream.Event.endEncountered:
147 | break
148 |
149 | default:
150 | break
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/EADSessionTransferViewController.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | View controller to allow transferring data to and from an accessory form the UI.
7 | */
8 |
9 |
10 | #import "EADSessionTransferViewController.h"
11 | #import "EADSessionController.h"
12 |
13 | @interface EADSessionTransferViewController ()
14 |
15 | @property(nonatomic) uint32_t totalBytesRead;
16 | @property(nonatomic, strong) IBOutlet EAAccessory *accessory;
17 | @property(nonatomic, strong) IBOutlet UILabel *receivedBytesCountLabel;
18 | @property(nonatomic, strong) IBOutlet UITextField *stringToSendText;
19 | @property(nonatomic, strong) IBOutlet UITextField *hexToSendText;
20 |
21 | @end
22 |
23 | @implementation EADSessionTransferViewController
24 |
25 | // send test string to the accessory
26 | - (IBAction)sendStringButtonPressed:(id)sender;
27 | {
28 | if ([_stringToSendText isFirstResponder]) {
29 | [_stringToSendText resignFirstResponder];
30 | }
31 |
32 | const char *buf = [[_stringToSendText text] UTF8String];
33 | if (buf)
34 | {
35 | uint32_t len = (uint32_t)strlen(buf) + 1;
36 | [[EADSessionController sharedController] writeData:[NSData dataWithBytes:buf length:len]];
37 | }
38 | }
39 |
40 | // Interpret a UITextField's string at a sequence of hex bytes and send those bytes to the accessory
41 | - (IBAction)sendHexButtonPressed:(id)sender;
42 | {
43 | if ([_hexToSendText isFirstResponder]) {
44 | [_hexToSendText resignFirstResponder];
45 | }
46 |
47 | const char *buf = [[_hexToSendText text] UTF8String];
48 | NSMutableData *data = [NSMutableData data];
49 | if (buf)
50 | {
51 | uint32_t len = (uint32_t)strlen(buf);
52 |
53 | char singleNumberString[3] = {'\0', '\0', '\0'};
54 | uint32_t singleNumber = 0;
55 | for(uint32_t i = 0 ; i < len; i+=2)
56 | {
57 | if ( ((i+1) < len) && isxdigit(buf[i]) && (isxdigit(buf[i+1])) )
58 | {
59 | singleNumberString[0] = buf[i];
60 | singleNumberString[1] = buf[i + 1];
61 | sscanf(singleNumberString, "%x", &singleNumber);
62 | uint8_t tmp = (uint8_t)(singleNumber & 0x000000FF);
63 | [data appendBytes:(void *)(&tmp) length:1];
64 | }
65 | else
66 | {
67 | break;
68 | }
69 | }
70 |
71 | [[EADSessionController sharedController] writeData:data];
72 | }
73 | }
74 |
75 | // send 10K of data to the accessory.
76 | - (IBAction)send10KButtonPressed:(id)sender
77 | {
78 | #define STRESS_TEST_BYTE_COUNT 10000
79 | NSLog(@"send10KButtonPressed");
80 | uint8_t buf[STRESS_TEST_BYTE_COUNT];
81 | for(int i = 0; i < STRESS_TEST_BYTE_COUNT; i++) {
82 | buf[i] = (i & 0xFF); // fill buf with incrementing bytes;
83 | }
84 |
85 | [[EADSessionController sharedController] writeData:[NSData dataWithBytes:buf length:STRESS_TEST_BYTE_COUNT]];
86 | }
87 |
88 | #pragma mark UIViewController
89 |
90 | - (void)viewWillAppear:(BOOL)animated
91 | {
92 | [super viewWillAppear:animated];
93 | // watch for the accessory being disconnected
94 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_accessoryDidDisconnect:) name:EAAccessoryDidDisconnectNotification object:nil];
95 | // watch for received data from the accessory
96 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_sessionDataReceived:) name:EADSessionDataReceivedNotification object:nil];
97 |
98 | EADSessionController *sessionController = [EADSessionController sharedController];
99 |
100 | _accessory = [sessionController accessory];
101 | [self setTitle:[sessionController protocolString]];
102 | [sessionController openSession];
103 | _totalBytesRead = 0;
104 | }
105 |
106 | - (void)viewWillDisappear:(BOOL)animated
107 | {
108 | [super viewWillDisappear:animated];
109 | // remove the observers
110 | [[NSNotificationCenter defaultCenter] removeObserver:self name:EAAccessoryDidConnectNotification object:nil];
111 | [[NSNotificationCenter defaultCenter] removeObserver:self name:EADSessionDataReceivedNotification object:nil];
112 |
113 | EADSessionController *sessionController = [EADSessionController sharedController];
114 |
115 | [sessionController closeSession];
116 | // _accessory = nil;
117 | }
118 |
119 | - (void)viewDidUnload
120 | {
121 | [super viewDidUnload];
122 | }
123 |
124 | #pragma mark UITextFieldDelegate
125 |
126 | - (BOOL)textFieldShouldReturn:(UITextField *)textField
127 | {
128 | [textField resignFirstResponder];
129 | return YES;
130 | }
131 |
132 | #pragma mark Internal
133 |
134 | - (void)_accessoryDidDisconnect:(NSNotification *)notification
135 | {
136 | if ([[self navigationController] topViewController] == self)
137 | {
138 | EAAccessory *disconnectedAccessory = [[notification userInfo] objectForKey:EAAccessoryKey];
139 | if ([disconnectedAccessory connectionID] == [_accessory connectionID])
140 | {
141 | [[self navigationController] popViewControllerAnimated:YES];
142 |
143 | }
144 | }
145 | }
146 |
147 | // Data was received from the accessory, real apps should do something with this data but currently:
148 | // 1. bytes counter is incremented
149 | // 2. bytes are read from the session controller and thrown away
150 | - (void)_sessionDataReceived:(NSNotification *)notification
151 | {
152 | EADSessionController *sessionController = (EADSessionController *)[notification object];
153 | uint32_t bytesAvailable = 0;
154 |
155 | while ((bytesAvailable = (uint32_t)[sessionController readBytesAvailable]) > 0) {
156 | NSData *data = [sessionController readData:bytesAvailable];
157 | if (data) {
158 |
159 | _totalBytesRead = _totalBytesRead + bytesAvailable;
160 | }
161 | }
162 |
163 | [_receivedBytesCountLabel setText:[NSString stringWithFormat:@"Bytes Received from Session: %u", (unsigned int)_totalBytesRead]];
164 | }
165 |
166 | @end
167 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/EADSessionController.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | Provides an interface for communication with an EASession. Also the delegate for the EASession input and output stream objects.
7 | */
8 |
9 | #import "EADSessionController.h"
10 | @interface EADSessionController ()
11 |
12 | @property (nonatomic, strong) EASession *session;
13 | @property (nonatomic, strong) NSMutableData *writeData;
14 | @property (nonatomic, strong) NSMutableData *readData;
15 |
16 | @end
17 |
18 | NSString *EADSessionDataReceivedNotification = @"EADSessionDataReceivedNotification";
19 |
20 | @implementation EADSessionController
21 |
22 | #pragma mark Internal
23 |
24 | // low level write method - write data to the accessory while there is space available and data to write
25 | - (void)_writeData {
26 | while (([[_session outputStream] hasSpaceAvailable]) && ([_writeData length] > 0))
27 | {
28 | NSInteger bytesWritten = [[_session outputStream] write:[_writeData bytes] maxLength:[_writeData length]];
29 | if (bytesWritten == -1)
30 | {
31 | NSLog(@"%@: write error", DEMO_APP_NAME);
32 | break;
33 | }
34 | else if (bytesWritten > 0)
35 | {
36 | [_writeData replaceBytesInRange:NSMakeRange(0, bytesWritten) withBytes:NULL length:0];
37 | NSLog(@"%@bytesWritten %ld", DEMO_APP_NAME, (long)bytesWritten);
38 |
39 | }
40 | }
41 | }
42 |
43 | // low level read method - read data while there is data and space available in the input buffer
44 | - (void)_readData {
45 | #define EAD_INPUT_BUFFER_SIZE 1024
46 | char buf[EAD_INPUT_BUFFER_SIZE+1];
47 | while ([[_session inputStream] hasBytesAvailable])
48 | {
49 | NSInteger bytesRead = [[_session inputStream] read:buf maxLength:EAD_INPUT_BUFFER_SIZE];
50 | if (_readData == nil) {
51 | _readData = [[NSMutableData alloc] init];
52 | }
53 | [_readData appendBytes:(void *)buf length:bytesRead];
54 | NSLog(@"%@: read %ld bytes from input stream", DEMO_APP_NAME, (long)bytesRead);
55 |
56 | if (bytesRead > 0) {
57 | buf[bytesRead] = 0; // NULL terminate
58 | NSString *ascii = [[NSString alloc] initWithUTF8String:buf];
59 | NSLog(@"%@:\n%@", DEMO_APP_NAME, ascii);
60 | }
61 | }
62 |
63 | [[NSNotificationCenter defaultCenter] postNotificationName:EADSessionDataReceivedNotification object:self userInfo:nil];
64 | }
65 |
66 | #pragma mark Public Methods
67 |
68 | + (EADSessionController *)sharedController
69 | {
70 | static EADSessionController *sessionController = nil;
71 | if (sessionController == nil) {
72 | sessionController = [[EADSessionController alloc] init];
73 | }
74 |
75 | return sessionController;
76 | }
77 |
78 | - (void)dealloc
79 | {
80 | [self closeSession];
81 | [self setupControllerForAccessory:nil withProtocolString:nil];
82 | }
83 |
84 | // initialize the accessory with the protocolString
85 | - (void)setupControllerForAccessory:(EAAccessory *)accessory withProtocolString:(NSString *)protocolString
86 | {
87 | NSLog(@"%@: setupControllerForAccessory entered protocolString is %@", DEMO_APP_NAME, protocolString);
88 | _accessory = accessory;
89 | _protocolString = [protocolString copy];
90 | }
91 |
92 | // open a session with the accessory and set up the input and output stream on the default run loop
93 | - (BOOL)openSession
94 | {
95 | [_accessory setDelegate:self];
96 | _session = [[EASession alloc] initWithAccessory:_accessory forProtocol:_protocolString];
97 |
98 | if (_session)
99 | {
100 | [[_session inputStream] setDelegate:self];
101 | [[_session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
102 | [[_session inputStream] open];
103 |
104 | [[_session outputStream] setDelegate:self];
105 | [[_session outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
106 | [[_session outputStream] open];
107 | }
108 | else
109 | {
110 | NSLog(@"%@: creating session failed", DEMO_APP_NAME);
111 | }
112 |
113 | return (_session != nil);
114 | }
115 |
116 | // close the session with the accessory.
117 | - (void)closeSession
118 | {
119 | [[_session inputStream] close];
120 | [[_session inputStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
121 | [[_session inputStream] setDelegate:nil];
122 | [[_session outputStream] close];
123 | [[_session outputStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
124 | [[_session outputStream] setDelegate:nil];
125 |
126 | _session = nil;
127 |
128 | _writeData = nil;
129 | _readData = nil;
130 | }
131 |
132 | // high level write data method
133 | - (void)writeData:(NSData *)data
134 | {
135 | if (_writeData == nil) {
136 | _writeData = [[NSMutableData alloc] init];
137 | }
138 |
139 | [_writeData appendData:data];
140 | [self _writeData];
141 | }
142 |
143 | // high level read method
144 | - (NSData *)readData:(NSUInteger)bytesToRead
145 | {
146 | NSData *data = nil;
147 | if ([_readData length] >= bytesToRead) {
148 | NSRange range = NSMakeRange(0, bytesToRead);
149 | data = [_readData subdataWithRange:range];
150 | [_readData replaceBytesInRange:range withBytes:NULL length:0];
151 | }
152 | return data;
153 | }
154 |
155 | // get number of bytes read into local buffer
156 | - (NSUInteger)readBytesAvailable
157 | {
158 | return [_readData length];
159 | }
160 |
161 | #pragma mark EAAccessoryDelegate
162 | - (void)accessoryDidDisconnect:(EAAccessory *)accessory
163 | {
164 | // do something ...
165 | }
166 |
167 | #pragma mark NSStreamDelegateEventExtensions
168 |
169 | // asynchronous NSStream handleEvent method
170 | - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
171 | {
172 | switch (eventCode) {
173 | case NSStreamEventNone:
174 | break;
175 | case NSStreamEventOpenCompleted:
176 | break;
177 | case NSStreamEventHasBytesAvailable:
178 | [self _readData];
179 | break;
180 | case NSStreamEventHasSpaceAvailable:
181 | [self _writeData];
182 | break;
183 | case NSStreamEventErrorOccurred:
184 | break;
185 | case NSStreamEventEndEncountered:
186 | break;
187 | default:
188 | break;
189 | }
190 | }
191 |
192 | @end
193 |
--------------------------------------------------------------------------------
/samples/ios/swift/old/GPS Sample/Views/ConfigurationViewController.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | View controller that allows configuration of the protocol strings to the Bad Elf accessory.
7 | */
8 |
9 | import UIKit
10 | import ExternalAccessory
11 |
12 | class ConfigurationViewController: UIViewController {
13 |
14 | @IBOutlet weak var textView: UITextView!
15 | var sessionController: SessionController!
16 | var accessory: EAAccessory?
17 |
18 | override func viewDidLoad() {
19 | super.viewDidLoad()
20 |
21 | // Do any additional setup after loading the view.
22 |
23 | self.title = "Accessory"
24 | }
25 |
26 | override func viewWillAppear(_ animated: Bool) {
27 |
28 | NotificationCenter.default.addObserver(self, selector: #selector(sessionDataReceived), name: NSNotification.Name(rawValue: "BESessionDataReceivedNotification"), object: nil)
29 | NotificationCenter.default.addObserver(self, selector: #selector(accessoryDidDisconnect), name: NSNotification.Name.EAAccessoryDidDisconnect, object: nil)
30 |
31 | sessionController = SessionController.sharedController
32 |
33 | accessory = sessionController._accessory
34 | let _ = sessionController.openSession()
35 |
36 | super.viewWillAppear(animated)
37 | }
38 |
39 | override func viewWillDisappear(_ animated: Bool) {
40 |
41 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "BESessionDataReceivedNotification"), object: nil)
42 | NotificationCenter.default.removeObserver(self, name: NSNotification.Name.EAAccessoryDidDisconnect, object: nil)
43 |
44 | sessionController.closeSession()
45 |
46 | super.viewWillDisappear(animated)
47 | }
48 |
49 | override func didReceiveMemoryWarning() {
50 | super.didReceiveMemoryWarning()
51 | // Dispose of any resources that can be recreated.
52 | }
53 |
54 | // MARK: - Interface Actions
55 |
56 | @IBAction func segmentedControlForBasicDataDidChange(sender: UISegmentedControl) {
57 | var configString: String!
58 | switch sender.selectedSegmentIndex {
59 | case 0:
60 | // 1Hz Updates
61 | configString = "24be001105010205310132043301640d0a"
62 | break
63 | case 1:
64 | // 2 Hz Updates
65 | configString = "24be001104010206310232043301630d0a"
66 | break
67 | case 2:
68 | // 4 Hz Updates
69 | configString = "24be001107010203310432113301540d0a"
70 | break
71 | case 3:
72 | // 5 Hz Updates
73 | configString = "24be001106010204310532043301600d0a"
74 | break
75 | case 4:
76 | // 10 Hz Updates
77 | configString = "24be001108010202310a320433015b0d0a"
78 | break
79 | default:
80 | break
81 | }
82 |
83 | configureAccessoryWithString(configString: configString)
84 |
85 | }
86 |
87 | @IBAction func segmentedControlForSatDataDidChange(sender: UISegmentedControl) {
88 | var configString: String!
89 | switch sender.selectedSegmentIndex {
90 | case 0:
91 | // 1Hz Updates
92 | configString = "24be00110b0102ff310132043302630d0a"
93 | break
94 | case 1:
95 | // 2 Hz Updates
96 | configString = "24be0011100102fa310232043302620d0a"
97 | break
98 | case 2:
99 | // 4 Hz Updates
100 | configString = "24be0011120102f8310432043302600d0a"
101 | break
102 | case 3:
103 | // 5 Hz Updates
104 | configString = "24be0011130102f73105320433025f0d0a"
105 | break
106 | case 4:
107 | // 10 Hz Updates
108 | configString = "24be0011160102f4310a320433025a0d0a"
109 | break
110 | default:
111 | break
112 | }
113 |
114 | configureAccessoryWithString(configString: configString)
115 | }
116 |
117 | // MARK: - Session Updates
118 |
119 | @objc func sessionDataReceived(notification: NSNotification) {
120 |
121 | if sessionController._dataAsString != nil {
122 | textView.textStorage.beginEditing()
123 | textView.textStorage.mutableString.appendFormat(sessionController._dataAsString!)
124 | textView.textStorage.endEditing()
125 | textView.scrollRangeToVisible(NSMakeRange(textView.textStorage.length, 0))
126 | }
127 | }
128 |
129 | // MARK: - EAAccessory Disconnection
130 |
131 | @objc func accessoryDidDisconnect(notification: NSNotification) {
132 | if navigationController?.topViewController == self {
133 | let disconnectedAccessory = notification.userInfo![EAAccessoryKey]
134 | if (disconnectedAccessory as AnyObject).connectionID == accessory?.connectionID {
135 | dismiss(animated: true, completion: nil)
136 | }
137 | }
138 | }
139 |
140 | func configureAccessoryWithString(configString: String) {
141 |
142 | let data = configString.dataFromHexadecimalString()
143 | sessionController.writeData(data: data!)
144 | }
145 |
146 | }
147 |
148 | extension String {
149 | func dataFromHexadecimalString() -> NSData? {
150 | let trimmedString = self.trimmingCharacters(in: (NSCharacterSet(charactersIn: "<>".replacingOccurrences(of: " ", with: "")) as CharacterSet))
151 |
152 | let regex = try! NSRegularExpression(pattern: "^[0-9a-f]*$", options: .caseInsensitive)
153 |
154 | let found = regex.firstMatch(in: trimmedString, options: [], range: NSMakeRange(0, trimmedString.count))
155 | if found == nil || found?.range.location == NSNotFound || trimmedString.count % 2 != 0 {
156 | return nil
157 | }
158 |
159 | // everything ok, so now let's build NSData
160 |
161 | let data = NSMutableData(capacity: trimmedString.count / 2)
162 |
163 | var index = trimmedString.startIndex
164 |
165 | while index < trimmedString.endIndex {
166 | let byteString = trimmedString[index...trimmedString.index(index, offsetBy:1)]
167 | let num = UInt8(byteString.withCString { strtoul($0, nil, 16) })
168 | data?.append([num] as [UInt8], length: 1)
169 | index = trimmedString.index(index, offsetBy: 2)
170 | }
171 |
172 | return data
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/README.md:
--------------------------------------------------------------------------------
1 | # EADemo
2 |
3 | 1.2
4 | Updated for iOS 9. Implements Storyboard support.
5 |
6 | ## Requirements
7 |
8 | ### Building
9 |
10 | Xcode 7.3
11 | The sample was built using Xcode 7.3 on OS X 10.11.5 with the 1OS 9 SDK.
12 |
13 | ### Runtime
14 |
15 | iOS 9.x
16 | The sample requires iOS 8.0, but the core code works fine on all versions of iOS to iOS 7.
17 |
18 | ### Packing List
19 |
20 | The sample contains the following items:
21 | * README.md -- This file.
22 | * LICENSE.txt — The standard sample code license.
23 | * EADemo.xcodeproj -- An Xcode project for the sample.
24 | * EADemo_Prefix.pch -- Prefix header for all source files in the EADemo project.
25 | * Info.plist -- The application Info.plist file.
26 | * EADSessionController.[hm] -- Provides an interface for communication with an EASession. It is also the delegate for the EASession input and output stream objects.
27 | * EADSessionTransferViewController.[hm] -- A view controller to allow transferring data to and from an accessory form the UI.
28 | * EADemoAppDelegate.[hm] -- A delegate object for the User Interface.
29 | * RootViewController.[hm] -- A table view controller for watching the device come and go.
30 |
31 | ## Using the sample
32 |
33 | Before you build the sample, open Info.plist and enter the protocolString for your accessory in the "Supported external accessory protocols" property. If the protocolString is not registered in the Info.plist, the attempt to open an EASession with the accessory will fail.
34 | The sample can be used with any Made For iPod (MFI) accessory designed for use with the External Accessory Framework. The application will display all attached External Accessories in the "Accessories" table view, provide information registered by the MFI accessory, and provides methods to send and receive data to the accessory. Information about MFI accessories is available to licensees of the MFI program. You can learn more about the MFI program at the Apple Developer Connection "Made For iPod Program" web page .
35 | When the MFI accessory is attached, iOS reads the MFI accessory provided information that includes the supported protocol strings. The system searches for a matching protocol string in the UISupportedExternalAccessoryProtocols array of the Info.plist of all the installed applications. If no matching protocol string is found, iOS raises the "Application Not Installed" alert. You can modify the UISupportedExternalAccessoryProtocols property in the Info.plist to include the protocol string registered by your accessory, to keep the system from presenting the "Application Not Installed" alert on accessory attachment.
36 | At the "Accessories" table view, the name of all attached MFI accessories are displayed. Click on the accessory name to see a list of supported protocols. Under iOS 5+, if the application has the protocol string defined in the UISupportedExternalAccessoryProtocols property, then select the protocol, and the application will use the protocol to open a session for communication with the accessory. If the protocol has not been previously defined, an alert is present to indicate that the protocolString is not defined in the Info.plist, and the session is be opened.
37 | Under iOS 4.x and 3.2, the External Accessory Framework allows a connection to be opened regardless whether the protocol string is defined in the UISupportedExternalAccessoryProtocols property.
38 | The Protocol table view provides options for three different ways to send data to the accessory. There is also a counter to display the number of bytes received from the accessory. The three buttons and the methods that are called are
39 | "Send String" - sendString - sends the string entered in the UITextField it's associated with in the view to the accessory.
40 | "Send Hex Data" - sendHex - sends the string entered in the UITextField it's associated with in the view interpreted as a hex byte sequence to the accessory.
41 | "Send 10K" - send10K - sends 10K bytes of incrementing 8-bit values (0 to 255) to the accessory.
42 | If the accessory is detached, the application will detect this action and reset itself to the main Accessories table view. When no accessory is attached, the main screen will display the message "No Accessories Connected".
43 | Under iOS 5, when EADemo is put into the background, the application will continue to support an open connection. iOS 5 looks for the "external-accessory" string in the UIBackgroundModes key, and will support open sessions with an accessory while in the background. If the "external-accessory" is not declared, then when the application is put into the background, it will receive the didDisconnectNotification for each attached accessory as it does under iOS 4.x and 3.2.
44 | Under iOS 4.x and earlier, when EADemo is put into the background, the application will receive the didDisconnectNotification for attached accessories. While in the background, there is no support for open sessions. When the application is brought to the foreground, it will receive a didConnectNotification for each attached accessory.
45 | For more information about Multitasking support, please read the "iOS Application Programming Guide" sections on "Multitasking" and "Executing Code in the Background".
46 |
47 | For iOS 5.0
48 | iOS 5.0 provides background session support to process incoming data from an external accessory. Including the UIBackgroundModes key with the external-accessory value in your application’s Info.plist file keeps your accessory sessions open even when your application is suspended. (Prior to iOS 5, these sessions were closed automatically at suspend time.) When new data arrives for a given session, a suspended app is woken up and given time to process the new data. This type of behavior is designed for applications that work with accessories that need to deliver data at regular intervals.
49 | The iOS 5.0 application which sets background support will not receive a didDisconnectNotification when the application moves to the background. The session will stay open and continue to receive new data from the accessory via the handleEvent method. The application must follow the standard guidelines as documented in the App Programming Guide for iOS
50 | When the application is active and an MFI accessory is attached, you may observe the accessory momentarily displayed in the table view. The application has received the EAAccessoryDidConnectNotification but the accessory identification / authentication process is incomplete. The accessory will note that the protocolStrings is empty for this event. The accessory will receive the EAAccessoryDidDisconnectNotification event. Moments later, the application will receive the EAAccessoryDidConnectNotification, this time the protocolStrings array will contain the protocolString(s) registered by the accessory.
51 |
52 | ## Version History
53 | 1.0 - First shipping version
54 | 1.1 - (Feb 2012) - implemented background support and check for registered protocolString
55 | 1.2 - (June 2016) - fixed crash in iOS 9 and added Storyboard support.
56 | If you find any problems with this sample, please file a bug against it.
57 |
58 |
59 |
60 | Apple Developer Technical Support
61 | Core OS/Hardware
62 | Copyright (C) 2016 Apple Inc. All rights reserved.
63 |
64 |
--------------------------------------------------------------------------------
/samples/android/badelfgps/src/main/java/com/bad_elf/badelfgps/BadElfGpsConnection.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | * See LICENSE.txt for this sample's licensing information
4 | *
5 | */
6 |
7 | package com.bad_elf.badelfgps;
8 |
9 | import android.content.ComponentName;
10 | import android.content.Context;
11 | import android.content.Intent;
12 | import android.content.ServiceConnection;
13 | import android.os.IBinder;
14 | import android.util.Log;
15 |
16 | import com.bad_elf.badelfgps.BadElfService.State;
17 |
18 | /**
19 | * This class controls the connection to a Bad Elf Device.
20 | *
21 | * Most of the actual work is performed by the BadElfService class.
22 | *
23 | * When this class is instantiated it Binds to the BadElfService and it Unbinds when onDestroy is
24 | * called. After Binding to the BadElfService connect can be called and the Service will be started
25 | * and will continue to run until disconnect is called or until there is an error.
26 | *
27 | */
28 | public class BadElfGpsConnection {
29 |
30 | private static String TAG = "BadElfGpsConnection";
31 |
32 | private final BadElfGpsConnectionObserver observer;
33 | private final Context appContext;
34 | private BadElfService badElfService;
35 |
36 | /**
37 | * Create a BadElfGpsConnection instance
38 | *
39 | * @param observer A class that implements BadElfGpsConnectionObserver
40 | * @param context used to grab the application context that will be used to bind and unbind the Service
41 | */
42 | public BadElfGpsConnection(final BadElfGpsConnectionObserver observer, final Context context){
43 | this.observer = observer;
44 | appContext = context.getApplicationContext(); // get an application context so we don't hold the Activity context
45 |
46 | // Bind To the Service.
47 | Intent intent = new Intent(appContext, BadElfService.class);
48 | boolean bound = appContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
49 | Log.d(TAG, "bound = "+bound);
50 | }
51 |
52 | private final ServiceConnection serviceConnection = new ServiceConnection() {
53 | /**
54 | * Called when the service is connected to us
55 | *
56 | * @param name Unused
57 | * @param binder The Binder from the Service
58 | */
59 | @Override
60 | public void onServiceConnected(ComponentName name, IBinder binder) {
61 | Log.d(TAG, "onServiceConnected");
62 | badElfService = ((BadElfService.BadElfBinder)binder).getServiceInstance(); // get the service instance
63 | badElfService.addObserver(observer); // add the observer to the service
64 | observer.onReady(); // tell the observer that we are ready to go
65 | }
66 |
67 | @Override
68 | public void onServiceDisconnected(ComponentName name) {
69 | // onServiceDisconnected is only called if the service is killed or crashes.
70 | // but a local service runs in the same process as the app so if the
71 | // service gets killed or crashes the app will also be killed.
72 | // Meaning this code should never get called.
73 | throw new AssertionError("Unexpected onServiceDisconnected");
74 | }
75 | };
76 |
77 |
78 | /**
79 | * Destroy the BadElfGpsConnection instance
80 | *
81 | * NOTE: If there is an active connection to the Bad Elf Device this does not cause that to
82 | * disconnect. To disconnect from the Bad Elf Device disconnect must be called. The connection
83 | * to the Bad Elf Device is not tied to an instance of BadElfGpsConnection
84 | *
85 | */
86 | public void onDestroy(){
87 | Log.d(TAG, "onDestroy");
88 | try {
89 | ifBadElfServiceIsBound().removeObserver(observer); // Tell the service the observer is not interested in hearing from it anymore.
90 | badElfService = null;
91 | appContext.unbindService(serviceConnection); // We don't need to talk to the service anymore.
92 | }catch (NotBoundToServiceException | IllegalArgumentException e){
93 | // This could happen if we call onDestroy before onServiceConnected runs or if
94 | // onDestroy is called twice. Ignore because we are already destroyed
95 | }
96 | }
97 |
98 | // Exception thrown if the wrapper methods below are called before onServiceConnected runs or
99 | // after onDestroy is called.
100 | public static class NotBoundToServiceException extends IllegalStateException {
101 | public NotBoundToServiceException() {
102 | super("Not Bound To Service Exception");
103 | }
104 | }
105 |
106 | /**
107 | * If not bound to service Throw NotBoundToServiceException
108 | *
109 | * @return a copied reference to the badElfService
110 | *
111 | */
112 | private BadElfService ifBadElfServiceIsBound(){
113 | BadElfService temp = badElfService;
114 | if (temp == null)
115 | throw new NotBoundToServiceException();
116 | return temp;
117 | }
118 |
119 | /**
120 | * The following five methods are wrappers around the methods in BadElfService
121 | *
122 | * If called when not bound to the BadElfService, NotBoundToServiceException will be thrown.
123 | *
124 | */
125 |
126 | public void setBadElfDevice(BadElfDevice badElfDevice) { ifBadElfServiceIsBound().setBadElfDevice((badElfDevice)); }
127 | public void setBadElfRemoteController(BadElfRemoteController remoteController) { ifBadElfServiceIsBound().setBadElfRemoteController((remoteController)); }
128 | public void connect() { ifBadElfServiceIsBound().connect(); }
129 | public void sendData(final byte[] data) { ifBadElfServiceIsBound().sendData(data); }
130 | public void disconnect() { ifBadElfServiceIsBound().disconnect(); }
131 | public State getState() { return ifBadElfServiceIsBound().getState(); }
132 |
133 |
134 | /**
135 | * Request Enum
136 | *
137 | * This enum is used to send data to the device to request a change in data rate and whether to
138 | * include satellite data.
139 | */
140 | public enum Request {
141 | ONE_HZ_INCLUDE_SATELLITES ( 1, true, "24be001105010205310132043301640d0a"),
142 | TWO_HZ_INCLUDE_SATELLITES ( 2, true, "24be001104010206310232043301630d0a"),
143 | FOUR_HZ_INCLUDE_SATELLITES( 4, true, "24be001107010203310432113301540d0a"),
144 | FIVE_HZ_INCLUDE_SATELLITES( 5, true, "24be001106010204310532043301600d0a"),
145 | TEN_HZ_INCLUDE_SATELLITES (10, true, "24be001108010202310a320433015b0d0a"),
146 |
147 | ONE_HZ_NO_SATELLITES ( 1, false, "24be00110b0102ff310132043302630d0a"),
148 | TWO_HZ_NO_SATELLITES ( 2, false, "24be0011100102fa310232043302620d0a"),
149 | FOUR_HZ_NO_SATELLITES ( 4, false, "24be0011120102f8310432043302600d0a"),
150 | FIVE_HZ_NO_SATELLITES ( 5, false, "24be0011130102f73105320433025f0d0a"),
151 | TEN_HZ_NO_SATELLITES (10, false, "24be0011160102f4310a320433025a0d0a");
152 |
153 | public final byte[] data;
154 | public final int rate;
155 | public final boolean includeSatellites;
156 |
157 | /**
158 | * Construct a Request enum
159 | *
160 | * @param rate requested data rate
161 | * @param includeSatellites if true request will include satellites
162 | * @param messageString The data to send to the device encoded as a hex string.
163 | */
164 | Request(int rate, boolean includeSatellites, String messageString) {
165 | this.rate = rate;
166 | this.includeSatellites = includeSatellites;
167 | // convert the hex string to an Array of Bytes
168 | int len = messageString.length();
169 | byte[] temp = new byte[len / 2];
170 | for (int i = 0; i < len; i += 2) {
171 | temp[i / 2] = (byte) ((Character.digit(messageString.charAt(i), 16) << 4)
172 | + Character.digit(messageString.charAt(i + 1), 16));
173 | }
174 | this.data=temp;
175 | }
176 | }
177 |
178 |
179 |
180 | }
--------------------------------------------------------------------------------
/samples/android/badelfgps/badelfgps.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | generateDebugSources
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 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/samples/ios/obj-c/EADemo/EADemo/RootViewController.m:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2016 Apple Inc. All Rights Reserved.
3 | See LICENSE.txt for this sample’s licensing information
4 |
5 | Abstract:
6 | View controller for watching the device come and go
7 | */
8 |
9 | #import "RootViewController.h"
10 | #import "EADSessionTransferViewController.h"
11 | #import "EADSessionController.h"
12 |
13 | #import
14 |
15 | @interface RootViewController ()
16 |
17 | @property (nonatomic, strong) NSMutableArray *accessoryList;
18 | @property (nonatomic, strong) EAAccessory *selectedAccessory;
19 | @property (nonatomic, strong) EADSessionController *eaSessionController;
20 | @property (nonatomic, strong) IBOutlet UIAlertController *protocolSelectionAlertController;
21 | @property (nonatomic, strong) IBOutlet UIView *noExternalAccessoriesPosterView;
22 | @property (nonatomic, strong) IBOutlet UILabel *noExternalAccessoriesLabelView;
23 | @property (nonatomic, strong) NSArray *supportedProtocolsStrings;
24 |
25 | @end
26 |
27 | @implementation RootViewController
28 |
29 | - (void)viewDidLoad {
30 | // Create the view that gets shown when no accessories are connected
31 | _noExternalAccessoriesPosterView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
32 | [_noExternalAccessoriesPosterView setBackgroundColor:[UIColor whiteColor]];
33 | _noExternalAccessoriesLabelView = [[UILabel alloc] initWithFrame:CGRectMake(60, 170, 240, 50)];
34 | [_noExternalAccessoriesLabelView setText:@"No Accessories Connected"];
35 | [_noExternalAccessoriesPosterView addSubview:_noExternalAccessoriesLabelView];
36 | [[self view] addSubview:_noExternalAccessoriesPosterView];
37 |
38 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_accessoryDidConnect:) name:EAAccessoryDidConnectNotification object:nil];
39 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_accessoryDidDisconnect:) name:EAAccessoryDidDisconnectNotification object:nil];
40 | [[EAAccessoryManager sharedAccessoryManager] registerForLocalNotifications];
41 |
42 | _eaSessionController = [EADSessionController sharedController];
43 | _accessoryList = [[NSMutableArray alloc] initWithArray:[[EAAccessoryManager sharedAccessoryManager] connectedAccessories]];
44 |
45 | if ([_accessoryList count] == 0) {
46 | [_noExternalAccessoriesPosterView setHidden:NO];
47 | } else {
48 | [_noExternalAccessoriesPosterView setHidden:YES];
49 | }
50 | // load the UISupportedExternalAccessory property to know which protocolStrings are registered in the app
51 | NSBundle *mainBundle = [NSBundle mainBundle];
52 | self.supportedProtocolsStrings = [mainBundle objectForInfoDictionaryKey:@"UISupportedExternalAccessoryProtocols"];
53 |
54 | [super viewDidLoad];
55 | }
56 |
57 | - (void)viewDidUnload {
58 | [[NSNotificationCenter defaultCenter] removeObserver:self name:EAAccessoryDidConnectNotification object:nil];
59 | [[NSNotificationCenter defaultCenter] removeObserver:self name:EAAccessoryDidDisconnectNotification object:nil];
60 |
61 | _accessoryList = nil;
62 |
63 | _selectedAccessory = nil;
64 |
65 | // _protocolSelectionAlertController = nil;
66 |
67 | [super viewDidUnload];
68 | }
69 |
70 | #pragma mark UITableViewDataSource methods
71 |
72 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
73 | return 1;
74 | }
75 |
76 |
77 | // Customize the number of rows in the table view.
78 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
79 | return [_accessoryList count];
80 | }
81 |
82 |
83 | // Customize the appearance of table view cells.
84 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
85 |
86 | static NSString *eaAccessoryCellIdentifier = @"eaAccessoryCellIdentifier";
87 | NSUInteger row = [indexPath row];
88 |
89 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:eaAccessoryCellIdentifier];
90 | if (cell == nil) {
91 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:eaAccessoryCellIdentifier];
92 | }
93 |
94 | NSString *eaAccessoryName = [[_accessoryList objectAtIndex:row] name];
95 | if (!eaAccessoryName || [eaAccessoryName isEqualToString:@""]) {
96 | eaAccessoryName = @"unknown";
97 | }
98 |
99 | [[cell textLabel] setText:eaAccessoryName];
100 |
101 | return cell;
102 | }
103 |
104 | #pragma mark UITableViewDelegate methods
105 |
106 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
107 | NSUInteger row = [indexPath row];
108 |
109 | _selectedAccessory = [_accessoryList objectAtIndex:row];
110 |
111 | _protocolSelectionAlertController = [UIAlertController alertControllerWithTitle:@"Select Protocol"
112 | message:nil
113 | preferredStyle:UIAlertControllerStyleActionSheet];
114 |
115 | NSArray *protocolStrings = [_selectedAccessory protocolStrings];
116 |
117 | for(NSString *protocolString in protocolStrings)
118 | {
119 | UIAlertAction *protocolAction = [UIAlertAction actionWithTitle:protocolString style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
120 |
121 | if (_selectedAccessory)
122 | {
123 | BOOL matchFound = FALSE;
124 | for ( NSString *item in self.supportedProtocolsStrings)
125 | {
126 | if ([item compare: protocolString] == NSOrderedSame)
127 | {
128 | matchFound = TRUE;
129 | NSLog(@"match found - protocolString %@", protocolString);
130 | }
131 | }
132 |
133 |
134 | if (matchFound == FALSE)
135 | {
136 | UIAlertController *invalidProtocolAlertController;
137 |
138 | invalidProtocolAlertController = [UIAlertController alertControllerWithTitle:@"Alert"
139 | message:@"protocolString unregistered"
140 | preferredStyle:UIAlertControllerStyleActionSheet];
141 | UIAlertAction *ok = [UIAlertAction
142 | actionWithTitle:@"OK"
143 | style: UIAlertActionStyleDefault
144 | handler:^(UIAlertAction *action)
145 | {
146 | [invalidProtocolAlertController dismissViewControllerAnimated:YES completion:nil];
147 |
148 | }];
149 |
150 | [invalidProtocolAlertController addAction:ok];
151 | // Present alert controller
152 |
153 | [self presentViewController: invalidProtocolAlertController animated:YES completion:nil];
154 | _selectedAccessory = nil;
155 |
156 |
157 | }
158 | else
159 | {
160 | [_eaSessionController setupControllerForAccessory:_selectedAccessory
161 | withProtocolString:[action title]];
162 |
163 | EADSessionTransferViewController *sessionTransferViewController =
164 | [self.storyboard instantiateViewControllerWithIdentifier:@"EADSessionTransfer"];
165 |
166 | [[self navigationController] pushViewController:sessionTransferViewController animated:YES];
167 | }
168 | }
169 |
170 | _selectedAccessory = nil;
171 | _protocolSelectionAlertController = nil;
172 | }];
173 | [_protocolSelectionAlertController addAction:protocolAction];
174 | }
175 |
176 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
177 | _selectedAccessory = nil;
178 | _protocolSelectionAlertController = nil;
179 | }];
180 | [_protocolSelectionAlertController addAction:cancelAction];
181 |
182 | [self presentViewController:_protocolSelectionAlertController animated:YES completion:nil];
183 |
184 | [[self tableView] deselectRowAtIndexPath:indexPath animated:YES];
185 | }
186 |
187 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
188 | {
189 | return 100;
190 | }
191 |
192 | #pragma mark Internal
193 |
194 | - (void)_accessoryDidConnect:(NSNotification *)notification {
195 | EAAccessory *connectedAccessory = [[notification userInfo] objectForKey:EAAccessoryKey];
196 |
197 | [_accessoryList addObject:connectedAccessory];
198 |
199 | if ([_accessoryList count] == 0) {
200 | [_noExternalAccessoriesPosterView setHidden:NO];
201 | } else {
202 | [_noExternalAccessoriesPosterView setHidden:YES];
203 | }
204 |
205 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:([_accessoryList count] - 1) inSection:0];
206 | [[self tableView] insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
207 | }
208 |
209 | - (void)_accessoryDidDisconnect:(NSNotification *)notification {
210 | EAAccessory *disconnectedAccessory = [[notification userInfo] objectForKey:EAAccessoryKey];
211 |
212 | if (_selectedAccessory && [disconnectedAccessory connectionID] == [_selectedAccessory connectionID])
213 | {
214 | // clear the protocolSelectionAlertController if the accessory is disconnected
215 | [_protocolSelectionAlertController dismissViewControllerAnimated:YES completion:^(void) {
216 | _selectedAccessory = nil;
217 | _protocolSelectionAlertController = nil;
218 | }];
219 |
220 |
221 | }
222 |
223 | int disconnectedAccessoryIndex = 0;
224 | for(EAAccessory *accessory in _accessoryList) {
225 | if ([disconnectedAccessory connectionID] == [accessory connectionID]) {
226 | break;
227 | }
228 | disconnectedAccessoryIndex++;
229 | }
230 |
231 | if (disconnectedAccessoryIndex < [_accessoryList count]) {
232 | [_accessoryList removeObjectAtIndex:disconnectedAccessoryIndex];
233 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:disconnectedAccessoryIndex inSection:0];
234 | [[self tableView] deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
235 | } else {
236 | NSLog(@"could not find disconnected accessory in accessory list");
237 | }
238 |
239 | if ([_accessoryList count] == 0) {
240 | [_noExternalAccessoriesPosterView setHidden:NO];
241 | } else {
242 | [_noExternalAccessoriesPosterView setHidden:YES];
243 | }
244 | }
245 |
246 | @end
247 |
--------------------------------------------------------------------------------
/samples/android/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | generateDebugSources
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 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/samples/android/app/src/main/java/com/bad_elf/gpssample/BadElfDeviceDataActivity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2016 Bad Elf, LLC. All Rights Reserved.
3 | * See LICENSE.txt for this sample's licensing information
4 | *
5 | */
6 |
7 | package com.bad_elf.gpssample;
8 |
9 | import android.graphics.LightingColorFilter;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.os.Bundle;
12 | import android.text.Editable;
13 | import android.text.Layout;
14 | import android.text.method.ScrollingMovementMethod;
15 | import android.util.Log;
16 | import android.view.MenuItem;
17 | import android.view.View;
18 | import android.view.ViewGroup;
19 | import android.widget.Button;
20 | import android.widget.TextView;
21 |
22 | import java.nio.charset.Charset;
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | import com.bad_elf.badelfgps.BadElfDevice;
27 | import com.bad_elf.badelfgps.BadElfRemoteController;
28 | import com.bad_elf.badelfgps.BadElfService.State;
29 | import com.bad_elf.badelfgps.BadElfGpsConnection;
30 | import com.bad_elf.badelfgps.BadElfGpsConnectionObserver;
31 |
32 | /**
33 | * This Activity lets the user connect to and disconnect from a Bad Elf Device. The data received
34 | * from the device is displayed and the user can send requests to change the data rate and
35 | * data format.
36 | *
37 | * This activity communicates with the Device using the BadElfGpsConnection class and through
38 | * callbacks by implementing the BadElfGpsConnectionObserver interface.
39 | *
40 | */
41 | public class BadElfDeviceDataActivity extends AppCompatActivity implements BadElfGpsConnectionObserver {
42 |
43 | private static final String TAG = "BadElfDeviceDataActvty";
44 |
45 | private Button connectDisconnectButton;
46 | private TextView stateView;
47 | private List