57 Commits

Author SHA1 Message Date
Alexandros Schillings
8871fc5d20 Merge pull request #25 from alt236/release/app_v1_1_1
Preparing for App relase v1.1.1
2017-02-03 12:32:30 +00:00
Alexandros Schillings
e5ed6f1dbb Preparing for App relase v1.1.1 2017-02-03 12:16:08 +00:00
Alexandros Schillings
e838cacad1 Merge pull request #24 from alt236/bugfix/dont-ask-for-location-permission-pre-API23
App no longer tries to ask for COARSE_LOCATION permission pre API 23 …
2017-02-03 12:12:48 +00:00
Alexandros Schillings
ebc44c7537 App no longer tries to ask for COARSE_LOCATION permission pre API 23 as it is not needed 2017-02-03 12:09:20 +00:00
Alexandros Schillings
f2f9ac38f4 Bumped app version, updated manifest and README 2017-01-24 16:48:28 +00:00
Alexandros Schillings
be2583ce4e Merge pull request #21 from alt236/app-material-redisign-and-optimisations
App material redisign and optimisations
2017-01-19 17:24:06 +00:00
Alexandros Schillings
0d1085730b Bumped tools to 2.2.3 2017-01-19 17:15:49 +00:00
Alexandros Schillings
47a4c124f6 Added unit tests for BluetoothLeDeviceStore.java 2017-01-19 17:11:21 +00:00
Alexandros Schillings
81d984efac The dound device list is now implemented as a recyclerview. 2017-01-17 17:31:53 +00:00
Alexandros Schillings
a7312ad51c Added circle.yml 2017-01-17 17:07:16 +00:00
Alexandros Schillings
9ba9f2728b Updated app icon (again) 2016-09-04 20:50:37 +01:00
Alexandros Schillings
3a234b8080 Fixed crash when selecting GATT service 2016-09-04 20:42:48 +01:00
Alexandros Schillings
1d3dd85eeb Updated the app icon 2016-08-31 20:35:59 +01:00
Alexandros Schillings
1639e1a22d Updated share and bluetooth icons 2016-08-31 20:21:31 +01:00
Alexandros Schillings
ef5b84387f Fixed bug where the device class name was returned instead of the major class name 2016-08-31 20:19:18 +01:00
Alexandros Schillings
6f092344f5 Fixed CSV sharing 2016-08-31 19:56:09 +01:00
Alexandros Schillings
7f15ea3d1e We now have a "connecting" state in the ControlActivity. 2016-08-31 19:09:38 +01:00
Alexandros Schillings
727f2d8953 Moved the list adapter creation out of DeviceControlActivity 2016-08-31 18:04:17 +01:00
Alexandros Schillings
b54a56b15b Updated app colours and margins between sections 2016-08-31 17:51:24 +01:00
Alexandros Schillings
e43bfc1b82 Added navigation class to abstract activity launching 2016-08-31 17:50:31 +01:00
Alexandros Schillings
e9c2f0d486 The extras in BluetoothLeService are now properly unique 2016-08-31 13:16:14 +01:00
Alexandros Schillings
65b597ab29 Now using EasyCursor off maven instead of the bundled jar 2016-08-30 18:14:26 +01:00
Alexandros Schillings
92d6ee5241 Removed merge adapter, details screen now uses a recyclerview 2016-08-30 18:05:44 +01:00
Alexandros Schillings
54d0caf6c8 Rearranged app packages and started splitting classes 2016-08-24 16:23:22 +01:00
Alexandros Schillings
ec33fd7618 Materialized the UI, added runtme permissions support, now compiling against 24 2016-08-24 14:39:26 +01:00
Alexandros Schillings
c6cece6acc Merge pull request #13 from ravidsrk/patch-1
Added code syntax highlighting to Readme
2016-02-20 20:51:00 +00:00
Ravindra Kumar
1647ca1ec2 Added code syntax highlighting to Readme 2016-02-20 21:29:31 +05:30
Alexandros Schillings
112bc00054 Merge pull request #12 from orthographic-pedant/spell_check/advertisement
Fixed typographical error, changed advertisment to advertisement in README.
2015-10-01 10:13:09 +01:00
orthographic-pedant
f483a0e24a Fixed typographical error, changed advertisment to advertisement in README. 2015-09-30 17:08:24 -04:00
Alexandros Schillings
51c9e5ca90 Merge branch 'master' of github.com:alt236/Bluetooth-LE-Library---Android
Conflicts:
	README.md
2015-07-14 17:18:04 +01:00
Alexandros Schillings
28f694f14b Merge branch 'move-to-android-studio' 2015-07-14 17:14:40 +01:00
Alexandros Schillings
6946d05e9c Ready to release v1.0.0 2015-07-14 17:11:45 +01:00
Alexandros Schillings
8c0c0b4ebe Finalising before merging 2015-07-14 15:04:45 +01:00
Alexandros Schillings
459eb1d2d4 Starting to abstract more so we can support more beacon types 2015-07-14 14:01:32 +01:00
Alexandros Schillings
cb43be74ef added BeaconDevice Interface 2015-07-13 18:08:59 +01:00
Alexandros Schillings
201e4a6129 Started making the library less bound to ibeacons 2015-07-13 17:51:57 +01:00
Alexandros Schillings
4e173659e9 We can now list supported bluetooth services 2015-07-13 17:13:06 +01:00
Alexandros Schillings
eae8e9c776 Added Bluetooth Major Class resolver 2015-07-13 16:36:17 +01:00
Alexandros Schillings
ab6997b5af We are now using AppCompat and support Material 2015-07-13 16:04:39 +01:00
Alexandros Schillings
262fa72910 Bumping versions and updating README 2015-07-13 15:06:08 +01:00
Alexandros Schillings
f68b2f5950 Fix for #9 (Some issue in GattAttributeResolver) 2015-07-13 14:53:55 +01:00
Alexandros Schillings
31f191b695 Fix for #5 (IBeaconManufacturerData.calculateUUIDString(byte[]) bug) 2015-07-03 18:16:21 +01:00
Alexandros Schillings
33f2a265f7 Added some IBeaconUtils tests 2015-07-03 18:06:10 +01:00
Alexandros Schillings
70169dc0b7 More tests and general code cleanup 2015-07-03 17:50:24 +01:00
Alexandros Schillings
4fcbc7c468 Java 7-ness 2015-07-03 16:53:20 +01:00
Alexandros Schillings
9c04515a34 Added some tests around ByteUtils 2015-07-03 15:38:57 +01:00
Alexandros Schillings
53138d5462 Full code reformat 2015-07-03 14:52:14 +01:00
Alexandros Schillings
5f55a3ea45 Fixed some static analysis issues 2015-07-03 14:43:54 +01:00
Alexandros Schillings
56e27ffab1 finalised things that could be final 2015-07-03 14:32:19 +01:00
Alexandros Schillings
67bc13a9c2 Migrated project from Eclipse to Android Studio 2015-07-03 14:22:13 +01:00
Alexandros Schillings
e838503792 Merge pull request #3 from xrmx/patch-1
Add instructions for creating local.properties
2014-08-27 17:54:59 +01:00
Riccardo Magliocchetti
bcfaa21fad Add instructions for creating local.properties 2014-08-27 11:16:16 +02:00
Alexandros Schillings
cc58a76bc6 Preparing for releasing app v0.0.3 2014-04-28 18:04:18 +01:00
Alexandros Schillings
4792282b59 Externalised strings 2014-04-28 17:54:11 +01:00
Alexandros Schillings
b0d65c08dd Added GATT Services Exporter 2014-04-28 17:39:31 +01:00
Alexandros Schillings
131ab06bfb Started rewriting the Gatt Screen UI 2014-04-28 16:42:12 +01:00
Alexandros Schillings
cf48721d77 Making the Device Details activity pretty 2014-04-25 12:55:25 +01:00
223 changed files with 7901 additions and 4610 deletions

13
.gitignore vendored
View File

@@ -1,6 +1,7 @@
/bin
/gen
local.properties
.idea/
lint.xml
/.apt_generated
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
documents/.~lock.Bluetooth_UUIDs.ods#

22
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

3
.idea/copyright/profiles_settings.xml generated Normal file
View File

@@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

19
.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/library" />
<option value="$PROJECT_DIR$/sample_app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

80
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<expanded-state>
<State>
<id />
</State>
<State>
<id>Android</id>
</State>
<State>
<id>Android &gt; Lint &gt; Correctness</id>
</State>
<State>
<id>Android &gt; Lint &gt; Performance</id>
</State>
<State>
<id>CorrectnessLintAndroid</id>
</State>
<State>
<id>General</id>
</State>
<State>
<id>LintAndroid</id>
</State>
</expanded-state>
<selected-state>
<State>
<id>Android</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

10
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/bluetooth-le-library.iml" filepath="$PROJECT_DIR$/bluetooth-le-library.iml" />
<module fileurl="file://$PROJECT_DIR$/library/library.iml" filepath="$PROJECT_DIR$/library/library.iml" />
<module fileurl="file://$PROJECT_DIR$/sample_app/sample_app.iml" filepath="$PROJECT_DIR$/sample_app/sample_app.iml" />
</modules>
</component>
</project>

12
.idea/runConfigurations.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="Bluetooth-LE-Library---Android" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

235
LICENSE-2.0.html Normal file
View File

@@ -0,0 +1,235 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="LICENSE-2.0_fichiers/style.css" type="text/css">
<meta name="author" content="The Apache Software Foundation">
<meta name="email" content="apache.AT.apache.DOT.org">
<title>Apache License, Version 2.0 - The Apache Software Foundation</title>
</head>
<body>
<p align="center">
Apache License<br>
Version 2.0, January 2004<br>
<a href="http://www.apache.org/licenses/">http://www.apache.org/licenses/</a>
</p>
<p>
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
</p>
<p><b><a name="definitions">1. Definitions</a></b>.</p>
<p>
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
</p>
<p>
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
</p>
<p>
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
</p>
<p>
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
</p>
<p>
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
</p>
<p>
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
</p>
<p>
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
</p>
<p>
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
</p>
<p>
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
</p>
<p>
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
</p>
<p><b><a name="copyright">2. Grant of Copyright License</a></b>.
Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
</p>
<p><b><a name="patent">3. Grant of Patent License</a></b>.
Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
</p>
<p><b><a name="redistribution">4. Redistribution</a></b>.
You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
</p>
<ol type="a">
<li>You must give any other recipients of the Work or
Derivative Works a copy of this License; and
<br> <br></li>
<li>You must cause any modified files to carry prominent notices
stating that You changed the files; and
<br> <br></li>
<li>You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
<br> <br></li>
<li>If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
</li>
</ol>
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
<p><b><a name="contributions">5. Submission of Contributions</a></b>.
Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
</p>
<p><b><a name="trademarks">6. Trademarks</a></b>.
This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
</p>
<p><b><a name="no-warranty">7. Disclaimer of Warranty</a></b>.
Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
</p>
<p><b><a name="no-liability">8. Limitation of Liability</a></b>.
In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
</p>
<p><b><a name="additional">9. Accepting Warranty or Additional Liability</a></b>.
While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
</p>
<p>
END OF TERMS AND CONDITIONS
</p>
</body>
</html>

103
README.md
View File

@@ -9,49 +9,53 @@ It also offers:
* For iBeacons: A decently inaccurate (due to real world issues) distance approximation.
* All the new object types are Parcelable.
This will only work on Android 4.3 (API Level 18).
This will only work on devices with Android 4.3 (API Level 18) and above.
Sample app available on the [Play Store](https://play.google.com/store/apps/details?id=uk.co.alt236.btlescan)
<a href='https://play.google.com/store/apps/details?id=uk.co.alt236.btlescan&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'>
<img alt='Get it on Google Play' height=100 src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png'/>
</a>
## Including the Library in Your Project
There are two ways to use this library:
* Download a copy of the Bluetooth LE Library project and reference it in your project.
* Create a Jar file (see Jarification below) and add it into your project.
This project is available as an artifact for use with Gradle. To use that, add the following blocks to your build.gradle file:
```groovy
repositories {
maven {
url "https://dl.bintray.com/alt236/maven"
}
}
### Jarification
Type `ant jar` at the root of the Library Project to produce a Jar file.
The library jar along with it's javadoc jar will be found in the `dist` directory inside the library project.
You will need to provide your own `local.properties` inside the library project.
dependencies {
compile 'uk.co.alt236:bluetooth-le-library-android:1.0.0'
}
```
If you *really* need a Jar file, fork the project and execute `./gradlew clean build generateRelease` at the root of the project.
This will create a zip file under `<PROJECT_ROOT>/library/build/` the Jar can be found inside.
## Using the Library
In the `onLeScan()` method of your `BluetoothAdapter.LeScanCallback()` create a new BluetoothLeDevice with the given information.
For example:
<pre>
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
```java
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final BluetoothLeDevice deviceLe = new BluetoothLeDevice(device, rssi, scanRecord, System.currentTimeMillis());
runOnUiThread(new Runnable() {
@Override
public void run() {
mDeviceStore.addDevice(deviceLe);
mLeDeviceListAdapter.replaceData(mDeviceStore.getDeviceList());
}
});
}
};
</pre>
```
### Device Properties
@@ -71,7 +75,7 @@ Once you have created a device, you can access the following methods:
**Note:** The Running Average RSSI is not updated automatically (i.e. the library does not monitor on its own in the background). To add another measurement, you need to call `updateRssiReading(long timestamp, int rssiReading)`.
### Accessing the Advertisment (Ad) Records
### Accessing the Advertisement (Ad) Records
Once you've created a BluetoothLe device, you can access the AdRecord store via the `leDevice.getAdRecordStore()`. Once you have the AdRecordStore you can use the following methods:
@@ -83,7 +87,17 @@ Once you've created a BluetoothLe device, you can access the AdRecord store via
They are also declared as constants in `AdRecord.java`.
### Fun with iBeacons
You can check if a device is an iBeacon by using `IBeaconUtils.isThisAnIBeacon(BluetootLeDevice device)`. Once you have confirmed that it is, you can create a new IBeaconDevice via the IBeaconDevice constructor.
You can check if a device is an iBeacon by using `BeaconUtils.getBeaconType(BluetootLeDevice device)`. Once you have confirmed that it is, you can create a new IBeaconDevice via the IBeaconDevice constructor.
Example Flow:
```java
final BluetoothLeDevice device = ... // A generic BLE device
if (BeaconUtils.getBeaconType(device) == BeaconType.IBEACON) {
final IBeaconDevice iBeacon = new IBeaconDevice(device);
// DO STUFF
}
```
An IBeaconDevice extends BluetoothLeDevice, so you still have access to the same methods as before. In addition you can do the following:
@@ -103,21 +117,37 @@ You can also lookup values and convert them to human friendly strings:
* `CompanyIdentifierResolver.getCompanyName(int companyId, String fallback)`: Will try to resolve a Company identifier to the company name
* `GattAttributeResolver.getAttributeName(String uuid, String fallback)`: Will try to convert a UUID to its name.
**Note:** The data can be found as ODS (Open Office Spreadsheets) in the documents folder.
**Note:** The data can be found as ODS (Open Office Spreadsheets) in the documents folder.
## Library Changelog
* v0.0.1
* v0.0.1
* First public release
* v0.0.2:
* v0.0.2:
* Attempting to create an iBeaconDevice from a device which is not an iBeacon will now throw an IllegalArgumentException exception.
* Fixed a ConcurrentModificationException on getRunningAverageRssi()
* Added some Estimote UUIDs
* v1.0.0:
* Migrated project to Android Studio/ gradle
* Note that the API has slightly changed in this version.
* We now use the more generic `BeaconUtils.getBeaconType()` method instead of `IBeaconUtils.isThisAnIBeacon()`
* Fix for [issue 5](https://github.com/alt236/Bluetooth-LE-Library---Android/issues/5)
* Fix for [issue 9](https://github.com/alt236/Bluetooth-LE-Library---Android/issues/9)
## Sample Application Changelog
* v0.0.1
* First public release
* v0.0.2:
* Can now export scanned devices as a CSV file.
* v0.0.1
* First public release
* v0.0.2:
* Can now export scanned devices as a CSV file.
* v0.0.3:
* UI Refresh.
* v1.0.0:
* Migrated project to Android Studio/ gradle
* Using version v1.0.0 of the library project
* v1.1.0:
* App refactor and materialisation.
* Added runtime permissions.
* v1.1.1:
* Fix for [issue 23](https://github.com/alt236/Bluetooth-LE-Library---Android/issues/23)
## Permission Explanation
You will need the following permissions to access the Bluetooth Hardware
@@ -125,17 +155,15 @@ You will need the following permissions to access the Bluetooth Hardware
* `android.permission.BLUETOOTH`
* `android.permission.BLUETOOTH_ADMIN`
In addition one of the following is needed from API 23 and above to scan for BT LE devices:
* `android.permission.ACCESS_COARSE_LOCATION`
* `android.permission.ACCESS_FINE_LOCATION `
## TODO
* Tidy up Javadoc. There is quite a lot of it that is template
* Add parsers for common Ad Records.
## Sample App Screenshots
![screenshot1](https://github.com/alt236/Bluetooth-LE-Library---Android/raw/master/screenshots/screenshot_1.png)
![screenshot2](https://github.com/alt236/Bluetooth-LE-Library---Android/raw/master/screenshots/screenshot_2.png)
![screenshot3](https://github.com/alt236/Bluetooth-LE-Library---Android/raw/master/screenshots/screenshot_3.png)
## Links
* Github: [https://github.com/alt236/Bluetooth-LE-Library---Android]()
@@ -145,9 +173,10 @@ Author: [Alexandros Schillings](https://github.com/alt236).
* The Accuracy calculation algorithm was taken from: http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing
* The AdRecord parser was taken from: https://github.com/devunwired/accessory-samples
* The sample application has been adapted from Android's Bluetooth LE example
* Google Play and the Google Play logo are trademarks of Google Inc.
All logos are the property of their respective owners.
The code in this project is licensed under the Apache Software License 2.0.
Copyright (c) 2014 Alexandros Schillings.
Copyright (c) 2014-2017 Alexandros Schillings.

19
bluetooth-le-library.iml Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="bluetooth-le-library" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

21
build.gradle Normal file
View File

@@ -0,0 +1,21 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
ext.compileSdkVersion = 24
ext.buildToolsVersion = "24.0.1"
ext.minSdkVersion = 18
ext.targetSdkVersion = 24
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
}
}
allprojects {
repositories {
jcenter()
}
}

7
circle.yml Normal file
View File

@@ -0,0 +1,7 @@
test:
override:
- (echo "Running JUnit tests!")
- ./gradlew test -PdisablePreDex
post:
- mkdir -p $CIRCLE_TEST_REPORTS/junit/
- find . -type f -regex ".*/build/test-results/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;

Binary file not shown.

BIN
dist/BluetoothLeLibrary-0.0.1.jar vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Wed Aug 24 14:15:35 BST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

164
gradlew vendored Executable file
View File

@@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

8
library/.gitignore vendored
View File

@@ -1,7 +1 @@
/bin
/gen
local.properties
.idea/
lint.xml
/.apt_generated
/dist
/build

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Bluetooth LE Library</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -1,4 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.source=1.6

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="uk.co.alt236.bluetoothlelib"
android:versionCode="2"
android:versionName="0.0.2" >
<uses-sdk
android:minSdkVersion="18"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
</application>
</manifest>

53
library/build.gradle Normal file
View File

@@ -0,0 +1,53 @@
apply plugin: 'com.android.library'
final int versionMajor = 1
final int versionMinor = 0
final int versionPatch = 0
final int androidVersionCode = 5
final int targetSdk = rootProject.targetSdkVersion;
final int minSdkRed = rootProject.minSdkVersion;
final String semanticVersion = "${versionMajor}.${versionMinor}.${versionPatch}"
dependencies {
testCompile 'junit:junit:4.12'
testCompile "org.mockito:mockito-core:1.9.5"
compile fileTree(include: ['*.jar'], dir: 'libs')
}
ext {
PUBLISH_GROUP_ID = 'uk.co.alt236'
PUBLISH_ARTIFACT_ID = 'bluetooth-le-library-android'
PUBLISH_VERSION = "${semanticVersion}"
}
android {
compileSdkVersion rootProject.compileSdkVersion
buildToolsVersion rootProject.buildToolsVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
defaultConfig {
minSdkVersion minSdkRed
targetSdkVersion targetSdk
versionCode androidVersionCode
versionName semanticVersion
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
}
}
// Script from https://github.com/blundell/release-android-library
// execute: ./gradlew clean build generateRelease
apply from: 'https://raw.githubusercontent.com/ArthurHub/release-android-library/master/android-release-jar.gradle'

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<project name="BluetoothLeLibrary" default="default">
<loadproperties srcFile="local.properties" />
<property file="ant.properties" />
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project'" unless="sdk.dir" />
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
<!-- Read the Android Manifest -->
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/ant-tasks.jar" />
</path>
<taskdef name="xpath" classname="com.android.ant.XPathTask" classpathref="android.antlibs" />
<xpath input="./AndroidManifest.xml" expression="/manifest/@android:versionName" output="manifest.versionName" />
<!-- Setup the build properties -->
<property name="versionedName" value="${ant.project.name}-${manifest.versionName}" />
<property name="distLocation" location="dist" />
<echo message="Running task(s) for ${versionedName}" />
<target name="default">
<antcall target="jar"/>
<antcall target="doc"/>
</target>
<target name="jar" depends="debug" description="build the library as a jar">
<jar destfile="${distLocation}/${versionedName}.jar" basedir="bin/classes" />
</target>
<target name="doc" description="generate documentation">
<property name="temp" location="temp" />
<javadoc sourcepath="${source.dir}" destdir="${temp}" />
<jar destfile="${distLocation}/${versionedName}-javadoc.jar" basedir="temp" keepcompression="true" />
<delete dir="${temp}" />
</target>
</project>

110
library/library.iml Normal file
View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":library" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="bluetooth-le-library" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":library" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_unit_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="LIBRARY_PROJECT" value="true" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" scope="TEST" name="objenesis-1.0" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="hamcrest-core-1.3" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="junit-4.12" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="mockito-core-1.9.5" level="project" />
</component>
</module>

Binary file not shown.

View File

@@ -1,11 +1,8 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
# in /home/alex/Dev/android-sdk-linux/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

View File

@@ -1,15 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-19
android.library=true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -1,11 +0,0 @@
<resources>
<!--
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
<!-- API 11 theme customizations can go here. -->
</style>
</resources>

View File

@@ -1,12 +0,0 @@
<resources>
<!--
Base application theme for API 14+. This theme completely replaces
AppBaseTheme from BOTH res/values/styles.xml and
res/values-v11/styles.xml on API 14+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!-- API 14 theme customizations can go here. -->
</style>
</resources>

View File

@@ -1,5 +0,0 @@
<resources>
<string name="app_name">Bluetooth LE Library</string>
</resources>

View File

@@ -1,20 +0,0 @@
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
package="uk.co.alt236.bluetoothlelib">
</manifest>

View File

@@ -0,0 +1,422 @@
package uk.co.alt236.bluetoothlelib.device;
import android.bluetooth.BluetoothDevice;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecordStore;
import uk.co.alt236.bluetoothlelib.resolvers.BluetoothClassResolver;
import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
import uk.co.alt236.bluetoothlelib.util.LimitedLinkHashMap;
// TODO: Auto-generated Javadoc
/**
* This is a wrapper around the default BluetoothDevice object
* As BluetoothDevice is final it cannot be extended, so to get it you
* need to call {@link #getDevice()} method.
*
* @author Alexandros Schillings
*/
public class BluetoothLeDevice implements Parcelable {
/**
* The Constant CREATOR.
*/
public static final Parcelable.Creator<BluetoothLeDevice> CREATOR = new Parcelable.Creator<BluetoothLeDevice>() {
public BluetoothLeDevice createFromParcel(final Parcel in) {
return new BluetoothLeDevice(in);
}
public BluetoothLeDevice[] newArray(final int size) {
return new BluetoothLeDevice[size];
}
};
protected static final int MAX_RSSI_LOG_SIZE = 10;
private static final String PARCEL_EXTRA_BLUETOOTH_DEVICE = "bluetooth_device";
private static final String PARCEL_EXTRA_CURRENT_RSSI = "current_rssi";
private static final String PARCEL_EXTRA_CURRENT_TIMESTAMP = "current_timestamp";
private static final String PARCEL_EXTRA_DEVICE_RSSI_LOG = "device_rssi_log";
private static final String PARCEL_EXTRA_DEVICE_SCANRECORD = "device_scanrecord";
private static final String PARCEL_EXTRA_DEVICE_SCANRECORD_STORE = "device_scanrecord_store";
private static final String PARCEL_EXTRA_FIRST_RSSI = "device_first_rssi";
private static final String PARCEL_EXTRA_FIRST_TIMESTAMP = "first_timestamp";
private static final long LOG_INVALIDATION_THRESHOLD = 10 * 1000;
private final AdRecordStore mRecordStore;
private final BluetoothDevice mDevice;
private final Map<Long, Integer> mRssiLog;
private final byte[] mScanRecord;
private final int mFirstRssi;
private final long mFirstTimestamp;
private int mCurrentRssi;
private long mCurrentTimestamp;
private transient Set<BluetoothService> mServiceSet;
/**
* Instantiates a new Bluetooth LE device.
*
* @param device a standard android Bluetooth device
* @param rssi the RSSI value of the Bluetooth device
* @param scanRecord the scan record of the device
* @param timestamp the timestamp of the RSSI reading
*/
public BluetoothLeDevice(final BluetoothDevice device, final int rssi, final byte[] scanRecord, final long timestamp) {
mDevice = device;
mFirstRssi = rssi;
mFirstTimestamp = timestamp;
mRecordStore = new AdRecordStore(AdRecordUtils.parseScanRecordAsSparseArray(scanRecord));
mScanRecord = scanRecord;
mRssiLog = new LimitedLinkHashMap<>(MAX_RSSI_LOG_SIZE);
updateRssiReading(timestamp, rssi);
}
/**
* Instantiates a new Bluetooth LE device.
*
* @param device the device
*/
public BluetoothLeDevice(final BluetoothLeDevice device) {
mCurrentRssi = device.getRssi();
mCurrentTimestamp = device.getTimestamp();
mDevice = device.getDevice();
mFirstRssi = device.getFirstRssi();
mFirstTimestamp = device.getFirstTimestamp();
mRecordStore = new AdRecordStore(
AdRecordUtils.parseScanRecordAsSparseArray(device.getScanRecord()));
mRssiLog = device.getRssiLog();
mScanRecord = device.getScanRecord();
}
/**
* Instantiates a new bluetooth le device.
*
* @param in the in
*/
@SuppressWarnings("unchecked")
protected BluetoothLeDevice(final Parcel in) {
final Bundle b = in.readBundle(getClass().getClassLoader());
mCurrentRssi = b.getInt(PARCEL_EXTRA_CURRENT_RSSI, 0);
mCurrentTimestamp = b.getLong(PARCEL_EXTRA_CURRENT_TIMESTAMP, 0);
mDevice = b.getParcelable(PARCEL_EXTRA_BLUETOOTH_DEVICE);
mFirstRssi = b.getInt(PARCEL_EXTRA_FIRST_RSSI, 0);
mFirstTimestamp = b.getLong(PARCEL_EXTRA_FIRST_TIMESTAMP, 0);
mRecordStore = b.getParcelable(PARCEL_EXTRA_DEVICE_SCANRECORD_STORE);
mRssiLog = (Map<Long, Integer>) b.getSerializable(PARCEL_EXTRA_DEVICE_RSSI_LOG);
mScanRecord = b.getByteArray(PARCEL_EXTRA_DEVICE_SCANRECORD);
}
/**
* Adds the to rssi log.
*
* @param timestamp the timestamp
* @param rssiReading the rssi reading
*/
private void addToRssiLog(final long timestamp, final int rssiReading) {
synchronized (mRssiLog) {
if (timestamp - mCurrentTimestamp > LOG_INVALIDATION_THRESHOLD) {
mRssiLog.clear();
}
mCurrentRssi = rssiReading;
mCurrentTimestamp = timestamp;
mRssiLog.put(timestamp, rssiReading);
}
}
/* (non-Javadoc)
* @see android.os.Parcelable#describeContents()
*/
@Override
public int describeContents() {
return 0;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final BluetoothLeDevice other = (BluetoothLeDevice) obj;
if (mCurrentRssi != other.mCurrentRssi)
return false;
if (mCurrentTimestamp != other.mCurrentTimestamp)
return false;
if (mDevice == null) {
if (other.mDevice != null)
return false;
} else if (!mDevice.equals(other.mDevice))
return false;
if (mFirstRssi != other.mFirstRssi)
return false;
if (mFirstTimestamp != other.mFirstTimestamp)
return false;
if (mRecordStore == null) {
if (other.mRecordStore != null)
return false;
} else if (!mRecordStore.equals(other.mRecordStore))
return false;
if (mRssiLog == null) {
if (other.mRssiLog != null)
return false;
} else if (!mRssiLog.equals(other.mRssiLog))
return false;
if (!Arrays.equals(mScanRecord, other.mScanRecord))
return false;
return true;
}
/**
* Gets the ad record store.
*
* @return the ad record store
*/
public AdRecordStore getAdRecordStore() {
return mRecordStore;
}
/**
* Gets the address.
*
* @return the address
*/
public String getAddress() {
return mDevice.getAddress();
}
/**
* Gets the bluetooth device bond state.
*
* @return the bluetooth device bond state
*/
public String getBluetoothDeviceBondState() {
return resolveBondingState(mDevice.getBondState());
}
/**
* Gets the bluetooth device class name.
*
* @return the bluetooth device class name
*/
public String getBluetoothDeviceClassName() {
return BluetoothClassResolver.resolveDeviceClass(mDevice.getBluetoothClass().getDeviceClass());
}
public Set<BluetoothService> getBluetoothDeviceKnownSupportedServices() {
if (mServiceSet == null) {
synchronized (this) {
if (mServiceSet == null) {
final Set<BluetoothService> serviceSet = new HashSet<>();
for (final BluetoothService service : BluetoothService.values()) {
if (mDevice.getBluetoothClass().hasService(service.getAndroidConstant())) {
serviceSet.add(service);
}
}
mServiceSet = Collections.unmodifiableSet(serviceSet);
}
}
}
return mServiceSet;
}
/**
* Gets the bluetooth device major class name.
*
* @return the bluetooth device major class name
*/
public String getBluetoothDeviceMajorClassName() {
return BluetoothClassResolver.resolveMajorDeviceClass(mDevice.getBluetoothClass().getMajorDeviceClass());
}
/**
* Gets the device.
*
* @return the device
*/
public BluetoothDevice getDevice() {
return mDevice;
}
/**
* Gets the first rssi.
*
* @return the first rssi
*/
public int getFirstRssi() {
return mFirstRssi;
}
/**
* Gets the first timestamp.
*
* @return the first timestamp
*/
public long getFirstTimestamp() {
return mFirstTimestamp;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName() {
return mDevice.getName();
}
/**
* Gets the rssi.
*
* @return the rssi
*/
public int getRssi() {
return mCurrentRssi;
}
/**
* Gets the rssi log.
*
* @return the rssi log
*/
protected Map<Long, Integer> getRssiLog() {
synchronized (mRssiLog) {
return mRssiLog;
}
}
/**
* Gets the running average rssi.
*
* @return the running average rssi
*/
public double getRunningAverageRssi() {
int sum = 0;
int count = 0;
synchronized (mRssiLog) {
for (final Long aLong : mRssiLog.keySet()) {
count++;
sum += mRssiLog.get(aLong);
}
}
if (count > 0) {
return sum / count;
} else {
return 0;
}
}
/**
* Gets the scan record.
*
* @return the scan record
*/
public byte[] getScanRecord() {
return mScanRecord;
}
/**
* Gets the timestamp.
*
* @return the timestamp
*/
public long getTimestamp() {
return mCurrentTimestamp;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + mCurrentRssi;
result = prime * result + (int) (mCurrentTimestamp ^ (mCurrentTimestamp >>> 32));
result = prime * result + ((mDevice == null) ? 0 : mDevice.hashCode());
result = prime * result + mFirstRssi;
result = prime * result + (int) (mFirstTimestamp ^ (mFirstTimestamp >>> 32));
result = prime * result + ((mRecordStore == null) ? 0 : mRecordStore.hashCode());
result = prime * result + ((mRssiLog == null) ? 0 : mRssiLog.hashCode());
result = prime * result + Arrays.hashCode(mScanRecord);
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "BluetoothLeDevice [mDevice=" + mDevice + ", mRssi=" + mFirstRssi + ", mScanRecord=" + ByteUtils.byteArrayToHexString(mScanRecord) + ", mRecordStore=" + mRecordStore + ", getBluetoothDeviceBondState()=" + getBluetoothDeviceBondState() + ", getBluetoothDeviceClassName()=" + getBluetoothDeviceClassName() + "]";
}
/**
* Update rssi reading.
*
* @param timestamp the timestamp
* @param rssiReading the rssi reading
*/
public void updateRssiReading(final long timestamp, final int rssiReading) {
addToRssiLog(timestamp, rssiReading);
}
/* (non-Javadoc)
* @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
*/
@Override
public void writeToParcel(final Parcel parcel, final int arg1) {
final Bundle b = new Bundle(getClass().getClassLoader());
b.putByteArray(PARCEL_EXTRA_DEVICE_SCANRECORD, mScanRecord);
b.putInt(PARCEL_EXTRA_FIRST_RSSI, mFirstRssi);
b.putInt(PARCEL_EXTRA_CURRENT_RSSI, mCurrentRssi);
b.putLong(PARCEL_EXTRA_FIRST_TIMESTAMP, mFirstTimestamp);
b.putLong(PARCEL_EXTRA_CURRENT_TIMESTAMP, mCurrentTimestamp);
b.putParcelable(PARCEL_EXTRA_BLUETOOTH_DEVICE, mDevice);
b.putParcelable(PARCEL_EXTRA_DEVICE_SCANRECORD_STORE, mRecordStore);
b.putSerializable(PARCEL_EXTRA_DEVICE_RSSI_LOG, (Serializable) mRssiLog);
parcel.writeBundle(b);
}
/**
* Resolve bonding state.
*
* @param bondState the bond state
* @return the string
*/
private static String resolveBondingState(final int bondState) {
switch (bondState) {
case BluetoothDevice.BOND_BONDED:
return "Paired";
case BluetoothDevice.BOND_BONDING:
return "Pairing";
case BluetoothDevice.BOND_NONE:
return "Unbonded";
default:
return "Unknown";
}
}
}

View File

@@ -0,0 +1,28 @@
package uk.co.alt236.bluetoothlelib.device;
import android.bluetooth.BluetoothClass;
/**
*
*/
public enum BluetoothService {
AUDIO(BluetoothClass.Service.AUDIO),
CAPTURE(BluetoothClass.Service.CAPTURE),
INFORMATION(BluetoothClass.Service.INFORMATION),
LIMITED_DISCOVERABILITY(BluetoothClass.Service.LIMITED_DISCOVERABILITY),
NETWORKING(BluetoothClass.Service.NETWORKING),
OBJECT_TRANSFER(BluetoothClass.Service.OBJECT_TRANSFER),
POSITIONING(BluetoothClass.Service.POSITIONING),
RENDER(BluetoothClass.Service.RENDER),
TELEPHONY(BluetoothClass.Service.TELEPHONY);
private final int mAndroidConstant;
BluetoothService(final int androidCode){
mAndroidConstant = androidCode;
}
public int getAndroidConstant(){
return mAndroidConstant;
}
}

View File

@@ -0,0 +1,227 @@
package uk.co.alt236.bluetoothlelib.device.adrecord;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Arrays;
/**
* Created by Dave Smith
* Double Encore, Inc.
* <p>
* Expanded by Alexandros Schillings
*/
public final class AdRecord implements Parcelable {
// 02 # Number of bytes that follow in first AD structure
// 01 # Flags AD type
// 1A # Flags value 0x1A = 000011010
// bit 0 (OFF) LE Limited Discoverable Mode
// bit 1 (ON) LE General Discoverable Mode
// bit 2 (OFF) BR/EDR Not Supported
// bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
// bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
// 1A # Number of bytes that follow in second (and last) AD structure
// FF # Manufacturer specific data AD type
// 4C 00 # Company identifier code (0x004C == Apple)
// 02 # Byte 0 of iBeacon advertisement indicator
// 15 # Byte 1 of iBeacon advertisement indicator
// e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon proximity uuid
// 00 00 # major
// 00 00 # minor
// c5 # The 2's complement of the calibrated Tx Power
/**
* General FLAGS
* <p>
* Description: Flags
* <p>
* Information:
* Bit 0: LE Limited Discoverable Mode
* Bit 1: LE General Discoverable Mode
* Bit 2: BR/EDR Not Supported (i.e. bit 37 of LMP Extended Feature bits Page 0)
* Bit 3: Simultaneous LE and BR/EDR to Same Device Capable (Controller) (i.e. bit 49 of LMP Extended Feature bits Page 0)
* Bit 4: Simultaneous LE and BR/EDR to Same Device Capable (Host) (i.e. bit 66 of LMP Extended Feature bits Page 1)
* Bits 5-7 Reserved
*/
public static final int TYPE_FLAGS = 0x01;
// SERVICE
public static final int TYPE_UUID16_INC = 0x02;
public static final int TYPE_UUID16 = 0x03;
public static final int TYPE_UUID32_INC = 0x04;
public static final int TYPE_UUID32 = 0x05;
public static final int TYPE_UUID128_INC = 0x06;
public static final int TYPE_UUID128 = 0x07;
// Local name
public static final int TYPE_LOCAL_NAME_SHORT = 0x08;
public static final int TYPE_LOCAL_NAME_COMPLETE = 0x09;
// TX Power Level
public static final int TYPE_TX_POWER_LEVEL = 0x0A;
// SIMPLE PAIRING OPTIONAL OOB TAGS
public static final int TYPE_DEVICE_CLASS = 0x0D;
public static final int TYPE_SIMPLE_PAIRING_HASH_C = 0x0E;
public static final int TYPE_SIMPLE_PAIRING_RANDOMIZER_R = 0x0F;
// SECURITY MANAGER TK VALUE
public static final int TYPE_TK_VALUE = 0x10;
/* SECURITY MANAGER OOB FLAGS
*
* Description: Flag (1 octet)
*
* Information:
* Bit 0: OOB Flags Field: (0 = OOB data not present, 1 = OOB data present)
* Bit 1: LE supported (Host) (i.e. bit 65 of LMP Extended Feature bits Page 1
* Bit 2: Simultaneous LE and BR/EDR to Same Device Capable (Host) (i.e. bit 66 of LMP Extended Feature bits Page 1)
* Bit 3: Address type (0 = Public Address, 1 = Random Address)
* Bits 4-7 Reserved
*/
public static final int TYPE_SECURITY_MANAGER_OOB_FLAGS = 0x11;
/* SLAVE CONNECTION INTERVAL RANGE
*
* Description: Slave Connection Interval Range
*
* Information:
* The first 2 octets defines the minimum value for the connection interval in the following manner:
* connInterval min = Conn_Interval_Min * 1.25 ms
* Conn_Interval_Min range: 0x0006 to 0x0C80
* Value of 0xFFFF indicates no specific minimum.
* Values outside the range are reserved. (excluding 0xFFFF)
*
* The second 2 octets defines the maximum value for the connection interval in the following manner:
* connInterval max = Conn_Interval_Max * 1.25 ms
* Conn_Interval_Max range: 0x0006 to 0x0C80
* Conn_Interval_Max shall be equal to or greater
* than the Conn_Interval_Min.
* Value of 0xFFFF indicates no specific maximum.
* Values outside the range are reserved (excluding 0xFFFF)
*/
public static final int TYPE_CONNECTION_INTERVAL_RANGE = 0x12;
// SERVICE SOLICITATION
public static final int TYPE_SERVICE_UUIDS_LIST_16BIT = 0x14;
public static final int TYPE_SERVICE_UUIDS_LIST_128BIT = 0x15;
/* SERVICE DATA
*
* Description: Service Data (2 or more octets)
* Information: The first 2 octets contain the 16 bit Service UUID followed by additional service data
*/
public static final int TYPE_SERVICE_DATA = 0x16;
/* MANUFACTURER SPECIFIC DATA
*
* Description: Manufacturer Specific Data (2 or more octets)
* Information: The first 2 octets contain the Company Identifier Code followed by additional manufacturer specific data
*/
public static final int TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
public static final Parcelable.Creator<AdRecord> CREATOR = new Parcelable.Creator<AdRecord>() {
public AdRecord createFromParcel(final Parcel in) {
return new AdRecord(in);
}
public AdRecord[] newArray(final int size) {
return new AdRecord[size];
}
};
private static final String PARCEL_RECORD_DATA = "record_data";
private static final String PARCEL_RECORD_TYPE = "record_type";
private static final String PARCEL_RECORD_LENGTH = "record_length";
/* Model Object Definition */
private final int mLength;
private final int mType;
private final byte[] mData;
public AdRecord(final int length, final int type, final byte[] data) {
mLength = length;
mType = type;
mData = data;
}
public AdRecord(final Parcel in) {
final Bundle b = in.readBundle(getClass().getClassLoader());
mLength = b.getInt(PARCEL_RECORD_LENGTH);
mType = b.getInt(PARCEL_RECORD_TYPE);
mData = b.getByteArray(PARCEL_RECORD_DATA);
}
@Override
public int describeContents() {
return 0;
}
public byte[] getData() {
return mData;
}
public String getHumanReadableType() {
return getHumanReadableAdType(mType);
}
public int getLength() {
return mLength;
}
public int getType() {
return mType;
}
@Override
public String toString() {
return "AdRecord [mLength=" + mLength + ", mType=" + mType + ", mData=" + Arrays.toString(mData) + ", getHumanReadableType()=" + getHumanReadableType() + "]";
}
@Override
public void writeToParcel(final Parcel parcel, final int arg1) {
final Bundle b = new Bundle(getClass().getClassLoader());
b.putInt(PARCEL_RECORD_LENGTH, mLength);
b.putInt(PARCEL_RECORD_TYPE, mType);
b.putByteArray(PARCEL_RECORD_DATA, mData);
parcel.writeBundle(b);
}
private static String getHumanReadableAdType(final int type) {
switch (type) {
case TYPE_CONNECTION_INTERVAL_RANGE:
return "Slave Connection Interval Range";
case TYPE_DEVICE_CLASS:
return "Class of device";
case TYPE_FLAGS:
return "Flags";
case TYPE_MANUFACTURER_SPECIFIC_DATA:
return "Manufacturer Specific Data";
case TYPE_LOCAL_NAME_COMPLETE:
return "Name (Complete)";
case TYPE_LOCAL_NAME_SHORT:
return "Name (Short)";
case TYPE_SECURITY_MANAGER_OOB_FLAGS:
return "Security Manager OOB Flags";
case TYPE_SERVICE_UUIDS_LIST_128BIT:
return "Service UUIDs (128bit)";
case TYPE_SERVICE_UUIDS_LIST_16BIT:
return "Service UUIDs (16bit)";
case TYPE_SERVICE_DATA:
return "Service Data";
case TYPE_SIMPLE_PAIRING_HASH_C:
return "Simple Pairing Hash C";
case TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
return "Simple Pairing Randomizer R";
case TYPE_TK_VALUE:
return "TK Value";
case TYPE_TX_POWER_LEVEL:
return "Transmission Power Level";
case TYPE_UUID128:
return "Complete list of 128-bit UUIDs available";
case TYPE_UUID128_INC:
return "More 128-bit UUIDs available";
case TYPE_UUID16:
return "Complete list of 16-bit UUIDs available";
case TYPE_UUID16_INC:
return "More 16-bit UUIDs available";
case TYPE_UUID32:
return "Complete list of 32-bit UUIDs available";
case TYPE_UUID32_INC:
return "More 32-bit UUIDs available";
default:
return "Unknown AdRecord Structure: " + type;
}
}
}

View File

@@ -0,0 +1,158 @@
package uk.co.alt236.bluetoothlelib.device.adrecord;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
/**
* The Class AdRecordStore.
*/
public class AdRecordStore implements Parcelable {
public static final Parcelable.Creator<AdRecordStore> CREATOR = new Parcelable.Creator<AdRecordStore>() {
public AdRecordStore createFromParcel(final Parcel in) {
return new AdRecordStore(in);
}
public AdRecordStore[] newArray(final int size) {
return new AdRecordStore[size];
}
};
private final SparseArray<AdRecord> mAdRecords;
private final String mLocalNameComplete;
private final String mLocalNameShort;
public AdRecordStore(final Parcel in) {
final Bundle b = in.readBundle(getClass().getClassLoader());
mAdRecords = b.getSparseParcelableArray("records_array");
mLocalNameComplete = b.getString("local_name_complete");
mLocalNameShort = b.getString("local_name_short");
}
/**
* Instantiates a new Bluetooth LE device Ad Record Store.
*
* @param adRecords the ad records
*/
public AdRecordStore(final SparseArray<AdRecord> adRecords) {
mAdRecords = adRecords;
mLocalNameComplete = AdRecordUtils.getRecordDataAsString(
mAdRecords.get(AdRecord.TYPE_LOCAL_NAME_COMPLETE));
mLocalNameShort = AdRecordUtils.getRecordDataAsString(
mAdRecords.get(AdRecord.TYPE_LOCAL_NAME_SHORT));
}
/* (non-Javadoc)
* @see android.os.Parcelable#describeContents()
*/
@Override
public int describeContents() {
return 0;
}
/**
* Gets the short local device name.
*
* @return the local name complete
*/
public String getLocalNameComplete() {
return mLocalNameComplete;
}
/**
* Gets the complete local device name.
*
* @return the local name short
*/
public String getLocalNameShort() {
return mLocalNameShort;
}
/**
* retrieves an individual record.
*
* @param record the record
* @return the record
*/
public AdRecord getRecord(final int record) {
return mAdRecords.get(record);
}
/**
* Gets the record data as string.
*
* @param record the record
* @return the record data as string
*/
public String getRecordDataAsString(final int record) {
return AdRecordUtils.getRecordDataAsString(
mAdRecords.get(record));
}
/**
* Gets the record as collection.
*
* @return the records as collection
*/
public Collection<AdRecord> getRecordsAsCollection() {
return Collections.unmodifiableCollection(asList(mAdRecords));
}
/**
* Checks if is record present.
*
* @param record the record
* @return true, if is record present
*/
public boolean isRecordPresent(final int record) {
return mAdRecords.indexOfKey(record) >= 0;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "AdRecordStore [mLocalNameComplete=" + mLocalNameComplete + ", mLocalNameShort=" + mLocalNameShort + "]";
}
/* (non-Javadoc)
* @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
*/
@Override
public void writeToParcel(final Parcel parcel, final int arg1) {
final Bundle b = new Bundle();
b.putString("local_name_complete", mLocalNameComplete);
b.putString("local_name_short", mLocalNameShort);
b.putSparseParcelableArray("records_array", mAdRecords);
parcel.writeBundle(b);
}
/**
* As list.
*
* @param <C> the generic type
* @param sparseArray the sparse array
* @return the collection
*/
public static <C> Collection<C> asList(final SparseArray<C> sparseArray) {
if (sparseArray == null) return null;
final Collection<C> arrayList = new ArrayList<>(sparseArray.size());
for (int i = 0; i < sparseArray.size(); i++) {
arrayList.add(sparseArray.valueAt(i));
}
return arrayList;
}
}

View File

@@ -0,0 +1,8 @@
package uk.co.alt236.bluetoothlelib.device.beacon;
/**
*
*/
public interface BeaconDevice {
BeaconType getBeaconType();
}

View File

@@ -0,0 +1,31 @@
package uk.co.alt236.bluetoothlelib.device.beacon;
import java.util.Arrays;
/**
*
*/
public abstract class BeaconManufacturerData {
private final BeaconType mBeaconType;
private final byte[] mData;
protected BeaconManufacturerData(final BeaconType expectedType, final byte[] data){
if (BeaconUtils.getBeaconType(data) != expectedType) {
throw new IllegalArgumentException(
"Manufacturer record '"
+ Arrays.toString(data)
+ "' is not from a " + expectedType);
}
this.mData = data;
this.mBeaconType = expectedType;
}
public BeaconType getBeaconType(){
return mBeaconType;
}
public byte[] getData(){
return mData;
}
}

View File

@@ -0,0 +1,9 @@
package uk.co.alt236.bluetoothlelib.device.beacon;
/**
*
*/
public enum BeaconType {
NOT_A_BEACON,
IBEACON,
}

View File

@@ -0,0 +1,58 @@
package uk.co.alt236.bluetoothlelib.device.beacon;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconConstants;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
/**
*
*/
public final class BeaconUtils {
private BeaconUtils(){
// TO AVOID INSTANTIATION
}
/**
* Ascertains whether a Manufacturer Data byte array belongs to a known Beacon type;
*
* @param manufacturerData a Bluetooth LE device's raw manufacturerData.
* @return the {@link BeaconType}
*/
public static BeaconType getBeaconType(final byte[] manufacturerData) {
if (manufacturerData == null || manufacturerData.length == 0) {
return BeaconType.NOT_A_BEACON;
}
if(isIBeacon(manufacturerData)){
return BeaconType.IBEACON;
} else {
return BeaconType.NOT_A_BEACON;
}
}
/**
* Ascertains whether a {@link uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice} is an iBeacon;
*
* @param device a {@link uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice} device.
* @return the {@link BeaconType}
*/
public static BeaconType getBeaconType(final BluetoothLeDevice device) {
final int key = AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA;
return getBeaconType(device.getAdRecordStore().getRecordDataAsString(key).getBytes());
}
private static boolean isIBeacon(final byte[] manufacturerData){
// An iBeacon record must be at least 25 chars long
if (!(manufacturerData.length >= 25)) {
return false;
}
if (ByteUtils.doesArrayBeginWith(manufacturerData, IBeaconConstants.MANUFACTURER_DATA_IBEACON_PREFIX)) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,9 @@
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
/**
*
*/
public class IBeaconConstants {
public static final byte[] MANUFACTURER_DATA_IBEACON_PREFIX = {0x4C, 0x00, 0x02, 0x15};
}

View File

@@ -0,0 +1,142 @@
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconDevice;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
public class IBeaconDevice extends BluetoothLeDevice implements BeaconDevice{
/**
* The m iBeacon data.
*/
private final IBeaconManufacturerData mIBeaconData;
/**
* Instantiates a new iBeacon device.
*
* @param device the device
* @param rssi the RSSI value
* @param scanRecord the scanRecord
* @throws IllegalArgumentException if the passed device is not an iBeacon
*/
public IBeaconDevice(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
super(device, rssi, scanRecord, 0);
mIBeaconData = new IBeaconManufacturerData(this);
}
/**
* Instantiates a new iBeacon device.
*
* @param device the device
* @param rssi the RSSI value of the RSSI measurement
* @param scanRecord the scan record
* @param timestamp the timestamp of the RSSI measurement
* @throws IllegalArgumentException if the passed device is not an iBeacon
*/
public IBeaconDevice(final BluetoothDevice device, final int rssi, final byte[] scanRecord, final long timestamp) {
super(device, rssi, scanRecord, timestamp);
mIBeaconData = new IBeaconManufacturerData(this);
}
/**
* Will try to convert a {@link BluetoothLeDevice} into an
* iBeacon Device.
*
* @param device the device
* @throws IllegalArgumentException if the passed device is not an iBeacon
*/
public IBeaconDevice(final BluetoothLeDevice device) {
super(device);
mIBeaconData = new IBeaconManufacturerData(this);
}
private IBeaconDevice(final Parcel in) {
super(in);
mIBeaconData = new IBeaconManufacturerData(this);
}
/**
* Gets the estimated Accuracy of the reading in meters based on
* a simple running average of the last {@link #MAX_RSSI_LOG_SIZE}
* samples.
*
* @return the accuracy in meters
*/
public double getAccuracy() {
return IBeaconUtils.calculateAccuracy(
getCalibratedTxPower(),
getRunningAverageRssi());
}
@Override
public BeaconType getBeaconType() {
return BeaconType.IBEACON;
}
/**
* Gets the calibrated TX power of the iBeacon device as reported.
*
* @return the calibrated TX power
*/
public int getCalibratedTxPower() {
return getIBeaconData().getCalibratedTxPower();
}
/**
* Gets the iBeacon company identifier.
*
* @return the company identifier
*/
public int getCompanyIdentifier() {
return getIBeaconData().getCompanyIdentifier();
}
/**
* Gets the estimated Distance descriptor.
*
* @return the distance descriptor
*/
public IBeaconDistanceDescriptor getDistanceDescriptor() {
return IBeaconUtils.getDistanceDescriptor(getAccuracy());
}
/**
* Gets the iBeacon manufacturing data.
*
* @return the iBeacon data
*/
public IBeaconManufacturerData getIBeaconData() {
return mIBeaconData;
}
/**
* Gets the iBeacon Major value.
*
* @return the Major value
*/
public int getMajor() {
return getIBeaconData().getMajor();
}
/**
* Gets the iBeacon Minor value.
*
* @return the Minor value
*/
public int getMinor() {
return getIBeaconData().getMinor();
}
/**
* Gets the iBeacon UUID.
*
* @return the UUID
*/
public String getUUID() {
return getIBeaconData().getUUID();
}
}

View File

@@ -0,0 +1,8 @@
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
public enum IBeaconDistanceDescriptor {
IMMEDIATE,
NEAR,
FAR,
UNKNOWN,
}

View File

@@ -0,0 +1,133 @@
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
import java.util.Arrays;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconManufacturerData;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
/**
* Parses the Manufactured Data field of an iBeacon
* <p>
* The parsing is based on the following schema:
* <pre>
* Byte|Value
* -------------------------------------------------
* 0 4C - Byte 1 (LSB) of Company identifier code
* 1 00 - Byte 0 (MSB) of Company identifier code (0x004C == Apple)
* 2 02 - Byte 0 of iBeacon advertisement indicator
* 3 15 - Byte 1 of iBeacon advertisement indicator
* 4 e2 |\
* 5 c5 |\\
* 6 6d |#\\
* 7 b5 |##\\
* 8 df |###\\
* 9 fb |####\\
* 10 48 |#####\\
* 11 d2 |#####|| iBeacon
* 12 b0 |#####|| Proximity UUID
* 13 60 |#####//
* 14 d0 |####//
* 15 f5 |###//
* 16 a7 |##//
* 17 10 |#//
* 18 96 |//
* 19 e0 |/
* 20 00 - major
* 21 00
* 22 00 - minor
* 23 00
* 24 c5 - The 2's complement of the calibrated Tx Power
* </pre>
* @author Alexandros Schillings
*/
public final class IBeaconManufacturerData extends BeaconManufacturerData{
private final int mCalibratedTxPower;
private final int mCompanyIdentidier;
private final int mIBeaconAdvertisment;
private final int mMajor;
private final int mMinor;
private final String mUUID;
/**
* Instantiates a new iBeacon manufacturer data object.
*
* @param device a {@link BluetoothLeDevice}
* @throws IllegalArgumentException if the data is not from an iBeacon.
*/
public IBeaconManufacturerData(final BluetoothLeDevice device) {
this(device.getAdRecordStore().getRecord(AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA).getData());
}
/**
* Instantiates a new iBeacon manufacturer data object.
*
* @param manufacturerData the {@link AdRecord#TYPE_MANUFACTURER_SPECIFIC_DATA} data array
* @throws IllegalArgumentException if the data is not from an iBeacon.
*/
public IBeaconManufacturerData(final byte[] manufacturerData) {
super(BeaconType.IBEACON, manufacturerData);
final byte[] intArray = Arrays.copyOfRange(manufacturerData, 0, 2);
ByteUtils.invertArray(intArray);
mCompanyIdentidier = ByteUtils.getIntFrom2ByteArray(intArray);
mIBeaconAdvertisment = ByteUtils.getIntFrom2ByteArray(Arrays.copyOfRange(manufacturerData, 2, 4));
mUUID = IBeaconUtils.calculateUuidString(Arrays.copyOfRange(manufacturerData, 4, 20));
mMajor = ByteUtils.getIntFrom2ByteArray(Arrays.copyOfRange(manufacturerData, 20, 22));
mMinor = ByteUtils.getIntFrom2ByteArray(Arrays.copyOfRange(manufacturerData, 22, 24));
mCalibratedTxPower = manufacturerData[24];
}
/**
* Gets the calibrated TX power of the iBeacon device as reported.
*
* @return the calibrated TX power
*/
public int getCalibratedTxPower() {
return mCalibratedTxPower;
}
/**
* Gets the iBeacon company identifier.
*
* @return the company identifier
*/
public int getCompanyIdentifier() {
return mCompanyIdentidier;
}
public int getIBeaconAdvertisement() {
return mIBeaconAdvertisment;
}
/**
* Gets the iBeacon Major value.
*
* @return the Major value
*/
public int getMajor() {
return mMajor;
}
/**
* Gets the iBeacon Minor value.
*
* @return the Minor value
*/
public int getMinor() {
return mMinor;
}
/**
* Gets the iBeacon UUID.
*
* @return the UUID
*/
public String getUUID() {
return mUUID;
}
}

View File

@@ -0,0 +1,79 @@
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
final class IBeaconUtils {
private static final double DISTANCE_THRESHOLD_WTF = 0.0;
private static final double DISTANCE_THRESHOLD_IMMEDIATE = 0.5;
private static final double DISTANCE_THRESHOLD_NEAR = 3.0;
private IBeaconUtils(){
// TO AVOID INSTANTIATION
}
/**
* Calculates the accuracy of an RSSI reading.
* <p/>
* The code was taken from <a href="http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing" /a>
*
* @param txPower the calibrated TX power of an iBeacon
* @param rssi the RSSI value of the iBeacon
* @return the calculated Accuracy
*/
public static double calculateAccuracy(final int txPower, final double rssi) {
if (rssi == 0) {
return -1.0; // if we cannot determine accuracy, return -1.
}
final double ratio = rssi * 1.0 / txPower;
if (ratio < 1.0) {
return Math.pow(ratio, 10);
} else {
return (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
}
}
public static String calculateUuidString(final byte[] uuid) {
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < uuid.length; i++) {
if (i == 4) {
sb.append('-');
}
if (i == 6) {
sb.append('-');
}
if (i == 8) {
sb.append('-');
}
if (i == 10) {
sb.append('-');
}
final int intFromByte = ByteUtils.getIntFromByte(uuid[i]);
if(intFromByte <= 0xF){
sb.append('0');
}
sb.append(Integer.toHexString(intFromByte));
}
return sb.toString();
}
public static IBeaconDistanceDescriptor getDistanceDescriptor(final double accuracy) {
if (accuracy < DISTANCE_THRESHOLD_WTF) {
return IBeaconDistanceDescriptor.UNKNOWN;
}
if (accuracy < DISTANCE_THRESHOLD_IMMEDIATE) {
return IBeaconDistanceDescriptor.IMMEDIATE;
}
if (accuracy < DISTANCE_THRESHOLD_NEAR) {
return IBeaconDistanceDescriptor.NEAR;
}
return IBeaconDistanceDescriptor.FAR;
}
}

View File

@@ -0,0 +1,142 @@
package uk.co.alt236.bluetoothlelib.resolvers;
import android.bluetooth.BluetoothClass;
public class BluetoothClassResolver {
public static String resolveDeviceClass(final int btClass) {
switch (btClass) {
case BluetoothClass.Device.AUDIO_VIDEO_CAMCORDER:
return "A/V, Camcorder";
case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
return "A/V, Car Audio";
case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
return "A/V, Handsfree";
case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
return "A/V, Headphones";
case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
return "A/V, HiFi Audio";
case BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER:
return "A/V, Loudspeaker";
case BluetoothClass.Device.AUDIO_VIDEO_MICROPHONE:
return "A/V, Microphone";
case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
return "A/V, Portable Audio";
case BluetoothClass.Device.AUDIO_VIDEO_SET_TOP_BOX:
return "A/V, Set Top Box";
case BluetoothClass.Device.AUDIO_VIDEO_UNCATEGORIZED:
return "A/V, Uncategorized";
case BluetoothClass.Device.AUDIO_VIDEO_VCR:
return "A/V, VCR";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_CAMERA:
return "A/V, Video Camera";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_CONFERENCING:
return "A/V, Video Conferencing";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER:
return "A/V, Video Display and Loudspeaker";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_GAMING_TOY:
return "A/V, Video Gaming Toy";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_MONITOR:
return "A/V, Video Monitor";
case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
return "A/V, Video Wearable Headset";
case BluetoothClass.Device.COMPUTER_DESKTOP:
return "Computer, Desktop";
case BluetoothClass.Device.COMPUTER_HANDHELD_PC_PDA:
return "Computer, Handheld PC/PDA";
case BluetoothClass.Device.COMPUTER_LAPTOP:
return "Computer, Laptop";
case BluetoothClass.Device.COMPUTER_PALM_SIZE_PC_PDA:
return "Computer, Palm Size PC/PDA";
case BluetoothClass.Device.COMPUTER_SERVER:
return "Computer, Server";
case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
return "Computer, Uncategorized";
case BluetoothClass.Device.COMPUTER_WEARABLE:
return "Computer, Wearable";
case BluetoothClass.Device.HEALTH_BLOOD_PRESSURE:
return "Health, Blood Pressure";
case BluetoothClass.Device.HEALTH_DATA_DISPLAY:
return "Health, Data Display";
case BluetoothClass.Device.HEALTH_GLUCOSE:
return "Health, Glucose";
case BluetoothClass.Device.HEALTH_PULSE_OXIMETER:
return "Health, Pulse Oximeter";
case BluetoothClass.Device.HEALTH_PULSE_RATE:
return "Health, Pulse Rate";
case BluetoothClass.Device.HEALTH_THERMOMETER:
return "Health, Thermometer";
case BluetoothClass.Device.HEALTH_UNCATEGORIZED:
return "Health, Uncategorized";
case BluetoothClass.Device.HEALTH_WEIGHING:
return "Health, Weighting";
case BluetoothClass.Device.PHONE_CELLULAR:
return "Phone, Cellular";
case BluetoothClass.Device.PHONE_CORDLESS:
return "Phone, Cordless";
case BluetoothClass.Device.PHONE_ISDN:
return "Phone, ISDN";
case BluetoothClass.Device.PHONE_MODEM_OR_GATEWAY:
return "Phone, Modem or Gateway";
case BluetoothClass.Device.PHONE_SMART:
return "Phone, Smart";
case BluetoothClass.Device.PHONE_UNCATEGORIZED:
return "Phone, Uncategorized";
case BluetoothClass.Device.TOY_CONTROLLER:
return "Toy, Controller";
case BluetoothClass.Device.TOY_DOLL_ACTION_FIGURE:
return "Toy, Doll/Action Figure";
case BluetoothClass.Device.TOY_GAME:
return "Toy, Game";
case BluetoothClass.Device.TOY_ROBOT:
return "Toy, Robot";
case BluetoothClass.Device.TOY_UNCATEGORIZED:
return "Toy, Uncategorized";
case BluetoothClass.Device.TOY_VEHICLE:
return "Toy, Vehicle";
case BluetoothClass.Device.WEARABLE_GLASSES:
return "Wearable, Glasses";
case BluetoothClass.Device.WEARABLE_HELMET:
return "Wearable, Helmet";
case BluetoothClass.Device.WEARABLE_JACKET:
return "Wearable, Jacket";
case BluetoothClass.Device.WEARABLE_PAGER:
return "Wearable, Pager";
case BluetoothClass.Device.WEARABLE_UNCATEGORIZED:
return "Wearable, Uncategorized";
case BluetoothClass.Device.WEARABLE_WRIST_WATCH:
return "Wearable, Wrist Watch";
default:
return "Unknown, Unknown (class=" + btClass + ")";
}
}
public static String resolveMajorDeviceClass(final int majorBtClass) {
switch (majorBtClass) {
case BluetoothClass.Device.Major.AUDIO_VIDEO:
return "Audio/ Video";
case BluetoothClass.Device.Major.COMPUTER:
return "Computer";
case BluetoothClass.Device.Major.HEALTH:
return "Health";
case BluetoothClass.Device.Major.IMAGING:
return "Imaging";
case BluetoothClass.Device.Major.MISC:
return "Misc";
case BluetoothClass.Device.Major.NETWORKING:
return "Networking";
case BluetoothClass.Device.Major.PERIPHERAL:
return "Peripheral";
case BluetoothClass.Device.Major.PHONE:
return "Phone";
case BluetoothClass.Device.Major.TOY:
return "Toy";
case BluetoothClass.Device.Major.UNCATEGORIZED:
return "Uncategorized";
case BluetoothClass.Device.Major.WEARABLE:
return "Wearable";
default:
return "Unknown (" +majorBtClass+ ")";
}
}
}

View File

@@ -0,0 +1,646 @@
package uk.co.alt236.bluetoothlelib.resolvers;
import android.util.SparseArray;
public class CompanyIdentifierResolver {
public static final int ERICSSON_TECHNOLOGY_LICENSING = 0x0000;
public static final int NOKIA_MOBILE_PHONES = 0x0001;
public static final int INTEL_CORP = 0x0002;
public static final int IBM_CORP = 0x0003;
public static final int TOSHIBA_CORP = 0x0004;
public static final int THREE_COM = 0x0005;
public static final int MICROSOFT = 0x0006;
public static final int LUCENT = 0x0007;
public static final int MOTOROLA = 0x0008;
public static final int INFINEON_TECHNOLOGIES_AG = 0x0009;
public static final int CAMBRIDGE_SILICON_RADIO = 0x000A;
public static final int SILICON_WAVE = 0x000B;
public static final int DIGIANSWER_A_S = 0x000C;
public static final int TEXAS_INSTRUMENTS_INC = 0x000D;
public static final int CEVA_INC_FORMERLY_PARTHUS_TECHNOLOGIES_INC = 0x000E;
public static final int BROADCOM_CORPORATION = 0x000F;
public static final int MITEL_SEMICONDUCTOR = 0x0010;
public static final int WIDCOMM_INC = 0x0011;
public static final int ZEEVO_INC = 0x0012;
public static final int ATMEL_CORPORATION = 0x0013;
public static final int MITSUBISHI_ELECTRIC_CORPORATION = 0x0014;
public static final int RTX_TELECOM_A_S = 0x0015;
public static final int KC_TECHNOLOGY_INC = 0x0016;
public static final int NEWLOGIC = 0x0017;
public static final int TRANSILICA_INC = 0x0018;
public static final int ROHDE_SCHWARZ_GMBH_CO_KG = 0x0019;
public static final int TTPCOM_LIMITED = 0x001A;
public static final int SIGNIA_TECHNOLOGIES_INC = 0x001B;
public static final int CONEXANT_SYSTEMS_INC = 0x001C;
public static final int QUALCOMM = 0x001D;
public static final int INVENTEL = 0x001E;
public static final int AVM_BERLIN = 0x001F;
public static final int BANDSPEED_INC = 0x0020;
public static final int MANSELLA_LTD = 0x0021;
public static final int NEC_CORPORATION = 0x0022;
public static final int WAVEPLUS_TECHNOLOGY_CO_LTD = 0x0023;
public static final int ALCATEL = 0x0024;
public static final int PHILIPS_SEMICONDUCTORS = 0x0025;
public static final int C_TECHNOLOGIES = 0x0026;
public static final int OPEN_INTERFACE = 0x0027;
public static final int R_F_MICRO_DEVICES = 0x0028;
public static final int HITACHI_LTD = 0x0029;
public static final int SYMBOL_TECHNOLOGIES_INC = 0x002A;
public static final int TENOVIS = 0x002B;
public static final int MACRONIX_INTERNATIONAL_CO_LTD = 0x002C;
public static final int GCT_SEMICONDUCTOR = 0x002D;
public static final int NORWOOD_SYSTEMS = 0x002E;
public static final int MEWTEL_TECHNOLOGY_INC = 0x002F;
public static final int ST_MICROELECTRONICS = 0x0030;
public static final int SYNOPSIS = 0x0031;
public static final int REDM_COMMUNICATIONS_LTD = 0x0032;
public static final int COMMIL_LTD = 0x0033;
public static final int COMPUTER_ACCESS_TECHNOLOGY_CORPORATION_CATC = 0x0034;
public static final int ECLIPSE_HQ_ESPANA_SL = 0x0035;
public static final int RENESAS_TECHNOLOGY_CORP = 0x0036;
public static final int MOBILIAN_CORPORATION = 0x0037;
public static final int TERAX = 0x0038;
public static final int INTEGRATED_SYSTEM_SOLUTION_CORP = 0x0039;
public static final int MATSUSHITA_ELECTRIC_INDUSTRIAL_CO_LTD = 0x003A;
public static final int GENNUM_CORPORATION = 0x003B;
public static final int RESEARCH_IN_MOTION = 0x003C;
public static final int IPEXTREME_INC = 0x003D;
public static final int SYSTEMS_AND_CHIPS_INC = 0x003E;
public static final int BLUETOOTH_SIG_INC = 0x003F;
public static final int SEIKO_EPSON_CORPORATION = 0x0040;
public static final int INTEGRATED_SILICON_SOLUTION_TAIWAN_INC = 0x0041;
public static final int CONWISE_TECHNOLOGY_CORPORATION_LTD = 0x0042;
public static final int PARROT_SA = 0x0043;
public static final int SOCKET_MOBILE = 0x0044;
public static final int ATHEROS_COMMUNICATIONS_INC = 0x0045;
public static final int MEDIATEK_INC = 0x0046;
public static final int BLUEGIGA = 0x0047;
public static final int MARVELL_TECHNOLOGY_GROUP_LTD = 0x0048;
public static final int THREE_DSP_CORPORATION = 0x0049;
public static final int ACCEL_SEMICONDUCTOR_LTD = 0x004A;
public static final int CONTINENTAL_AUTOMOTIVE_SYSTEMS = 0x004B;
public static final int APPLE_INC = 0x004C;
public static final int STACCATO_COMMUNICATIONS_INC = 0x004D;
public static final int AVAGO_TECHNOLOGIES = 0x004E;
public static final int APT_LICENSING_LTD = 0x004F;
public static final int SIRF_TECHNOLOGY = 0x0050;
public static final int TZERO_TECHNOLOGIES_INC = 0x0051;
public static final int JM_CORPORATION = 0x0052;
public static final int FREE2MOVE_AB = 0x0053;
public static final int THREE_DIJOY_CORPORATION = 0x0054;
public static final int PLANTRONICS_INC = 0x0055;
public static final int SONY_ERICSSON_MOBILE_COMMUNICATIONS = 0x0056;
public static final int HARMAN_INTERNATIONAL_INDUSTRIES_INC = 0x0057;
public static final int VIZIO_INC = 0x0058;
public static final int NORDIC_SEMICONDUCTOR_ASA = 0x0059;
public static final int EM_MICROELECTRONICMARIN_SA = 0x005A;
public static final int RALINK_TECHNOLOGY_CORPORATION = 0x005B;
public static final int BELKIN_INTERNATIONAL_INC = 0x005C;
public static final int REALTEK_SEMICONDUCTOR_CORPORATION = 0x005D;
public static final int STONESTREET_ONE_LLC = 0x005E;
public static final int WICENTRIC_INC = 0x005F;
public static final int RIVIERAWAVES_SAS = 0x0060;
public static final int RDA_MICROELECTRONICS = 0x0061;
public static final int GIBSON_GUITARS = 0x0062;
public static final int MICOMMAND_INC = 0x0063;
public static final int BAND_XI_INTERNATIONAL_LLC = 0x0064;
public static final int HEWLETTPACKARD_COMPANY = 0x0065;
public static final int NINE_SOLUTIONS_OY = 0x0066;
public static final int GN_NETCOM_A_S = 0x0067;
public static final int GENERAL_MOTORS = 0x0068;
public static final int AD_ENGINEERING_INC = 0x0069;
public static final int MINDTREE_LTD = 0x006A;
public static final int POLAR_ELECTRO_OY = 0x006B;
public static final int BEAUTIFUL_ENTERPRISE_CO_LTD = 0x006C;
public static final int BRIARTEK_INC = 0x006D;
public static final int SUMMIT_DATA_COMMUNICATIONS_INC = 0x006E;
public static final int SOUND_ID = 0x006F;
public static final int MONSTER_LLC = 0x0070;
public static final int CONNECTBLUE_AB = 0x0071;
public static final int SHANGHAI_SUPER_SMART_ELECTRONICS_CO_LTD = 0x0072;
public static final int GROUP_SENSE_LTD = 0x0073;
public static final int ZOMM_LLC = 0x0074;
public static final int SAMSUNG_ELECTRONICS_CO_LTD = 0x0075;
public static final int CREATIVE_TECHNOLOGY_LTD = 0x0076;
public static final int LAIRD_TECHNOLOGIES = 0x0077;
public static final int NIKE_INC = 0x0078;
public static final int LESSWIRE_AG = 0x0079;
public static final int MSTAR_SEMICONDUCTOR_INC = 0x007A;
public static final int HANLYNN_TECHNOLOGIES = 0x007B;
public static final int A_R_CAMBRIDGE = 0x007C;
public static final int SEERS_TECHNOLOGY_CO_LTD = 0x007D;
public static final int SPORTS_TRACKING_TECHNOLOGIES_LTD = 0x007E;
public static final int AUTONET_MOBILE = 0x007F;
public static final int DELORME_PUBLISHING_COMPANY_INC = 0x0080;
public static final int WUXI_VIMICRO = 0x0081;
public static final int SENNHEISER_COMMUNICATIONS_A_S = 0x0082;
public static final int TIMEKEEPING_SYSTEMS_INC = 0x0083;
public static final int LUDUS_HELSINKI_LTD = 0x0084;
public static final int BLUERADIOS_INC = 0x0085;
public static final int EQUINOX_AG = 0x0086;
public static final int GARMIN_INTERNATIONAL_INC = 0x0087;
public static final int ECOTEST = 0x0088;
public static final int GN_RESOUND_A_S = 0x0089;
public static final int JAWBONE = 0x008A;
public static final int TOPCORN_POSITIONING_SYSTEMS_LLC = 0x008B;
public static final int QUALCOMM_RETAIL_SOLUTIONS_INC_FORMERLY_QUALCOMM_LABS_INC = 0x008C;
public static final int ZSCAN_SOFTWARE = 0x008D;
public static final int QUINTIC_CORP = 0x008E;
public static final int STOLLMAN_EV_GMBH = 0x008F;
public static final int FUNAI_ELECTRIC_CO_LTD = 0x0090;
public static final int ADVANCED_PANMOBIL_SYSTEMS_GMBH_CO_KG = 0x0091;
public static final int THINKOPTICS_INC = 0x0092;
public static final int UNIVERSAL_ELECTRONICS_INC = 0x0093;
public static final int AIROHA_TECHNOLOGY_CORP = 0x0094;
public static final int NEC_LIGHTING_LTD = 0x0095;
public static final int ODM_TECHNOLOGY_INC = 0x0096;
public static final int CONNECTEDEVICE_LTD = 0x0097;
public static final int ZER01TV_GMBH = 0x0098;
public static final int ITECH_DYNAMIC_GLOBAL_DISTRIBUTION_LTD = 0x0099;
public static final int ALPWISE = 0x009A;
public static final int JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS_CO_LTD = 0x009B;
public static final int COLORFY_INC = 0x009C;
public static final int GEOFORCE_INC = 0x009D;
public static final int BOSE_CORPORATION = 0x009E;
public static final int SUUNTO_OY = 0x009F;
public static final int KENSINGTON_COMPUTER_PRODUCTS_GROUP = 0x00A0;
public static final int SRMEDIZINELEKTRONIK = 0x00A1;
public static final int VERTU_CORPORATION_LIMITED = 0x00A2;
public static final int META_WATCH_LTD = 0x00A3;
public static final int LINAK_A_S = 0x00A4;
public static final int OTL_DYNAMICS_LLC = 0x00A5;
public static final int PANDA_OCEAN_INC = 0x00A6;
public static final int VISTEON_CORPORATION = 0x00A7;
public static final int ARP_DEVICES_LIMITED = 0x00A8;
public static final int MAGNETI_MARELLI_SPA = 0x00A9;
public static final int CAEN_RFID_SRL = 0x00AA;
public static final int INGENIEURSYSTEMGRUPPE_ZAHN_GMBH = 0x00AB;
public static final int GREEN_THROTTLE_GAMES = 0x00AC;
public static final int PETER_SYSTEMTECHNIK_GMBH = 0x00AD;
public static final int OMEGAWAVE_OY = 0x00AE;
public static final int CINETIX = 0x00AF;
public static final int PASSIF_SEMICONDUCTOR_CORP = 0x00B0;
public static final int SARIS_CYCLING_GROUP_INC = 0x00B1;
public static final int BEKEY_A_S = 0x00B2;
public static final int CLARINOX_TECHNOLOGIES_PTY_LTD = 0x00B3;
public static final int BDE_TECHNOLOGY_CO_LTD = 0x00B4;
public static final int SWIRL_NETWORKS = 0x00B5;
public static final int MESO_INTERNATIONAL = 0x00B6;
public static final int TRELAB_LTD = 0x00B7;
public static final int QUALCOMM_INNOVATION_CENTER_INC_QUIC = 0x00B8;
public static final int JOHNSON_CONTROLS_INC = 0x00B9;
public static final int STARKEY_LABORATORIES_INC = 0x00BA;
public static final int SPOWER_ELECTRONICS_LIMITED = 0x00BB;
public static final int ACE_SENSOR_INC = 0x00BC;
public static final int APLIX_CORPORATION = 0x00BD;
public static final int AAMP_OF_AMERICA = 0x00BE;
public static final int STALMART_TECHNOLOGY_LIMITED = 0x00BF;
public static final int AMICCOM_ELECTRONICS_CORPORATION = 0x00C0;
public static final int SHENZHEN_EXCELSECU_DATA_TECHNOLOGY_COLTD = 0x00C1;
public static final int GENEQ_INC = 0x00C2;
public static final int ADIDAS_AG = 0x00C3;
public static final int LG_ELECTRONICS = 0x00C4;
public static final int ONSET_COMPUTER_CORPORATION = 0x00C5;
public static final int SELFLY_BV = 0x00C6;
public static final int QUUPPA_OY = 0x00C7;
public static final int GELO_INC = 0x00C8;
public static final int EVLUMA = 0x00C9;
public static final int MC10 = 0x00CA;
public static final int BINAURIC_SE = 0x00CB;
public static final int BEATS_ELECTRONICS = 0x00CC;
public static final int MICROCHIP_TECHNOLOGY_INC = 0x00CD;
public static final int ELGATO_SYSTEMS_GMBH = 0x00CE;
public static final int ARCHOS_SA = 0x00CF;
public static final int DEXCOM_INC = 0x00D0;
public static final int POLAR_ELECTRO_EUROPE_BV = 0x00D1;
public static final int DIALOG_SEMICONDUCTOR_BV = 0x00D2;
public static final int TAIXINGBANG_TECHNOLOGY_HK_CO_LTD = 0x00D3;
public static final int KAWANTECH = 0x00D4;
public static final int AUSTCO_COMMUNICATION_SYSTEMS = 0x00D5;
public static final int TIMEX_GROUP_USA_INC = 0x00D6;
public static final int QUALCOMM_TECHNOLOGIES_INC = 0x00D7;
public static final int QUALCOMM_CONNECTED_EXPERIENCES_INC = 0x00D8;
public static final int VOYETRA_TURTLE_BEACH = 0x00D9;
public static final int TXTR_GMBH = 0x00DA;
public static final int BIOSENTRONICS = 0x00DB;
public static final int PROCTER_GAMBLE = 0x00DC;
public static final int HOSIDEN_CORPORATION = 0x00DD;
public static final int MUZIK_LLC = 0x00DE;
public static final int MISFIT_WEARABLES_CORP = 0x00DF;
public static final int GOOGLE = 0x00E0;
public static final int DANLERS_LTD = 0x00E1;
public static final int SEMILINK_INC = 0x00E2;
public static final int INMUSIC_BRANDS_INC = 0x00E3;
public static final int LS_RESEARCH_INC = 0x00E4;
public static final int EDEN_SOFTWARE_CONSULTANTS_LTD = 0x00E5;
public static final int FRESHTEMP = 0x00E6;
public static final int KS_TECHNOLOGIES = 0x00E7;
public static final int ACTS_TECHNOLOGIES = 0x00E8;
public static final int VTRACK_SYSTEMS = 0x00E9;
public static final int NIELSENKELLERMAN_COMPANY = 0x00EA;
public static final int SERVER_TECHNOLOGY_INC = 0x00EB;
public static final int BIORESEARCH_ASSOCIATES = 0x00EC;
public static final int JOLLY_LOGIC_LLC = 0x00ED;
public static final int ABOVE_AVERAGE_OUTCOMES_INC = 0x00EE;
public static final int BITSPLITTERS_GMBH = 0x00EF;
public static final int PAYPAL_INC = 0x00F0;
public static final int WITRON_TECHNOLOGY_LIMITED = 0x00F1;
public static final int MORSE_PROJECT_INC = 0x00F2;
public static final int KENT_DISPLAYS_INC = 0x00F3;
public static final int NAUTILUS_INC = 0x00F4;
public static final int SMARTIFIER_OY = 0x00F5;
public static final int ELCOMETER_LIMITED = 0x00F6;
public static final int VSN_TECHNOLOGIES_INC = 0x00F7;
public static final int ACEUNI_CORP_LTD = 0x00F8;
public static final int STICKNFIND = 0x00F9;
public static final int CRYSTAL_CODE_AB = 0x00FA;
public static final int KOUKAAM_AS = 0x00FB;
public static final int DELPHI_CORPORATION = 0x00FC;
public static final int VALENCETECH_LIMITED = 0x00FD;
public static final int RESERVED = 0x00FE;
public static final int TYPO_PRODUCTS_LLC = 0x00FF;
public static final int TOMTOM_INTERNATIONAL_BV = 0x0100;
public static final int FUGOO_INC = 0x0101;
public static final int KEISER_CORPORATION = 0x0102;
public static final int BANG_OLUFSEN_A_S = 0x0103;
public static final int PLUS_LOCATIONS_SYSTEMS_PTY_LTD = 0x0104;
public static final int UBIQUITOUS_COMPUTING_TECHNOLOGY_CORPORATION = 0x0105;
public static final int INNOVATIVE_YACHTTER_SOLUTIONS = 0x0106;
public static final int WILLIAM_DEMANT_HOLDING_A_S = 0x0107;
public static final int CHICONY_ELECTRONICS_CO_LTD = 0x0108;
public static final int ATUS_BV = 0x0109;
public static final int CODEGATE_LTD = 0x010A;
public static final int ERI_INC = 0x010B;
public static final int TRANSDUCERS_DIRECT_LLC = 0x010C;
public static final int FUJITSU_TEN_LIMITED = 0x010D;
public static final int AUDI_AG = 0x010E;
public static final int HISILICON_TECHNOLOGIES_CO_LTD = 0x010F;
public static final int NIPPON_SEIKI_CO_LTD = 0x0110;
public static final int STEELSERIES_APS = 0x0111;
public static final int VYZYBL_INC = 0x0112;
public static final int OPENBRAIN_TECHNOLOGIES_CO_LTD = 0x0113;
public static final int XENSR = 0x0114;
public static final int ESOLUTIONS = 0x0115;
public static final int ONE_OAK_TECHNOLOGIES = 0x0116;
public static final int WIMOTO_TECHNOLOGIES_INC = 0x0117;
public static final int RADIUS_NETWORKS_INC = 0x0118;
public static final int WIZE_TECHNOLOGY_CO_LTD = 0x0119;
public static final int QUALCOMM_LABS_INC = 0x011A;
public static final int ARUBA_NETWORKS = 0x011B;
public static final int BAIDU = 0x011C;
public static final int ARENDI_AG = 0x011D;
public static final int SKODA_AUTO_AS = 0x011E;
public static final int VOLKSWAGON_AG = 0x011F;
public static final int PORSCHE_AG = 0x0120;
public static final int SINO_WEALTH_ELECTRONIC_LTD = 0x0121;
public static final int AIRTURN_INC = 0x0122;
public static final int KINSA_INC = 0x0123;
public static final int HID_GLOBAL = 0x0124;
public static final int SEAT_ES = 0x0125;
public static final int PROMETHEAN_LTD = 0x0126;
public static final int SALUTICA_ALLIED_SOLUTIONS = 0x0127;
public static final int GPSI_GROUP_PTY_LTD = 0x0128;
public static final int NIMBLE_DEVICES_OY = 0x0129;
public static final int CHANGZHOU_YONGSE_INFOTECH_CO_LTD = 0x012A;
public static final int SPORTIQ = 0x012B;
public static final int TEMEC_INSTRUMENTS_BV = 0x012C;
public static final int SONY_CORPORATION = 0x012D;
public static final int ASSA_ABLOY = 0x012E;
public static final int CLARION_CO_LTD = 0x012F;
public static final int WAREHOUSE_INNOVATIONS = 0x0130;
public static final int CYPRESS_SEMICONDUCTOR_CORPORATION = 0x0131;
public static final int MADS_INC = 0x0132;
public static final int BLUE_MAESTRO_LIMITED = 0x0133;
public static final int RESOLUTION_PRODUCTS_INC = 0x0134;
public static final int AIREWEAR_LLC = 0x0135;
public static final int ETC_SP_ZOO = 0x0136;
public static final int PRESTIGIO_PLAZA_LTD = 0x0137;
private static final SparseArray<String> COMPANY_NAME_MAP = populateCompanyNameMap();
public static String getCompanyName(final int companyId, final String fallback) {
final String name = COMPANY_NAME_MAP.get(companyId);
return name == null ? fallback : name;
}
private static SparseArray<String> populateCompanyNameMap() {
final SparseArray<String> map = new SparseArray<>();
map.put(ERICSSON_TECHNOLOGY_LICENSING, "Ericsson Technology Licensing");
map.put(NOKIA_MOBILE_PHONES, "Nokia Mobile Phones");
map.put(INTEL_CORP, "Intel Corp.");
map.put(IBM_CORP, "IBM Corp.");
map.put(TOSHIBA_CORP, "Toshiba Corp.");
map.put(THREE_COM, "3Com");
map.put(MICROSOFT, "Microsoft");
map.put(LUCENT, "Lucent");
map.put(MOTOROLA, "Motorola");
map.put(INFINEON_TECHNOLOGIES_AG, "Infineon Technologies AG");
map.put(CAMBRIDGE_SILICON_RADIO, "Cambridge Silicon Radio");
map.put(SILICON_WAVE, "Silicon Wave");
map.put(DIGIANSWER_A_S, "Digianswer A/S");
map.put(TEXAS_INSTRUMENTS_INC, "Texas Instruments Inc.");
map.put(CEVA_INC_FORMERLY_PARTHUS_TECHNOLOGIES_INC, "Ceva, Inc. (formerly Parthus Technologies, Inc.)");
map.put(BROADCOM_CORPORATION, "Broadcom Corporation");
map.put(MITEL_SEMICONDUCTOR, "Mitel Semiconductor");
map.put(WIDCOMM_INC, "Widcomm, Inc");
map.put(ZEEVO_INC, "Zeevo, Inc.");
map.put(ATMEL_CORPORATION, "Atmel Corporation");
map.put(MITSUBISHI_ELECTRIC_CORPORATION, "Mitsubishi Electric Corporation");
map.put(RTX_TELECOM_A_S, "RTX Telecom A/S");
map.put(KC_TECHNOLOGY_INC, "KC Technology Inc.");
map.put(NEWLOGIC, "NewLogic");
map.put(TRANSILICA_INC, "Transilica, Inc.");
map.put(ROHDE_SCHWARZ_GMBH_CO_KG, "Rohde & Schwarz GmbH & Co. KG");
map.put(TTPCOM_LIMITED, "TTPCom Limited");
map.put(SIGNIA_TECHNOLOGIES_INC, "Signia Technologies, Inc.");
map.put(CONEXANT_SYSTEMS_INC, "Conexant Systems Inc.");
map.put(QUALCOMM, "Qualcomm");
map.put(INVENTEL, "Inventel");
map.put(AVM_BERLIN, "AVM Berlin");
map.put(BANDSPEED_INC, "BandSpeed, Inc.");
map.put(MANSELLA_LTD, "Mansella Ltd");
map.put(NEC_CORPORATION, "NEC Corporation");
map.put(WAVEPLUS_TECHNOLOGY_CO_LTD, "WavePlus Technology Co., Ltd.");
map.put(ALCATEL, "Alcatel");
map.put(PHILIPS_SEMICONDUCTORS, "Philips Semiconductors");
map.put(C_TECHNOLOGIES, "C Technologies");
map.put(OPEN_INTERFACE, "Open Interface");
map.put(R_F_MICRO_DEVICES, "R F Micro Devices");
map.put(HITACHI_LTD, "Hitachi Ltd");
map.put(SYMBOL_TECHNOLOGIES_INC, "Symbol Technologies, Inc.");
map.put(TENOVIS, "Tenovis");
map.put(MACRONIX_INTERNATIONAL_CO_LTD, "Macronix International Co. Ltd.");
map.put(GCT_SEMICONDUCTOR, "GCT Semiconductor");
map.put(NORWOOD_SYSTEMS, "Norwood Systems");
map.put(MEWTEL_TECHNOLOGY_INC, "MewTel Technology Inc.");
map.put(ST_MICROELECTRONICS, "ST Microelectronics");
map.put(SYNOPSIS, "Synopsis");
map.put(REDM_COMMUNICATIONS_LTD, "Red-M (Communications) Ltd");
map.put(COMMIL_LTD, "Commil Ltd");
map.put(COMPUTER_ACCESS_TECHNOLOGY_CORPORATION_CATC, "Computer Access Technology Corporation (CATC)");
map.put(ECLIPSE_HQ_ESPANA_SL, "Eclipse (HQ Espana) S.L.");
map.put(RENESAS_TECHNOLOGY_CORP, "Renesas Technology Corp.");
map.put(MOBILIAN_CORPORATION, "Mobilian Corporation");
map.put(TERAX, "Terax");
map.put(INTEGRATED_SYSTEM_SOLUTION_CORP, "Integrated System Solution Corp.");
map.put(MATSUSHITA_ELECTRIC_INDUSTRIAL_CO_LTD, "Matsushita Electric Industrial Co., Ltd.");
map.put(GENNUM_CORPORATION, "Gennum Corporation");
map.put(RESEARCH_IN_MOTION, "Research In Motion");
map.put(IPEXTREME_INC, "IPextreme, Inc.");
map.put(SYSTEMS_AND_CHIPS_INC, "Systems and Chips, Inc.");
map.put(BLUETOOTH_SIG_INC, "Bluetooth SIG, Inc.");
map.put(SEIKO_EPSON_CORPORATION, "Seiko Epson Corporation");
map.put(INTEGRATED_SILICON_SOLUTION_TAIWAN_INC, "Integrated Silicon Solution Taiwan, Inc.");
map.put(CONWISE_TECHNOLOGY_CORPORATION_LTD, "CONWISE Technology Corporation Ltd");
map.put(PARROT_SA, "PARROT SA");
map.put(SOCKET_MOBILE, "Socket Mobile");
map.put(ATHEROS_COMMUNICATIONS_INC, "Atheros Communications, Inc.");
map.put(MEDIATEK_INC, "MediaTek, Inc.");
map.put(BLUEGIGA, "Bluegiga");
map.put(MARVELL_TECHNOLOGY_GROUP_LTD, "Marvell Technology Group Ltd.");
map.put(THREE_DSP_CORPORATION, "3DSP Corporation");
map.put(ACCEL_SEMICONDUCTOR_LTD, "Accel Semiconductor Ltd.");
map.put(CONTINENTAL_AUTOMOTIVE_SYSTEMS, "Continental Automotive Systems");
map.put(APPLE_INC, "Apple, Inc.");
map.put(STACCATO_COMMUNICATIONS_INC, "Staccato Communications, Inc.");
map.put(AVAGO_TECHNOLOGIES, "Avago Technologies");
map.put(APT_LICENSING_LTD, "APT Licensing Ltd.");
map.put(SIRF_TECHNOLOGY, "SiRF Technology");
map.put(TZERO_TECHNOLOGIES_INC, "Tzero Technologies, Inc.");
map.put(JM_CORPORATION, "J&M Corporation");
map.put(FREE2MOVE_AB, "Free2move AB");
map.put(THREE_DIJOY_CORPORATION, "3DiJoy Corporation");
map.put(PLANTRONICS_INC, "Plantronics, Inc.");
map.put(SONY_ERICSSON_MOBILE_COMMUNICATIONS, "Sony Ericsson Mobile Communications");
map.put(HARMAN_INTERNATIONAL_INDUSTRIES_INC, "Harman International Industries, Inc.");
map.put(VIZIO_INC, "Vizio, Inc.");
map.put(NORDIC_SEMICONDUCTOR_ASA, "Nordic Semiconductor ASA");
map.put(EM_MICROELECTRONICMARIN_SA, "EM Microelectronic-Marin SA");
map.put(RALINK_TECHNOLOGY_CORPORATION, "Ralink Technology Corporation");
map.put(BELKIN_INTERNATIONAL_INC, "Belkin International, Inc.");
map.put(REALTEK_SEMICONDUCTOR_CORPORATION, "Realtek Semiconductor Corporation");
map.put(STONESTREET_ONE_LLC, "Stonestreet One, LLC");
map.put(WICENTRIC_INC, "Wicentric, Inc.");
map.put(RIVIERAWAVES_SAS, "RivieraWaves S.A.S");
map.put(RDA_MICROELECTRONICS, "RDA Microelectronics");
map.put(GIBSON_GUITARS, "Gibson Guitars");
map.put(MICOMMAND_INC, "MiCommand Inc.");
map.put(BAND_XI_INTERNATIONAL_LLC, "Band XI International, LLC");
map.put(HEWLETTPACKARD_COMPANY, "Hewlett-Packard Company");
map.put(NINE_SOLUTIONS_OY, "9Solutions Oy");
map.put(GN_NETCOM_A_S, "GN Netcom A/S");
map.put(GENERAL_MOTORS, "General Motors");
map.put(AD_ENGINEERING_INC, "A&D Engineering, Inc.");
map.put(MINDTREE_LTD, "MindTree Ltd.");
map.put(POLAR_ELECTRO_OY, "Polar Electro OY");
map.put(BEAUTIFUL_ENTERPRISE_CO_LTD, "Beautiful Enterprise Co., Ltd.");
map.put(BRIARTEK_INC, "BriarTek, Inc.");
map.put(SUMMIT_DATA_COMMUNICATIONS_INC, "Summit Data Communications, Inc.");
map.put(SOUND_ID, "Sound ID");
map.put(MONSTER_LLC, "Monster, LLC");
map.put(CONNECTBLUE_AB, "connectBlue AB");
map.put(SHANGHAI_SUPER_SMART_ELECTRONICS_CO_LTD, "ShangHai Super Smart Electronics Co. Ltd.");
map.put(GROUP_SENSE_LTD, "Group Sense Ltd.");
map.put(ZOMM_LLC, "Zomm, LLC");
map.put(SAMSUNG_ELECTRONICS_CO_LTD, "Samsung Electronics Co. Ltd.");
map.put(CREATIVE_TECHNOLOGY_LTD, "Creative Technology Ltd.");
map.put(LAIRD_TECHNOLOGIES, "Laird Technologies");
map.put(NIKE_INC, "Nike, Inc.");
map.put(LESSWIRE_AG, "lesswire AG");
map.put(MSTAR_SEMICONDUCTOR_INC, "MStar Semiconductor, Inc.");
map.put(HANLYNN_TECHNOLOGIES, "Hanlynn Technologies");
map.put(A_R_CAMBRIDGE, "A & R Cambridge");
map.put(SEERS_TECHNOLOGY_CO_LTD, "Seers Technology Co. Ltd");
map.put(SPORTS_TRACKING_TECHNOLOGIES_LTD, "Sports Tracking Technologies Ltd.");
map.put(AUTONET_MOBILE, "Autonet Mobile");
map.put(DELORME_PUBLISHING_COMPANY_INC, "DeLorme Publishing Company, Inc.");
map.put(WUXI_VIMICRO, "WuXi Vimicro");
map.put(SENNHEISER_COMMUNICATIONS_A_S, "Sennheiser Communications A/S");
map.put(TIMEKEEPING_SYSTEMS_INC, "TimeKeeping Systems, Inc.");
map.put(LUDUS_HELSINKI_LTD, "Ludus Helsinki Ltd.");
map.put(BLUERADIOS_INC, "BlueRadios, Inc.");
map.put(EQUINOX_AG, "equinox AG");
map.put(GARMIN_INTERNATIONAL_INC, "Garmin International, Inc.");
map.put(ECOTEST, "Ecotest");
map.put(GN_RESOUND_A_S, "GN ReSound A/S");
map.put(JAWBONE, "Jawbone");
map.put(TOPCORN_POSITIONING_SYSTEMS_LLC, "Topcorn Positioning Systems, LLC");
map.put(QUALCOMM_RETAIL_SOLUTIONS_INC_FORMERLY_QUALCOMM_LABS_INC, "Qualcomm Retail Solutions, Inc. (formerly Qualcomm Labs, Inc.)");
map.put(ZSCAN_SOFTWARE, "Zscan Software");
map.put(QUINTIC_CORP, "Quintic Corp.");
map.put(STOLLMAN_EV_GMBH, "Stollman E+V GmbH");
map.put(FUNAI_ELECTRIC_CO_LTD, "Funai Electric Co., Ltd.");
map.put(ADVANCED_PANMOBIL_SYSTEMS_GMBH_CO_KG, "Advanced PANMOBIL Systems GmbH & Co. KG");
map.put(THINKOPTICS_INC, "ThinkOptics, Inc.");
map.put(UNIVERSAL_ELECTRONICS_INC, "Universal Electronics, Inc.");
map.put(AIROHA_TECHNOLOGY_CORP, "Airoha Technology Corp.");
map.put(NEC_LIGHTING_LTD, "NEC Lighting, Ltd.");
map.put(ODM_TECHNOLOGY_INC, "ODM Technology, Inc.");
map.put(CONNECTEDEVICE_LTD, "ConnecteDevice Ltd.");
map.put(ZER01TV_GMBH, "zer01.tv GmbH");
map.put(ITECH_DYNAMIC_GLOBAL_DISTRIBUTION_LTD, "i.Tech Dynamic Global Distribution Ltd.");
map.put(ALPWISE, "Alpwise");
map.put(JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS_CO_LTD, "Jiangsu Toppower Automotive Electronics Co., Ltd.");
map.put(COLORFY_INC, "Colorfy, Inc.");
map.put(GEOFORCE_INC, "Geoforce Inc.");
map.put(BOSE_CORPORATION, "Bose Corporation");
map.put(SUUNTO_OY, "Suunto Oy");
map.put(KENSINGTON_COMPUTER_PRODUCTS_GROUP, "Kensington Computer Products Group");
map.put(SRMEDIZINELEKTRONIK, "SR-Medizinelektronik");
map.put(VERTU_CORPORATION_LIMITED, "Vertu Corporation Limited");
map.put(META_WATCH_LTD, "Meta Watch Ltd.");
map.put(LINAK_A_S, "LINAK A/S");
map.put(OTL_DYNAMICS_LLC, "OTL Dynamics LLC");
map.put(PANDA_OCEAN_INC, "Panda Ocean Inc.");
map.put(VISTEON_CORPORATION, "Visteon Corporation");
map.put(ARP_DEVICES_LIMITED, "ARP Devices Limited");
map.put(MAGNETI_MARELLI_SPA, "Magneti Marelli S.p.A");
map.put(CAEN_RFID_SRL, "CAEN RFID srl");
map.put(INGENIEURSYSTEMGRUPPE_ZAHN_GMBH, "Ingenieur-Systemgruppe Zahn GmbH");
map.put(GREEN_THROTTLE_GAMES, "Green Throttle Games");
map.put(PETER_SYSTEMTECHNIK_GMBH, "Peter Systemtechnik GmbH");
map.put(OMEGAWAVE_OY, "Omegawave Oy");
map.put(CINETIX, "Cinetix");
map.put(PASSIF_SEMICONDUCTOR_CORP, "Passif Semiconductor Corp");
map.put(SARIS_CYCLING_GROUP_INC, "Saris Cycling Group, Inc");
map.put(BEKEY_A_S, "Bekey A/S");
map.put(CLARINOX_TECHNOLOGIES_PTY_LTD, "Clarinox Technologies Pty. Ltd.");
map.put(BDE_TECHNOLOGY_CO_LTD, "BDE Technology Co., Ltd.");
map.put(SWIRL_NETWORKS, "Swirl Networks");
map.put(MESO_INTERNATIONAL, "Meso international");
map.put(TRELAB_LTD, "TreLab Ltd");
map.put(QUALCOMM_INNOVATION_CENTER_INC_QUIC, "Qualcomm Innovation Center, Inc. (QuIC)");
map.put(JOHNSON_CONTROLS_INC, "Johnson Controls, Inc.");
map.put(STARKEY_LABORATORIES_INC, "Starkey Laboratories Inc.");
map.put(SPOWER_ELECTRONICS_LIMITED, "S-Power Electronics Limited");
map.put(ACE_SENSOR_INC, "Ace Sensor Inc");
map.put(APLIX_CORPORATION, "Aplix Corporation");
map.put(AAMP_OF_AMERICA, "AAMP of America");
map.put(STALMART_TECHNOLOGY_LIMITED, "Stalmart Technology Limited");
map.put(AMICCOM_ELECTRONICS_CORPORATION, "AMICCOM Electronics Corporation");
map.put(SHENZHEN_EXCELSECU_DATA_TECHNOLOGY_COLTD, "Shenzhen Excelsecu Data Technology Co.,Ltd");
map.put(GENEQ_INC, "Geneq Inc.");
map.put(ADIDAS_AG, "adidas AG");
map.put(LG_ELECTRONICS, "LG Electronics");
map.put(ONSET_COMPUTER_CORPORATION, "Onset Computer Corporation");
map.put(SELFLY_BV, "Selfly BV");
map.put(QUUPPA_OY, "Quuppa Oy.");
map.put(GELO_INC, "GeLo Inc");
map.put(EVLUMA, "Evluma");
map.put(MC10, "MC10");
map.put(BINAURIC_SE, "Binauric SE");
map.put(BEATS_ELECTRONICS, "Beats Electronics");
map.put(MICROCHIP_TECHNOLOGY_INC, "Microchip Technology Inc.");
map.put(ELGATO_SYSTEMS_GMBH, "Elgato Systems GmbH");
map.put(ARCHOS_SA, "ARCHOS SA");
map.put(DEXCOM_INC, "Dexcom, Inc.");
map.put(POLAR_ELECTRO_EUROPE_BV, "Polar Electro Europe B.V.");
map.put(DIALOG_SEMICONDUCTOR_BV, "Dialog Semiconductor B.V.");
map.put(TAIXINGBANG_TECHNOLOGY_HK_CO_LTD, "Taixingbang Technology (HK) Co,. LTD.");
map.put(KAWANTECH, "Kawantech");
map.put(AUSTCO_COMMUNICATION_SYSTEMS, "Austco Communication Systems");
map.put(TIMEX_GROUP_USA_INC, "Timex Group USA, Inc.");
map.put(QUALCOMM_TECHNOLOGIES_INC, "Qualcomm Technologies, Inc.");
map.put(QUALCOMM_CONNECTED_EXPERIENCES_INC, "Qualcomm Connected Experiences, Inc.");
map.put(VOYETRA_TURTLE_BEACH, "Voyetra Turtle Beach");
map.put(TXTR_GMBH, "txtr GmbH");
map.put(BIOSENTRONICS, "Biosentronics");
map.put(PROCTER_GAMBLE, "Procter & Gamble");
map.put(HOSIDEN_CORPORATION, "Hosiden Corporation");
map.put(MUZIK_LLC, "Muzik LLC");
map.put(MISFIT_WEARABLES_CORP, "Misfit Wearables Corp");
map.put(GOOGLE, "Google");
map.put(DANLERS_LTD, "Danlers Ltd");
map.put(SEMILINK_INC, "Semilink Inc");
map.put(INMUSIC_BRANDS_INC, "inMusic Brands, Inc");
map.put(LS_RESEARCH_INC, "L.S. Research Inc.");
map.put(EDEN_SOFTWARE_CONSULTANTS_LTD, "Eden Software Consultants Ltd.");
map.put(FRESHTEMP, "Freshtemp");
map.put(KS_TECHNOLOGIES, "KS Technologies");
map.put(ACTS_TECHNOLOGIES, "ACTS Technologies");
map.put(VTRACK_SYSTEMS, "Vtrack Systems");
map.put(NIELSENKELLERMAN_COMPANY, "Nielsen-Kellerman Company");
map.put(SERVER_TECHNOLOGY_INC, "Server Technology, Inc.");
map.put(BIORESEARCH_ASSOCIATES, "BioResearch Associates");
map.put(JOLLY_LOGIC_LLC, "Jolly Logic, LLC");
map.put(ABOVE_AVERAGE_OUTCOMES_INC, "Above Average Outcomes, Inc.");
map.put(BITSPLITTERS_GMBH, "Bitsplitters GmbH");
map.put(PAYPAL_INC, "PayPal, Inc.");
map.put(WITRON_TECHNOLOGY_LIMITED, "Witron Technology Limited");
map.put(MORSE_PROJECT_INC, "Morse Project Inc.");
map.put(KENT_DISPLAYS_INC, "Kent Displays Inc.");
map.put(NAUTILUS_INC, "Nautilus Inc.");
map.put(SMARTIFIER_OY, "Smartifier Oy");
map.put(ELCOMETER_LIMITED, "Elcometer Limited");
map.put(VSN_TECHNOLOGIES_INC, "VSN Technologies Inc.");
map.put(ACEUNI_CORP_LTD, "AceUni Corp., Ltd.");
map.put(STICKNFIND, "StickNFind");
map.put(CRYSTAL_CODE_AB, "Crystal Code AB");
map.put(KOUKAAM_AS, "KOUKAAM a.s.");
map.put(DELPHI_CORPORATION, "Delphi Corporation");
map.put(VALENCETECH_LIMITED, "ValenceTech Limited");
map.put(RESERVED, "Reserved");
map.put(TYPO_PRODUCTS_LLC, "Typo Products, LLC");
map.put(TOMTOM_INTERNATIONAL_BV, "TomTom International BV");
map.put(FUGOO_INC, "Fugoo, Inc");
map.put(KEISER_CORPORATION, "Keiser Corporation");
map.put(BANG_OLUFSEN_A_S, "Bang & Olufsen A/S");
map.put(PLUS_LOCATIONS_SYSTEMS_PTY_LTD, "PLUS Locations Systems Pty Ltd");
map.put(UBIQUITOUS_COMPUTING_TECHNOLOGY_CORPORATION, "Ubiquitous Computing Technology Corporation");
map.put(INNOVATIVE_YACHTTER_SOLUTIONS, "Innovative Yachtter Solutions");
map.put(WILLIAM_DEMANT_HOLDING_A_S, "William Demant Holding A/S");
map.put(CHICONY_ELECTRONICS_CO_LTD, "Chicony Electronics Co., Ltd.");
map.put(ATUS_BV, "Atus BV");
map.put(CODEGATE_LTD, "Codegate Ltd.");
map.put(ERI_INC, "ERi, Inc.");
map.put(TRANSDUCERS_DIRECT_LLC, "Transducers Direct, LLC");
map.put(FUJITSU_TEN_LIMITED, "Fujitsu Ten Limited");
map.put(AUDI_AG, "Audi AG");
map.put(HISILICON_TECHNOLOGIES_CO_LTD, "HiSilicon Technologies Co., Ltd.");
map.put(NIPPON_SEIKI_CO_LTD, "Nippon Seiki Co., Ltd.");
map.put(STEELSERIES_APS, "Steelseries ApS");
map.put(VYZYBL_INC, "vyzybl Inc.");
map.put(OPENBRAIN_TECHNOLOGIES_CO_LTD, "Openbrain Technologies, Co., Ltd.");
map.put(XENSR, "Xensr");
map.put(ESOLUTIONS, "e.solutions");
map.put(ONE_OAK_TECHNOLOGIES, "1OAK Technologies");
map.put(WIMOTO_TECHNOLOGIES_INC, "Wimoto Technologies Inc");
map.put(RADIUS_NETWORKS_INC, "Radius Networks, Inc.");
map.put(WIZE_TECHNOLOGY_CO_LTD, "Wize Technology Co., Ltd.");
map.put(QUALCOMM_LABS_INC, "Qualcomm Labs, Inc.");
map.put(ARUBA_NETWORKS, "Aruba Networks");
map.put(BAIDU, "Baidu");
map.put(ARENDI_AG, "Arendi AG");
map.put(SKODA_AUTO_AS, "Skoda Auto a.s.");
map.put(VOLKSWAGON_AG, "Volkswagon AG");
map.put(PORSCHE_AG, "Porsche AG");
map.put(SINO_WEALTH_ELECTRONIC_LTD, "Sino Wealth Electronic Ltd.");
map.put(AIRTURN_INC, "AirTurn, Inc.");
map.put(KINSA_INC, "Kinsa, Inc.");
map.put(HID_GLOBAL, "HID Global");
map.put(SEAT_ES, "SEAT es");
map.put(PROMETHEAN_LTD, "Promethean Ltd.");
map.put(SALUTICA_ALLIED_SOLUTIONS, "Salutica Allied Solutions");
map.put(GPSI_GROUP_PTY_LTD, "GPSI Group Pty Ltd");
map.put(NIMBLE_DEVICES_OY, "Nimble Devices Oy");
map.put(CHANGZHOU_YONGSE_INFOTECH_CO_LTD, "Changzhou Yongse Infotech Co., Ltd");
map.put(SPORTIQ, "SportIQ");
map.put(TEMEC_INSTRUMENTS_BV, "TEMEC Instruments B.V.");
map.put(SONY_CORPORATION, "Sony Corporation");
map.put(ASSA_ABLOY, "ASSA ABLOY");
map.put(CLARION_CO_LTD, "Clarion Co., Ltd.");
map.put(WAREHOUSE_INNOVATIONS, "Warehouse Innovations");
map.put(CYPRESS_SEMICONDUCTOR_CORPORATION, "Cypress Semiconductor Corporation");
map.put(MADS_INC, "MADS Inc");
map.put(BLUE_MAESTRO_LIMITED, "Blue Maestro Limited");
map.put(RESOLUTION_PRODUCTS_INC, "Resolution Products, Inc.");
map.put(AIREWEAR_LLC, "Airewear LLC");
map.put(ETC_SP_ZOO, "ETC sp. z.o.o.");
map.put(PRESTIGIO_PLAZA_LTD, "Prestigio Plaza Ltd.");
return map;
}
}

View File

@@ -0,0 +1,380 @@
package uk.co.alt236.bluetoothlelib.resolvers;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* The UUIDS have been collected from the following sources:
* <p>
* - http://developer.nokia.com/community/wiki/Bluetooth_Services_for_Windows_Phone
* - The Bluez project
*
* @author Alexandros Schillings
*/
public class GattAttributeResolver {
public static final String BASE_GUID = "00000000-0000-1000-8000-00805f9b34fb";
public static final String SERVICE_DISCOVERY_PROTOCOL_SDP = "00000001-0000-1000-8000-00805f9b34fb";
public static final String USER_DATAGRAM_PROTOCOL_UDP = "00000002-0000-1000-8000-00805f9b34fb";
public static final String RADIO_FREQUENCY_COMMUNICATION_PROTOCOL_RFCOMM = "00000003-0000-1000-8000-00805f9b34fb";
public static final String TCP = "00000004-0000-1000-8000-00805f9b34fb";
public static final String TCSBIN = "00000005-0000-1000-8000-00805f9b34fb";
public static final String TCSAT = "00000006-0000-1000-8000-00805f9b34fb";
public static final String OBJECT_EXCHANGE_PROTOCOL_OBEX = "00000008-0000-1000-8000-00805f9b34fb";
public static final String IP = "00000009-0000-1000-8000-00805f9b34fb";
public static final String FTP = "0000000a-0000-1000-8000-00805f9b34fb";
public static final String HTTP = "0000000c-0000-1000-8000-00805f9b34fb";
public static final String WSP = "0000000e-0000-1000-8000-00805f9b34fb";
public static final String BNEP_SVC = "0000000f-0000-1000-8000-00805f9b34fb";
public static final String UPNP_PROTOCOL = "00000010-0000-1000-8000-00805f9b34fb";
public static final String HIDP = "00000011-0000-1000-8000-00805f9b34fb";
public static final String HARDCOPY_CONTROL_CHANNEL_PROTOCOL = "00000012-0000-1000-8000-00805f9b34fb";
public static final String HARDCOPY_DATA_CHANNEL_PROTOCOL = "00000014-0000-1000-8000-00805f9b34fb";
public static final String HARDCOPY_NOTIFICATION_PROTOCOL = "00000016-0000-1000-8000-00805f9b34fb";
public static final String VCTP_PROTOCOL = "00000017-0000-1000-8000-00805f9b34fb";
public static final String VDTP_PROTOCOL = "00000019-0000-1000-8000-00805f9b34fb";
public static final String CMPT_PROTOCOL = "0000001b-0000-1000-8000-00805f9b34fb";
public static final String UDI_C_PLANE_PROTOCOL = "0000001d-0000-1000-8000-00805f9b34fb";
public static final String MCAP_CONTROL_CHANNEL = "0000001e-0000-1000-8000-00805f9b34fb";
public static final String MCAP_DATA_CHANNEL = "0000001f-0000-1000-8000-00805f9b34fb";
public static final String L2CAP = "00000100-0000-1000-8000-00805f9b34fb";
public static final String SERVICE_DISCOVERY_SERVER = "00001000-0000-1000-8000-00805f9b34fb";
public static final String BROWSE_GROUP_DESCRIPTOR = "00001001-0000-1000-8000-00805f9b34fb";
public static final String PUBLIC_BROWSE_GROUP = "00001002-0000-1000-8000-00805f9b34fb";
public static final String SPP = "00001101-0000-1000-8000-00805f9b34fb";
public static final String LAN_ACCESS_USING_PPP = "00001102-0000-1000-8000-00805f9b34fb";
public static final String DUN_GW = "00001103-0000-1000-8000-00805f9b34fb";
public static final String OBEX_SYNC = "00001104-0000-1000-8000-00805f9b34fb";
public static final String OBEX_OBJECT_PUSH = "00001105-0000-1000-8000-00805f9b34fb";
public static final String OBEX_FILE_TRANSFER = "00001106-0000-1000-8000-00805f9b34fb";
public static final String IRMC_SYNC_COMMAND = "00001107-0000-1000-8000-00805f9b34fb";
public static final String HSP_HS = "00001108-0000-1000-8000-00805f9b34fb";
public static final String CORDLESS_TELEPHONY = "00001109-0000-1000-8000-00805f9b34fb";
public static final String AUDIO_SOURCE = "0000110a-0000-1000-8000-00805f9b34fb";
public static final String AUDIO_SINK = "0000110b-0000-1000-8000-00805f9b34fb";
public static final String AV_REMOTE_CONTROL_TARGET = "0000110c-0000-1000-8000-00805f9b34fb";
public static final String ADVANCED_AUDIO = "0000110d-0000-1000-8000-00805f9b34fb";
public static final String AVRCP_REMOTE = "0000110e-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_CONFERENCING = "0000110f-0000-1000-8000-00805f9b34fb";
public static final String INTERCOM = "00001110-0000-1000-8000-00805f9b34fb";
public static final String FAX = "00001111-0000-1000-8000-00805f9b34fb";
public static final String HEADSET_PROFILE_HSP_AUDIO_GATEWAY = "00001112-0000-1000-8000-00805f9b34fb";
public static final String WAP = "00001113-0000-1000-8000-00805f9b34fb";
public static final String WAP_CLIENT = "00001114-0000-1000-8000-00805f9b34fb";
public static final String PANU = "00001115-0000-1000-8000-00805f9b34fb";
public static final String NAP = "00001116-0000-1000-8000-00805f9b34fb";
public static final String GN = "00001117-0000-1000-8000-00805f9b34fb";
public static final String DIRECT_PRINTING = "00001118-0000-1000-8000-00805f9b34fb";
public static final String REFERENCE_PRINTING = "00001119-0000-1000-8000-00805f9b34fb";
public static final String IMAGING = "0000111a-0000-1000-8000-00805f9b34fb";
public static final String IMAGING_RESPONDER = "0000111b-0000-1000-8000-00805f9b34fb";
public static final String IMAGING_AUTOMATIC_ARCHIVE = "0000111c-0000-1000-8000-00805f9b34fb";
public static final String IMAGING_REFERENCE_OBJECTS = "0000111d-0000-1000-8000-00805f9b34fb";
public static final String HANDS_FREE_PROFILE_HFP = "0000111e-0000-1000-8000-00805f9b34fb";
public static final String HANDS_FREE_PROFILE_HFP_AUDIO_GATEWAY = "0000111f-0000-1000-8000-00805f9b34fb";
public static final String DIRECT_PRINTING_REFERENCE_OBJECTS = "00001120-0000-1000-8000-00805f9b34fb";
public static final String REFLECTED_UI = "00001121-0000-1000-8000-00805f9b34fb";
public static final String BASIC_PRINTING = "00001122-0000-1000-8000-00805f9b34fb";
public static final String PRINTING_STATUS = "00001123-0000-1000-8000-00805f9b34fb";
public static final String HID = "00001124-0000-1000-8000-00805f9b34fb";
public static final String HARDCOPY_CABLE_REPLACEMENT = "00001125-0000-1000-8000-00805f9b34fb";
public static final String HCR_PRINT = "00001126-0000-1000-8000-00805f9b34fb";
public static final String HCR_SCAN = "00001127-0000-1000-8000-00805f9b34fb";
public static final String COMMON_ISDN_ACCESS = "00001128-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_CONFERENCING_GATEWAY = "00001129-0000-1000-8000-00805f9b34fb";
public static final String UDIMT = "0000112a-0000-1000-8000-00805f9b34fb";
public static final String UDITA = "0000112b-0000-1000-8000-00805f9b34fb";
public static final String AUDIO_VIDEO = "0000112c-0000-1000-8000-00805f9b34fb";
public static final String SIM_ACCESS = "0000112d-0000-1000-8000-00805f9b34fb";
public static final String OBEX_PCE = "0000112e-0000-1000-8000-00805f9b34fb";
public static final String OBEX_PSE = "0000112f-0000-1000-8000-00805f9b34fb";
public static final String OBEX_PBAP = "00001130-0000-1000-8000-00805f9b34fb";
public static final String OBEX_MAS = "00001132-0000-1000-8000-00805f9b34fb";
public static final String OBEX_MNS = "00001133-0000-1000-8000-00805f9b34fb";
public static final String OBEX_MAP = "00001134-0000-1000-8000-00805f9b34fb";
public static final String PNP = "00001200-0000-1000-8000-00805f9b34fb";
public static final String GENERIC_NETWORKING = "00001201-0000-1000-8000-00805f9b34fb";
public static final String GENERIC_FILE_TRANSFER = "00001202-0000-1000-8000-00805f9b34fb";
public static final String GENERIC_AUDIO = "00001203-0000-1000-8000-00805f9b34fb";
public static final String GENERIC_TELEPHONY = "00001204-0000-1000-8000-00805f9b34fb";
public static final String UPNP = "00001205-0000-1000-8000-00805f9b34fb";
public static final String UPNP_IP = "00001206-0000-1000-8000-00805f9b34fb";
public static final String ESDP_UPNP_IP_PAN = "00001300-0000-1000-8000-00805f9b34fb";
public static final String ESDP_UPNP_IP_LAP = "00001301-0000-1000-8000-00805f9b34fb";
public static final String ESDP_UPNP_L2CAP = "00001302-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_DISTRIBUTION_PROFILE_VDP_SOURCE = "00001303-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_DISTRIBUTION_PROFILE_VDP_SINK = "00001304-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_DISTRIBUTION_PROFILE_VDP = "00001305-0000-1000-8000-00805f9b34fb";
public static final String HEALTH_DEVICE_PROFILE_HDP = "00001400-0000-1000-8000-00805f9b34fb";
public static final String HEALTH_DEVICE_PROFILE_HDP_SOURCE = "00001401-0000-1000-8000-00805f9b34fb";
public static final String HEALTH_DEVICE_PROFILE_HDP_SINK = "00001402-0000-1000-8000-00805f9b34fb";
public static final String GAP = "00001800-0000-1000-8000-00805f9b34fb";
public static final String GATT = "00001801-0000-1000-8000-00805f9b34fb";
public static final String IMMEDIATE_ALERT = "00001802-0000-1000-8000-00805f9b34fb";
public static final String LINK_LOSS = "00001803-0000-1000-8000-00805f9b34fb";
public static final String TX_POWER = "00001804-0000-1000-8000-00805f9b34fb";
public static final String HEALTH_THERMOMETER = "00001809-0000-1000-8000-00805f9b34fb";
public static final String DEVICE_INFORMATION = "0000180a-0000-1000-8000-00805f9b34fb";
public static final String HEART_RATE = "0000180d-0000-1000-8000-00805f9b34fb";
public static final String CYCLING_SC = "00001816-0000-1000-8000-00805f9b34fb";
public static final String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
public static final String DEVICE_NAME = "00002a00-0000-1000-8000-00805f9b34fb";
public static final String APPEARANCE = "00002a01-0000-1000-8000-00805f9b34fb";
public static final String PERIPHERAL_PRIVACY_FLAG = "00002a02-0000-1000-8000-00805f9b34fb";
public static final String RECONNECTION_ADDRESS = "00002a03-0000-1000-8000-00805f9b34fb";
public static final String PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS = "00002a04-0000-1000-8000-00805f9b34fb";
public static final String SERVICE_CHANGED = "00002a05-0000-1000-8000-00805f9b34fb";
public static final String ALERT_LEVEL = "00002a06-0000-1000-8000-00805f9b34fb";
public static final String TX_POWER_LEVEL = "00002a07-0000-1000-8000-00805f9b34fb";
public static final String DATE_TIME = "00002a08-0000-1000-8000-00805f9b34fb";
public static final String DAY_OF_WEEK = "00002a09-0000-1000-8000-00805f9b34fb";
public static final String DAY_DATE_TIME = "00002a0a-0000-1000-8000-00805f9b34fb";
public static final String EXACT_TIME_256 = "00002a0c-0000-1000-8000-00805f9b34fb";
public static final String DST_OFFSET = "00002a0d-0000-1000-8000-00805f9b34fb";
public static final String TIME_ZONE = "00002a0e-0000-1000-8000-00805f9b34fb";
public static final String LOCAL_TIME_INFORMATION = "00002a0f-0000-1000-8000-00805f9b34fb";
public static final String TIME_WITH_DST = "00002a11-0000-1000-8000-00805f9b34fb";
public static final String TIME_ACCURACY = "00002a12-0000-1000-8000-00805f9b34fb";
public static final String TIME_SOURCE = "00002a13-0000-1000-8000-00805f9b34fb";
public static final String REFERENCE_TIME_INFORMATION = "00002a14-0000-1000-8000-00805f9b34fb";
public static final String TIME_UPDATE_CONTROL_POINT = "00002a16-0000-1000-8000-00805f9b34fb";
public static final String TIME_UPDATE_STATE = "00002a17-0000-1000-8000-00805f9b34fb";
public static final String TEMPERATURE_MEASUREMENT = "00002a1c-0000-1000-8000-00805f9b34fb";
public static final String TEMPERATURE_TYPE = "00002a1d-0000-1000-8000-00805f9b34fb";
public static final String INTERMEDIATE_TEMPERATURE = "00002a1e-0000-1000-8000-00805f9b34fb";
public static final String MEASUREMENT_INTERVAL = "00002a21-0000-1000-8000-00805f9b34fb";
public static final String SYSTEM_ID = "00002a23-0000-1000-8000-00805f9b34fb";
public static final String MODEL_NUMBER_STRING = "00002a24-0000-1000-8000-00805f9b34fb";
public static final String SERIAL_NUMBER_STRING = "00002a25-0000-1000-8000-00805f9b34fb";
public static final String FIRMWARE_REVISION_STRING = "00002a26-0000-1000-8000-00805f9b34fb";
public static final String HARDWARE_REVISION_STRING = "00002a27-0000-1000-8000-00805f9b34fb";
public static final String SOFTWARE_REVISION_STRING = "00002a28-0000-1000-8000-00805f9b34fb";
public static final String MANUFACTURER_NAME_STRING = "00002a29-0000-1000-8000-00805f9b34fb";
public static final String IEEE_1107320601_REGULATORY = "00002a2a-0000-1000-8000-00805f9b34fb";
public static final String CURRENT_TIME = "00002a2b-0000-1000-8000-00805f9b34fb";
public static final String BLOOD_PRESSURE_MEASUREMENT = "00002a35-0000-1000-8000-00805f9b34fb";
public static final String INTERMEDIATE_CUFF_PRESSURE = "00002a36-0000-1000-8000-00805f9b34fb";
public static final String HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb";
public static final String BODY_SENSOR_LOCATION = "00002a38-0000-1000-8000-00805f9b34fb";
public static final String HEART_RATE_CONTROL_POINT = "00002a39-0000-1000-8000-00805f9b34fb";
public static final String ALERT_STATUS = "00002a3f-0000-1000-8000-00805f9b34fb";
public static final String RINGER_CONTROL_POINT = "00002a40-0000-1000-8000-00805f9b34fb";
public static final String RINGER_SETTING = "00002a41-0000-1000-8000-00805f9b34fb";
public static final String ALERT_CATEGORY_ID_BIT_MASK = "00002a42-0000-1000-8000-00805f9b34fb";
public static final String ALERT_CATEGORY_ID = "00002a43-0000-1000-8000-00805f9b34fb";
public static final String ALERT_NOTIFICATION_CONTROL_POINT = "00002a44-0000-1000-8000-00805f9b34fb";
public static final String UNREAD_ALERT_STATUS = "00002a45-0000-1000-8000-00805f9b34fb";
public static final String NEW_ALERT = "00002a46-0000-1000-8000-00805f9b34fb";
public static final String SUPPORTED_NEW_ALERT_CATEGORY = "00002a47-0000-1000-8000-00805f9b34fb";
public static final String SUPPORTED_UNREAD_ALERT_CATEGORY = "00002a48-0000-1000-8000-00805f9b34fb";
public static final String BLOOD_PRESSURE_FEATURE = "00002a49-0000-1000-8000-00805f9b34fb";
public static final String PNPID = "00002a50-0000-1000-8000-00805f9b34fb";
public static final String SC_CONTROL_POINT = "00002a55-0000-1000-8000-00805f9b34fb";
public static final String CSC_MEASUREMENT = "00002a5b-0000-1000-8000-00805f9b34fb";
public static final String CSC_FEATURE = "00002a5c-0000-1000-8000-00805f9b34fb";
public static final String SENSOR_LOCATION = "00002a5d-0000-1000-8000-00805f9b34fb";
public static final String ACTIVESYNC = "831c4071-7bc8-4a9c-a01c-15df25a4adbc";
public static final String ESTIMOTE_SERVICE = "b9403000-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_UUID = "b9403003-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_MAJOR = "b9403001-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_MINOR = "b9403002-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_BATTERY = "b9403041-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_TEMPERATURE = "b9403021-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_POWER = "b9403011-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_ADVERTISING_INTERVAL = "b9403012-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_VERSION_SERVICE = "b9404000-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_SOFTWARE_VERSION = "b9404001-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_HARDWARE_VERSION = "b9404002-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_AUTHENTICATION_SERVICE = "b9402000-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_ADVERTISING_SEED = "b9402001-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_ADVERTISING_VECTOR = "b9402002-f5f8-466e-aff9-25556b57fe6d";
private final static Map<String, String> sGattAttributesMap = populateGattAttributesMap();
public static String getAttributeName(final String uuid, final String fallback) {
final String name = sGattAttributesMap.get(uuid.toLowerCase(Locale.US));
return name == null ? fallback : name;
}
private static Map<String, String> populateGattAttributesMap() {
final Map<String, String> map = new HashMap<>();
map.put(BASE_GUID , "Base GUID");
map.put(SERVICE_DISCOVERY_PROTOCOL_SDP , "Service Discovery Protocol (SDP)");
map.put(USER_DATAGRAM_PROTOCOL_UDP , "User Datagram Protocol (UDP)");
map.put(RADIO_FREQUENCY_COMMUNICATION_PROTOCOL_RFCOMM , "Radio Frequency Communication Protocol (RFCOMM)");
map.put(TCP , "TCP");
map.put(TCSBIN , "TCSBIN");
map.put(TCSAT , "TCSAT");
map.put(OBJECT_EXCHANGE_PROTOCOL_OBEX , "Object Exchange Protocol (OBEX)");
map.put(IP , "IP");
map.put(FTP , "FTP");
map.put(HTTP , "HTTP");
map.put(WSP , "WSP");
map.put(BNEP_SVC , "BNEP_SVC");
map.put(UPNP_PROTOCOL , "UPNP Protocol");
map.put(HIDP , "HIDP");
map.put(HARDCOPY_CONTROL_CHANNEL_PROTOCOL , "Hardcopy Control Channel Protocol");
map.put(HARDCOPY_DATA_CHANNEL_PROTOCOL , "Hardcopy Data Channel Protocol");
map.put(HARDCOPY_NOTIFICATION_PROTOCOL , "Hardcopy Notification Protocol");
map.put(VCTP_PROTOCOL , "VCTP Protocol");
map.put(VDTP_PROTOCOL , "VDTP Protocol");
map.put(CMPT_PROTOCOL , "CMPT Protocol");
map.put(UDI_C_PLANE_PROTOCOL , "UDI C Plane Protocol");
map.put(MCAP_CONTROL_CHANNEL , "MCAP Control Channel");
map.put(MCAP_DATA_CHANNEL , "MCAP Data Channel");
map.put(L2CAP , "L2CAP");
map.put(SERVICE_DISCOVERY_SERVER , "Service Discovery Server");
map.put(BROWSE_GROUP_DESCRIPTOR , "Browse Group Descriptor");
map.put(PUBLIC_BROWSE_GROUP , "Public Browse Group");
map.put(SPP , "SPP");
map.put(LAN_ACCESS_USING_PPP , "LAN Access Using PPP");
map.put(DUN_GW , "DUN_GW");
map.put(OBEX_SYNC , "OBEX_SYNC");
map.put(OBEX_OBJECT_PUSH , "OBEX Object Push");
map.put(OBEX_FILE_TRANSFER , "OBEX File Transfer");
map.put(IRMC_SYNC_COMMAND , "IrMC Sync Command");
map.put(HSP_HS , "HSP_HS");
map.put(CORDLESS_TELEPHONY , "Cordless Telephony");
map.put(AUDIO_SOURCE , "Audio Source");
map.put(AUDIO_SINK , "Audio Sink");
map.put(AV_REMOTE_CONTROL_TARGET , "AV Remote Control Target");
map.put(ADVANCED_AUDIO , "ADVANCED_AUDIO");
map.put(AVRCP_REMOTE , "AVRCP_REMOTE");
map.put(VIDEO_CONFERENCING , "Video Conferencing");
map.put(INTERCOM , "Intercom");
map.put(FAX , "FAX");
map.put(HEADSET_PROFILE_HSP_AUDIO_GATEWAY , "Headset Profile (HSP) - Audio Gateway");
map.put(WAP , "WAP");
map.put(WAP_CLIENT , "WAP Client");
map.put(PANU , "PANU");
map.put(NAP , "NAP");
map.put(GN , "GN");
map.put(DIRECT_PRINTING , "Direct Printing");
map.put(REFERENCE_PRINTING , "Reference Printing");
map.put(IMAGING , "Imaging");
map.put(IMAGING_RESPONDER , "Imaging Responder");
map.put(IMAGING_AUTOMATIC_ARCHIVE , "Imaging Automatic Archive");
map.put(IMAGING_REFERENCE_OBJECTS , "Imaging Reference Objects");
map.put(HANDS_FREE_PROFILE_HFP , "Hands Free Profile (HFP)");
map.put(HANDS_FREE_PROFILE_HFP_AUDIO_GATEWAY , "Hands Free Profile (HFP) Audio Gateway");
map.put(DIRECT_PRINTING_REFERENCE_OBJECTS , "Direct Printing Reference Objects");
map.put(REFLECTED_UI , "Reflected UI");
map.put(BASIC_PRINTING , "Basic Printing");
map.put(PRINTING_STATUS , "Printing Status");
map.put(HID , "HID");
map.put(HARDCOPY_CABLE_REPLACEMENT , "Hardcopy Cable Replacement");
map.put(HCR_PRINT , "HCR Print");
map.put(HCR_SCAN , "HCR Scan");
map.put(COMMON_ISDN_ACCESS , "Common ISDN Access");
map.put(VIDEO_CONFERENCING_GATEWAY , "Video Conferencing Gateway");
map.put(UDIMT , "UDIMT");
map.put(UDITA , "UDITA");
map.put(AUDIO_VIDEO , "Audio Video");
map.put(SIM_ACCESS , "SIM Access");
map.put(OBEX_PCE , "OBEX PCE");
map.put(OBEX_PSE , "OBEX PSE");
map.put(OBEX_PBAP , "OBEX PBAP");
map.put(OBEX_MAS , "OBEX MAS");
map.put(OBEX_MNS , "OBEX MNS");
map.put(OBEX_MAP , "OBEX MAP");
map.put(PNP , "PNP");
map.put(GENERIC_NETWORKING , "Generic Networking");
map.put(GENERIC_FILE_TRANSFER , "Generic File Transfer");
map.put(GENERIC_AUDIO , "Generic Audio");
map.put(GENERIC_TELEPHONY , "Generic Telephony");
map.put(UPNP , "UPNP");
map.put(UPNP_IP , "UPNP IP");
map.put(ESDP_UPNP_IP_PAN , "ESDP UPnP IP PAN");
map.put(ESDP_UPNP_IP_LAP , "ESDP UPnP IP LAP");
map.put(ESDP_UPNP_L2CAP , "ESDP Upnp L2CAP");
map.put(VIDEO_DISTRIBUTION_PROFILE_VDP_SOURCE , "Video Distribution Profile (VDP) - Source");
map.put(VIDEO_DISTRIBUTION_PROFILE_VDP_SINK , "Video Distribution Profile (VDP) - Sink");
map.put(VIDEO_DISTRIBUTION_PROFILE_VDP , "Video Distribution Profile (VDP)");
map.put(HEALTH_DEVICE_PROFILE_HDP , "Health Device Profile (HDP)");
map.put(HEALTH_DEVICE_PROFILE_HDP_SOURCE , "Health Device Profile (HDP) - Source");
map.put(HEALTH_DEVICE_PROFILE_HDP_SINK , "Health Device Profile (HDP) - Sink");
map.put(GAP , "GAP");
map.put(GATT , "GATT");
map.put(IMMEDIATE_ALERT , "IMMEDIATE_ALERT");
map.put(LINK_LOSS , "LINK_LOSS");
map.put(TX_POWER , "TX_POWER");
map.put(HEALTH_THERMOMETER , "Health Thermometer");
map.put(DEVICE_INFORMATION , "Device Information");
map.put(HEART_RATE , "HEART_RATE");
map.put(CYCLING_SC , "CYCLING_SC");
map.put(CLIENT_CHARACTERISTIC_CONFIG , "CLIENT_CHARACTERISTIC_CONFIG");
map.put(DEVICE_NAME , "Device Name");
map.put(APPEARANCE , "Appearance");
map.put(PERIPHERAL_PRIVACY_FLAG , "Peripheral Privacy Flag");
map.put(RECONNECTION_ADDRESS , "Reconnection Address");
map.put(PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS , "Peripheral Preferred Connection Parameters");
map.put(SERVICE_CHANGED , "Service Changed");
map.put(ALERT_LEVEL , "Alert Level");
map.put(TX_POWER_LEVEL , "Tx Power Level");
map.put(DATE_TIME , "Date Time");
map.put(DAY_OF_WEEK , "Day of Week");
map.put(DAY_DATE_TIME , "Day Date Time");
map.put(EXACT_TIME_256 , "Exact Time 256");
map.put(DST_OFFSET , "DST Offset");
map.put(TIME_ZONE , "Time Zone");
map.put(LOCAL_TIME_INFORMATION , "Local Time Information");
map.put(TIME_WITH_DST , "Time with DST");
map.put(TIME_ACCURACY , "Time Accuracy");
map.put(TIME_SOURCE , "Time Source");
map.put(REFERENCE_TIME_INFORMATION , "Reference Time Information");
map.put(TIME_UPDATE_CONTROL_POINT , "Time Update Control Point");
map.put(TIME_UPDATE_STATE , "Time Update State");
map.put(TEMPERATURE_MEASUREMENT , "Temperature Measurement");
map.put(TEMPERATURE_TYPE , "Temperature Type");
map.put(INTERMEDIATE_TEMPERATURE , "Intermediate Temperature");
map.put(MEASUREMENT_INTERVAL , "Measurement Interval");
map.put(SYSTEM_ID , "System ID");
map.put(MODEL_NUMBER_STRING , "Model Number String");
map.put(SERIAL_NUMBER_STRING , "Serial Number String");
map.put(FIRMWARE_REVISION_STRING , "Firmware Revision String");
map.put(HARDWARE_REVISION_STRING , "Hardware Revision String");
map.put(SOFTWARE_REVISION_STRING , "Software Revision String");
map.put(MANUFACTURER_NAME_STRING , "Manufacturer Name String");
map.put(IEEE_1107320601_REGULATORY , "IEEE 11073-20601 Regulatory");
map.put(CURRENT_TIME , "Current Time");
map.put(BLOOD_PRESSURE_MEASUREMENT , "Blood Pressure Measurement");
map.put(INTERMEDIATE_CUFF_PRESSURE , "Intermediate Cuff Pressure");
map.put(HEART_RATE_MEASUREMENT , "Heart Rate Measurement");
map.put(BODY_SENSOR_LOCATION , "Body Sensor Location");
map.put(HEART_RATE_CONTROL_POINT , "Heart Rate Control Point");
map.put(ALERT_STATUS , "Alert Status");
map.put(RINGER_CONTROL_POINT , "Ringer Control Point");
map.put(RINGER_SETTING , "Ringer Setting");
map.put(ALERT_CATEGORY_ID_BIT_MASK , "Alert Category ID Bit Mask");
map.put(ALERT_CATEGORY_ID , "Alert Category ID");
map.put(ALERT_NOTIFICATION_CONTROL_POINT , "Alert Notification Control Point");
map.put(UNREAD_ALERT_STATUS , "Unread Alert Status");
map.put(NEW_ALERT , "New Alert");
map.put(SUPPORTED_NEW_ALERT_CATEGORY , "Supported New Alert Category");
map.put(SUPPORTED_UNREAD_ALERT_CATEGORY , "Supported Unread Alert Category");
map.put(BLOOD_PRESSURE_FEATURE , "Blood Pressure Feature");
map.put(PNPID , "PNPID");
map.put(SC_CONTROL_POINT , "SC_CONTROL_POINT");
map.put(CSC_MEASUREMENT , "CSC_MEASUREMENT");
map.put(CSC_FEATURE , "CSC_FEATURE");
map.put(SENSOR_LOCATION , "SENSOR_LOCATION");
map.put(ACTIVESYNC , "ActiveSync");
map.put(ESTIMOTE_SERVICE , "Estimote Service");
map.put(ESTIMOTE_UUID , "Estimote UUID");
map.put(ESTIMOTE_MAJOR , "Estimote Major");
map.put(ESTIMOTE_MINOR , "Estimote Minor");
map.put(ESTIMOTE_BATTERY , "Estimote Battery");
map.put(ESTIMOTE_TEMPERATURE , "Estimote Temperature");
map.put(ESTIMOTE_POWER , "Estimote Power");
map.put(ESTIMOTE_ADVERTISING_INTERVAL , "Estimote Advertising Interval");
map.put(ESTIMOTE_VERSION_SERVICE , "Estimote Version Service");
map.put(ESTIMOTE_SOFTWARE_VERSION , "Estimote Software Version");
map.put(ESTIMOTE_HARDWARE_VERSION , "Estimote Hardware Version");
map.put(ESTIMOTE_AUTHENTICATION_SERVICE , "Estimote Authentication Service");
map.put(ESTIMOTE_ADVERTISING_SEED , "Estimote Advertising Seed");
map.put(ESTIMOTE_ADVERTISING_VECTOR , "Estimote Advertising Vector");
return map;
}
}

View File

@@ -0,0 +1,131 @@
package uk.co.alt236.bluetoothlelib.util;
import android.annotation.SuppressLint;
import android.util.SparseArray;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
public final class AdRecordUtils {
private AdRecordUtils(){
// TO AVOID INSTANTIATION
}
public static String getRecordDataAsString(final AdRecord nameRecord) {
if (nameRecord == null) {
return "";
}
return new String(nameRecord.getData());
}
public static byte[] getServiceData(final AdRecord serviceData) {
if (serviceData == null) {
return null;
}
if (serviceData.getType() != AdRecord.TYPE_SERVICE_DATA) return null;
final byte[] raw = serviceData.getData();
//Chop out the uuid
return Arrays.copyOfRange(raw, 2, raw.length);
}
public static int getServiceDataUuid(final AdRecord serviceData) {
if (serviceData == null) {
return -1;
}
if (serviceData.getType() != AdRecord.TYPE_SERVICE_DATA) return -1;
final byte[] raw = serviceData.getData();
//Find UUID data in byte array
int uuid = (raw[1] & 0xFF) << 8;
uuid += (raw[0] & 0xFF);
return uuid;
}
/*
* Read out all the AD structures from the raw scan record
*/
public static List<AdRecord> parseScanRecordAsList(final byte[] scanRecord) {
final List<AdRecord> records = new ArrayList<>();
int index = 0;
while (index < scanRecord.length) {
final int length = scanRecord[index++];
//Done once we run out of records
if (length == 0) break;
final int type = ByteUtils.getIntFromByte(scanRecord[index]);
//Done if our record isn't a valid type
if (type == 0) break;
final byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length);
records.add(new AdRecord(length, type, data));
//Advance
index += length;
}
return Collections.unmodifiableList(records);
}
@SuppressLint("UseSparseArrays")
public static Map<Integer, AdRecord> parseScanRecordAsMap(final byte[] scanRecord) {
final Map<Integer, AdRecord> records = new HashMap<>();
int index = 0;
while (index < scanRecord.length) {
final int length = scanRecord[index++];
//Done once we run out of records
if (length == 0) break;
final int type = ByteUtils.getIntFromByte(scanRecord[index]);
//Done if our record isn't a valid type
if (type == 0) break;
final byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length);
records.put(type, new AdRecord(length, type, data));
//Advance
index += length;
}
return Collections.unmodifiableMap(records);
}
public static SparseArray<AdRecord> parseScanRecordAsSparseArray(final byte[] scanRecord) {
final SparseArray<AdRecord> records = new SparseArray<>();
int index = 0;
while (index < scanRecord.length) {
final int length = scanRecord[index++];
//Done once we run out of records
if (length == 0) break;
final int type = ByteUtils.getIntFromByte(scanRecord[index]);
//Done if our record isn't a valid type
if (type == 0) break;
final byte[] data = Arrays.copyOfRange(scanRecord, index + 1, index + length);
records.put(type, new AdRecord(length, type, data));
//Advance
index += length;
}
return records;
}
}

View File

@@ -0,0 +1,128 @@
package uk.co.alt236.bluetoothlelib.util;
import java.nio.ByteBuffer;
public class ByteUtils {
/**
* The Constant HEXES.
*/
private static final String HEXES = "0123456789ABCDEF";
private ByteUtils(){
// TO AVOID INSTANTIATION
}
/**
* Gets a pretty representation of a Byte Array as a HEX String.
* <p>
* Sample output: [01, 30, FF, AA]
*
* @param array the array
* @return the string
*/
public static String byteArrayToHexString(final byte[] array) {
final StringBuilder sb = new StringBuilder();
boolean firstEntry = true;
sb.append('[');
for (final byte b : array) {
if (!firstEntry) {
sb.append(", ");
}
sb.append(HEXES.charAt((b & 0xF0) >> 4));
sb.append(HEXES.charAt((b & 0x0F)));
firstEntry = false;
}
sb.append(']');
return sb.toString();
}
/**
* Checks to see if a byte array starts with another byte array.
*
* @param array the array
* @param prefix the prefix
* @return true, if successful
*/
public static boolean doesArrayBeginWith(final byte[] array, final byte[] prefix) {
if (array.length < prefix.length) {
return false;
}
for (int i = 0; i < prefix.length; i++) {
if (array[i] != prefix[i]) {
return false;
}
}
return true;
}
/**
* Converts a byte array with a length of 2 into an int
*
* @param input the input
* @return the int from the array
*/
public static int getIntFrom2ByteArray(final byte[] input) {
final byte[] result = new byte[4];
result[0] = 0;
result[1] = 0;
result[2] = input[0];
result[3] = input[1];
return ByteUtils.getIntFromByteArray(result);
}
/**
* Converts a byte to an int, preserving the sign.
* <p>
* For example, FF will be converted to 255 and not -1.
*
* @param bite the byte
* @return the int from byte
*/
public static int getIntFromByte(final byte bite) {
return bite & 0xFF;
}
/**
* Converts a byte array to an int.
*
* @param bytes the bytes
* @return the int from byte array
*/
public static int getIntFromByteArray(final byte[] bytes) {
return ByteBuffer.wrap(bytes).getInt();
}
/**
* Converts a byte array to a long.
*
* @param bytes the bytes
* @return the long from byte array
*/
public static long getLongFromByteArray(final byte[] bytes) {
return ByteBuffer.wrap(bytes).getLong();
}
/**
* Inverts an byte array in place.
*
* @param array the array
*/
public static void invertArray(final byte[] array) {
final int size = array.length;
byte temp;
for (int i = 0; i < size / 2; i++) {
temp = array[i];
array[i] = array[size - 1 - i];
array[size - 1 - i] = temp;
}
}
}

View File

@@ -0,0 +1,20 @@
package uk.co.alt236.bluetoothlelib.util;
import java.util.LinkedHashMap;
import java.util.Map;
public class LimitedLinkHashMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = -5375660288461724925L;
private final int mMaxSize;
public LimitedLinkHashMap(final int maxSize) {
super(maxSize + 1, 1, false);
mMaxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(final Map.Entry<K, V> eldest) {
return this.size() > mMaxSize;
}
}

View File

@@ -0,0 +1,25 @@
package uk.co.alt236.bluetoothlelib.device.beacon;
import junit.framework.TestCase;
/**
*
*/
public class BeaconUtilsTest extends TestCase {
public void testGetBeaconTypeIBeacon() throws Exception {
assertEquals(BeaconType.IBEACON, BeaconUtils.getBeaconType(new byte[]{
0x4C, 0x00, 0x02, 0x15, 0x00, // <- Magic iBeacon header
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00
}));
}
public void testGetBeaconTypeInvalid() throws Exception {
assertEquals(BeaconType.NOT_A_BEACON, BeaconUtils.getBeaconType((byte[]) null));
assertEquals(BeaconType.NOT_A_BEACON, BeaconUtils.getBeaconType(new byte[0]));
assertEquals(BeaconType.NOT_A_BEACON, BeaconUtils.getBeaconType(new byte[25]));
}
}

View File

@@ -0,0 +1,39 @@
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
import junit.framework.TestCase;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconManufacturerData;
/**
*
*/
public class IBeaconManufacturerDataTest extends TestCase {
private static final byte[] NON_BEACON =
{2, 1, 26, 11, -1, 76, 0, 9, 6, 3, -32, -64, -88,
1, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
public void testNonIBeaconData() throws Exception{
try {
BeaconManufacturerData data = new IBeaconManufacturerData(NON_BEACON);
fail("Should have thrown an exception");
} catch (final IllegalArgumentException e){
// EXPECTED
}
try {
BeaconManufacturerData data = new IBeaconManufacturerData((byte[]) null);
fail("Should have thrown an exception");
} catch (final IllegalArgumentException e){
// EXPECTED
}
try {
BeaconManufacturerData data = new IBeaconManufacturerData(new byte[0]);
fail("Should have thrown an exception");
} catch (final IllegalArgumentException e){
// EXPECTED
}
}
}

View File

@@ -0,0 +1,32 @@
package uk.co.alt236.bluetoothlelib.device.beacon.ibeacon;
import junit.framework.TestCase;
/**
*
*/
public class IBeaconUtilsTest extends TestCase {
public void testCalculateUuidString() throws Exception {
assertEquals("00", IBeaconUtils.calculateUuidString(new byte[]{0}));
assertEquals("0a", IBeaconUtils.calculateUuidString(new byte[]{10}));
assertEquals("0f", IBeaconUtils.calculateUuidString(new byte[]{15}));
assertEquals("10", IBeaconUtils.calculateUuidString(new byte[]{16}));
assertEquals("7f", IBeaconUtils.calculateUuidString(new byte[]{127}));
assertEquals(
"00000000-0000-0000-0000-00",
IBeaconUtils.calculateUuidString(new byte[]{0,0,0,0,0,0,0,0,0,0,0}));
}
public void testGetDistanceDescriptor() throws Exception {
assertEquals(IBeaconDistanceDescriptor.UNKNOWN, IBeaconUtils.getDistanceDescriptor(-1));
assertEquals(IBeaconDistanceDescriptor.IMMEDIATE, IBeaconUtils.getDistanceDescriptor(0));
assertEquals(IBeaconDistanceDescriptor.IMMEDIATE, IBeaconUtils.getDistanceDescriptor(0.4));
assertEquals(IBeaconDistanceDescriptor.NEAR, IBeaconUtils.getDistanceDescriptor(0.5));
assertEquals(IBeaconDistanceDescriptor.NEAR, IBeaconUtils.getDistanceDescriptor(2.9));
assertEquals(IBeaconDistanceDescriptor.FAR, IBeaconUtils.getDistanceDescriptor(3));
}
}

View File

@@ -0,0 +1,20 @@
package uk.co.alt236.bluetoothlelib.resolvers;
import junit.framework.TestCase;
/**
*
*/
public class GattAttributeResolverTest extends TestCase {
private static final String UKNOWN = "unknown";
public void testGetAttributeName() throws Exception {
assertEquals(UKNOWN, GattAttributeResolver.getAttributeName("foo", UKNOWN));
assertEquals("Estimote Advertising Vector", GattAttributeResolver.getAttributeName("b9402002-f5f8-466e-aff9-25556b57fe6d", UKNOWN));
assertEquals("LINK_LOSS", GattAttributeResolver.getAttributeName("00001803-0000-1000-8000-00805f9b34fb", UKNOWN));
assertEquals("Base GUID", GattAttributeResolver.getAttributeName("00000000-0000-1000-8000-00805f9b34fb", UKNOWN));
assertEquals("PNPID", GattAttributeResolver.getAttributeName("00002a50-0000-1000-8000-00805f9b34fb", UKNOWN));
assertEquals("HTTP", GattAttributeResolver.getAttributeName("0000000c-0000-1000-8000-00805f9b34fb", UKNOWN));
}
}

View File

@@ -0,0 +1,58 @@
package uk.co.alt236.bluetoothlelib.util;
import junit.framework.TestCase;
import java.util.List;
import java.util.Map;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
/**
*
*/
public class AdRecordUtilsTest extends TestCase {
private static final byte[] NON_IBEACON =
{2, 1, 26, 11, -1, 76, 0, 9, 6, 3, -32, -64, -88,
1, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
public void testParseScanRecordAsList() throws Exception {
final List<AdRecord> adRecords = AdRecordUtils.parseScanRecordAsList(NON_IBEACON);
assertNotNull(adRecords);
assertEquals(2, adRecords.size());
int type = AdRecord.TYPE_FLAGS;
assertEquals(type, adRecords.get(0).getType());
assertEquals(2, adRecords.get(0).getLength());
type = AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA;
assertEquals(type, adRecords.get(1).getType());
assertEquals(11, adRecords.get(1).getLength());
}
public void testParseScanRecordAsMap() throws Exception {
final Map<Integer, AdRecord> adRecords = AdRecordUtils.parseScanRecordAsMap(NON_IBEACON);
assertNotNull(adRecords);
assertEquals(2, adRecords.size());
int type = AdRecord.TYPE_FLAGS;
assertEquals(type, adRecords.get(type).getType());
assertEquals(2, adRecords.get(type).getLength());
type = AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA;
assertEquals(type, adRecords.get(type).getType());
assertEquals(11, adRecords.get(type).getLength());
}
public void testParseScanRecordAsSparseArray() throws Exception {
//
// Cannot be tested here as it relies on Android code...
//
// final SparseArray<AdRecord> adRecords = AdRecordUtils.parseScanRecordAsSparseArray(NON_IBEACON);
// assertNotNull(adRecords);
// assertEquals(2, adRecords.size());
// assertEquals(AdRecord.TYPE_FLAGS, adRecords.get(AdRecord.TYPE_FLAGS).getType());
// assertEquals(AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA, adRecords.get(AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA).getType());
}
}

View File

@@ -0,0 +1,60 @@
package uk.co.alt236.bluetoothlelib.util;
import junit.framework.TestCase;
/**
*
*/
public class ByteUtilsTest extends TestCase {
public void testByteArrayToHexString() throws Exception {
assertEquals("[]", ByteUtils.byteArrayToHexString(new byte[0]));
final byte[] one = {1, 10, 15, 127};
assertEquals("[01, 0A, 0F, 7F]", ByteUtils.byteArrayToHexString(one));
}
public void testDoesArrayBeginWith() throws Exception {
// If the prefix is longer than the array,
// we automatically fail
byte[] array = new byte[10];
byte[] prefix = new byte[array.length * 2];
assertFalse(ByteUtils.doesArrayBeginWith(array, prefix));
array = new byte[]{1, 2, 3};
prefix = new byte[]{1, 3};
assertFalse(ByteUtils.doesArrayBeginWith(array, prefix));
array = new byte[10];
prefix = new byte[array.length];
assertTrue(ByteUtils.doesArrayBeginWith(array, prefix));
array = new byte[]{1, 2, 3};
prefix = new byte[]{1, 2};
assertTrue(ByteUtils.doesArrayBeginWith(array, prefix));
}
public void testGetIntFromByte() throws Exception {
byte bite = 127;
int integer = ByteUtils.getIntFromByte(bite);
assertEquals(127, integer);
bite = -1;
integer = ByteUtils.getIntFromByte(bite);
assertEquals(255, integer);
}
public void testInvertArray() throws Exception {
final byte[] original = {1, 2 ,3 ,4};
final byte[] out = new byte[original.length];
System.arraycopy( original, 0, out, 0, original.length);
ByteUtils.invertArray(out);
assertEquals(original[0], out[3]);
assertEquals(original[1], out[2]);
assertEquals(original[2], out[1]);
assertEquals(original[3], out[0]);
}
}

View File

@@ -1,395 +0,0 @@
package uk.co.alt236.bluetoothlelib.device;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecordStore;
import uk.co.alt236.bluetoothlelib.resolvers.BluetoothClassResolver;
import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
import uk.co.alt236.bluetoothlelib.util.LimitedLinkHashMap;
import android.bluetooth.BluetoothDevice;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
// TODO: Auto-generated Javadoc
/**
* This is a wrapper around the default BluetoothDevice object
* As BluetoothDevice is final it cannot be extended, so to get it you
* need to call {@link #getDevice()} method.
*
* @author Alexandros Schillings
*/
public class BluetoothLeDevice implements Parcelable{
private static final String PARCEL_EXTRA_BLUETOOTH_DEVICE = "bluetooth_device";
private static final String PARCEL_EXTRA_CURRENT_RSSI = "current_rssi";
private static final String PARCEL_EXTRA_CURRENT_TIMESTAMP = "current_timestamp";
private static final String PARCEL_EXTRA_DEVICE_RSSI_LOG = "device_rssi_log";
private static final String PARCEL_EXTRA_DEVICE_SCANRECORD = "device_scanrecord";
private static final String PARCEL_EXTRA_DEVICE_SCANRECORD_STORE = "device_scanrecord_store";
private static final String PARCEL_EXTRA_FIRST_RSSI = "device_first_rssi";
private static final String PARCEL_EXTRA_FIRST_TIMESTAMP = "first_timestamp";
private static final long LOG_INVALIDATION_THRESHOLD = 10 * 1000;
protected static final int MAX_RSSI_LOG_SIZE = 10;
private final AdRecordStore mRecordStore;
private final BluetoothDevice mDevice;
private final Map<Long, Integer> mRssiLog;
private final byte[] mScanRecord;
private final int mFirstRssi;
private final long mFirstTimestamp;
private int mCurrentRssi;
private long mCurrentTimestamp;
/** The Constant CREATOR. */
public static final Parcelable.Creator<BluetoothLeDevice> CREATOR = new Parcelable.Creator<BluetoothLeDevice>() {
public BluetoothLeDevice createFromParcel(Parcel in) {
return new BluetoothLeDevice(in);
}
public BluetoothLeDevice[] newArray(int size) {
return new BluetoothLeDevice[size];
}
};
/**
* Instantiates a new Bluetooth LE device.
*
* @param device a standard android Bluetooth device
* @param rssi the RSSI value of the Bluetooth device
* @param scanRecord the scan record of the device
* @param timestamp the timestamp of the RSSI reading
*/
public BluetoothLeDevice(BluetoothDevice device, int rssi, byte[] scanRecord, long timestamp){
mDevice = device;
mFirstRssi = rssi;
mFirstTimestamp = timestamp;
mRecordStore = new AdRecordStore(AdRecordUtils.parseScanRecordAsSparseArray(scanRecord));
mScanRecord = scanRecord;
mRssiLog = new LimitedLinkHashMap<Long, Integer>(MAX_RSSI_LOG_SIZE);
updateRssiReading(timestamp, rssi);
}
/**
* Instantiates a new Bluetooth LE device.
*
* @param device the device
*/
public BluetoothLeDevice(BluetoothLeDevice device) {
mCurrentRssi = device.getRssi();
mCurrentTimestamp = device.getTimestamp();
mDevice = device.getDevice();
mFirstRssi = device.getFirstRssi();
mFirstTimestamp = device.getFirstTimestamp();
mRecordStore = new AdRecordStore(
AdRecordUtils.parseScanRecordAsSparseArray(device.getScanRecord()));
mRssiLog = device.getRssiLog();
mScanRecord = device.getScanRecord();
}
/**
* Instantiates a new bluetooth le device.
*
* @param in the in
*/
@SuppressWarnings("unchecked")
protected BluetoothLeDevice(Parcel in) {
final Bundle b = in.readBundle(getClass().getClassLoader());
mCurrentRssi = b.getInt(PARCEL_EXTRA_CURRENT_RSSI, 0);
mCurrentTimestamp = b.getLong(PARCEL_EXTRA_CURRENT_TIMESTAMP, 0);
mDevice = b.getParcelable(PARCEL_EXTRA_BLUETOOTH_DEVICE);
mFirstRssi = b.getInt(PARCEL_EXTRA_FIRST_RSSI, 0);
mFirstTimestamp = b.getLong(PARCEL_EXTRA_FIRST_TIMESTAMP, 0);
mRecordStore = b.getParcelable(PARCEL_EXTRA_DEVICE_SCANRECORD_STORE);
mRssiLog = (Map<Long, Integer>) b.getSerializable(PARCEL_EXTRA_DEVICE_RSSI_LOG);
mScanRecord = b.getByteArray(PARCEL_EXTRA_DEVICE_SCANRECORD);
}
/**
* Adds the to rssi log.
*
* @param timestamp the timestamp
* @param rssiReading the rssi reading
*/
private void addToRssiLog(long timestamp, int rssiReading){
synchronized (mRssiLog) {
if(timestamp - mCurrentTimestamp > LOG_INVALIDATION_THRESHOLD){
mRssiLog.clear();
}
mCurrentRssi = rssiReading;
mCurrentTimestamp = timestamp;
mRssiLog.put(timestamp, rssiReading);
}
}
/* (non-Javadoc)
* @see android.os.Parcelable#describeContents()
*/
@Override
public int describeContents() {
return 0;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BluetoothLeDevice other = (BluetoothLeDevice) obj;
if (mCurrentRssi != other.mCurrentRssi)
return false;
if (mCurrentTimestamp != other.mCurrentTimestamp)
return false;
if (mDevice == null) {
if (other.mDevice != null)
return false;
} else if (!mDevice.equals(other.mDevice))
return false;
if (mFirstRssi != other.mFirstRssi)
return false;
if (mFirstTimestamp != other.mFirstTimestamp)
return false;
if (mRecordStore == null) {
if (other.mRecordStore != null)
return false;
} else if (!mRecordStore.equals(other.mRecordStore))
return false;
if (mRssiLog == null) {
if (other.mRssiLog != null)
return false;
} else if (!mRssiLog.equals(other.mRssiLog))
return false;
if (!Arrays.equals(mScanRecord, other.mScanRecord))
return false;
return true;
}
/**
* Gets the address.
*
* @return the address
*/
public String getAddress(){
return mDevice.getAddress();
}
/**
* Gets the ad record store.
*
* @return the ad record store
*/
public AdRecordStore getAdRecordStore(){
return mRecordStore;
}
/**
* Gets the bluetooth device bond state.
*
* @return the bluetooth device bond state
*/
public String getBluetoothDeviceBondState(){
return resolveBondingState(mDevice.getBondState());
}
/**
* Gets the bluetooth device class name.
*
* @return the bluetooth device class name
*/
public String getBluetoothDeviceClassName(){
return BluetoothClassResolver.resolveDeviceClass(mDevice.getBluetoothClass().getDeviceClass());
}
/**
* Gets the device.
*
* @return the device
*/
public BluetoothDevice getDevice() {
return mDevice;
}
/**
* Gets the first rssi.
*
* @return the first rssi
*/
public int getFirstRssi(){
return mFirstRssi;
}
/**
* Gets the first timestamp.
*
* @return the first timestamp
*/
public long getFirstTimestamp(){
return mFirstTimestamp;
}
/**
* Gets the name.
*
* @return the name
*/
public String getName(){
return mDevice.getName();
}
/**
* Gets the rssi.
*
* @return the rssi
*/
public int getRssi() {
return mCurrentRssi;
}
/**
* Gets the rssi log.
*
* @return the rssi log
*/
protected Map<Long, Integer> getRssiLog() {
synchronized (mRssiLog) {
return mRssiLog;
}
}
/**
* Gets the running average rssi.
*
* @return the running average rssi
*/
public double getRunningAverageRssi(){
int sum = 0;
int count = 0;
synchronized (mRssiLog) {
final Iterator<Long> it1 = mRssiLog.keySet().iterator();
while(it1.hasNext()){
count ++;
sum += mRssiLog.get(it1.next());
}
}
// for(final Map.Entry<Long,Integer> e : mRssiLog.entrySet()){
// count ++;
// sum += e.getValue();
// }
if(count > 0){
return sum/count;
} else {
return 0;
}
}
/**
* Gets the scan record.
*
* @return the scan record
*/
public byte[] getScanRecord() {
return mScanRecord;
}
/**
* Gets the timestamp.
*
* @return the timestamp
*/
public long getTimestamp(){
return mCurrentTimestamp;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + mCurrentRssi;
result = prime * result + (int) (mCurrentTimestamp ^ (mCurrentTimestamp >>> 32));
result = prime * result + ((mDevice == null) ? 0 : mDevice.hashCode());
result = prime * result + mFirstRssi;
result = prime * result + (int) (mFirstTimestamp ^ (mFirstTimestamp >>> 32));
result = prime * result + ((mRecordStore == null) ? 0 : mRecordStore.hashCode());
result = prime * result + ((mRssiLog == null) ? 0 : mRssiLog.hashCode());
result = prime * result + Arrays.hashCode(mScanRecord);
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "BluetoothLeDevice [mDevice=" + mDevice + ", mRssi=" + mFirstRssi + ", mScanRecord=" + ByteUtils.byteArrayToHexString(mScanRecord) + ", mRecordStore=" + mRecordStore + ", getBluetoothDeviceBondState()=" + getBluetoothDeviceBondState() + ", getBluetoothDeviceClassName()=" + getBluetoothDeviceClassName() + "]";
}
/**
* Update rssi reading.
*
* @param timestamp the timestamp
* @param rssiReading the rssi reading
*/
public void updateRssiReading(long timestamp, int rssiReading){
addToRssiLog(timestamp, rssiReading);
}
/* (non-Javadoc)
* @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
*/
@Override
public void writeToParcel(Parcel parcel, int arg1) {
final Bundle b = new Bundle(getClass().getClassLoader());
b.putByteArray(PARCEL_EXTRA_DEVICE_SCANRECORD, mScanRecord);
b.putInt(PARCEL_EXTRA_FIRST_RSSI, mFirstRssi);
b.putInt(PARCEL_EXTRA_CURRENT_RSSI, mCurrentRssi);
b.putLong(PARCEL_EXTRA_FIRST_TIMESTAMP, mFirstTimestamp);
b.putLong(PARCEL_EXTRA_CURRENT_TIMESTAMP, mCurrentTimestamp);
b.putParcelable(PARCEL_EXTRA_BLUETOOTH_DEVICE, mDevice);
b.putParcelable(PARCEL_EXTRA_DEVICE_SCANRECORD_STORE, mRecordStore);
b.putSerializable(PARCEL_EXTRA_DEVICE_RSSI_LOG, (Serializable) mRssiLog);
parcel.writeBundle(b);
}
/**
* Resolve bonding state.
*
* @param bondState the bond state
* @return the string
*/
private static String resolveBondingState(int bondState){
switch (bondState){
case BluetoothDevice.BOND_BONDED:
return "Paired";
case BluetoothDevice.BOND_BONDING:
return "Pairing";
case BluetoothDevice.BOND_NONE:
return "Unbonded";
default:
return "Unknown";
}
}
}

View File

@@ -1,143 +0,0 @@
package uk.co.alt236.bluetoothlelib.device;
import uk.co.alt236.bluetoothlelib.device.mfdata.IBeaconManufacturerData;
import uk.co.alt236.bluetoothlelib.util.IBeaconUtils;
import uk.co.alt236.bluetoothlelib.util.IBeaconUtils.IBeaconDistanceDescriptor;
import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
public class IBeaconDevice extends BluetoothLeDevice{
/** The m iBeacon data. */
private final IBeaconManufacturerData mIBeaconData;
/**
* Instantiates a new iBeacon device.
*
* @param device the device
* @param rssi the RSSI value
* @param scanRecord the scanRecord
* @throws IllegalArguementException if the passed device is not an iBecon
*/
public IBeaconDevice(BluetoothDevice device, int rssi, byte[] scanRecord) {
super(device, rssi, scanRecord, 0);
validate();
mIBeaconData = new IBeaconManufacturerData(this);
}
/**
* Instantiates a new iBeacon device.
*
* @param device the device
* @param rssi the RSSI value of the RSSI measurement
* @param scanRecord the scan record
* @param timestamp the timestamp of the RSSI measurement
* @throws IllegalArguementException if the passed device is not an iBecon
*/
public IBeaconDevice(BluetoothDevice device, int rssi, byte[] scanRecord, long timestamp){
super(device, rssi, scanRecord, timestamp);
validate();
mIBeaconData = new IBeaconManufacturerData(this);
}
/**
* Will try to convert a {@link BluetoothLeDevice} into an
* iBeacon Device.
*
* @param device the device
* @throws IllegalArguementException if the passed device is not an iBecon
*/
public IBeaconDevice(BluetoothLeDevice device){
super(device);
validate();
mIBeaconData = new IBeaconManufacturerData(this);
}
private IBeaconDevice(Parcel in) {
super(in);
validate();
mIBeaconData = new IBeaconManufacturerData(this);
}
/**
* Gets the estimated Accuracy of the reading in meters based on
* a simple running average of the last {@link #MAX_RSSI_LOG_SIZE}
* samples.
*
* @return the accuracy in meters
*/
public double getAccuracy(){
return IBeaconUtils.calculateAccuracy(
getCalibratedTxPower(),
getRunningAverageRssi());
}
/**
* Gets the calibrated TX power of the iBeacon device as reported.
*
* @return the calibrated TX power
*/
public int getCalibratedTxPower(){
return getIBeaconData().getCalibratedTxPower();
}
/**
* Gets the iBeacon company identifier.
*
* @return the company identifier
*/
public int getCompanyIdentifier(){
return getIBeaconData().getCompanyIdentifier();
}
/**
* Gets the estimated Distance descriptor.
*
* @return the distance descriptor
*/
public IBeaconDistanceDescriptor getDistanceDescriptor(){
return IBeaconUtils.getDistanceDescriptor(getAccuracy());
}
/**
* Gets the iBeacon manufacturing data.
*
* @return the iBeacon data
*/
public IBeaconManufacturerData getIBeaconData(){
return mIBeaconData;
}
/**
* Gets the iBeacon Major value.
*
* @return the Major value
*/
public int getMajor(){
return getIBeaconData().getMajor();
}
/**
* Gets the iBeacon Minor value.
*
* @return the Minor value
*/
public int getMinor(){
return getIBeaconData().getMinor();
}
/**
* Gets the iBeacon UUID.
*
* @return the UUID
*/
public String getUUID(){
return getIBeaconData().getUUID();
}
private void validate(){
if(!IBeaconUtils.isThisAnIBeacon(this)){
throw new IllegalArgumentException("Device " + getDevice() + " is not an iBeacon.");
}
}
}

View File

@@ -1,244 +0,0 @@
package uk.co.alt236.bluetoothlelib.device.adrecord;
import java.util.Arrays;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by Dave Smith
* Double Encore, Inc.
*
* Expanded by Alexandros Schillings
*/
public final class AdRecord implements Parcelable{
// 02 # Number of bytes that follow in first AD structure
// 01 # Flags AD type
// 1A # Flags value 0x1A = 000011010
// bit 0 (OFF) LE Limited Discoverable Mode
// bit 1 (ON) LE General Discoverable Mode
// bit 2 (OFF) BR/EDR Not Supported
// bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
// bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
// 1A # Number of bytes that follow in second (and last) AD structure
// FF # Manufacturer specific data AD type
// 4C 00 # Company identifier code (0x004C == Apple)
// 02 # Byte 0 of iBeacon advertisement indicator
// 15 # Byte 1 of iBeacon advertisement indicator
// e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon proximity uuid
// 00 00 # major
// 00 00 # minor
// c5 # The 2's complement of the calibrated Tx Power
private static final String PARCEL_RECORD_DATA = "record_data";
private static final String PARCEL_RECORD_TYPE = "record_type";
private static final String PARCEL_RECORD_LENGTH = "record_length";
/**
* General FLAGS
*
* Description: Flags
*
* Information:
* Bit 0: LE Limited Discoverable Mode
* Bit 1: LE General Discoverable Mode
* Bit 2: BR/EDR Not Supported (i.e. bit 37 of LMP Extended Feature bits Page 0)
* Bit 3: Simultaneous LE and BR/EDR to Same Device Capable (Controller) (i.e. bit 49 of LMP Extended Feature bits Page 0)
* Bit 4: Simultaneous LE and BR/EDR to Same Device Capable (Host) (i.e. bit 66 of LMP Extended Feature bits Page 1)
* Bits 5-7 Reserved
*/
public static final int TYPE_FLAGS = 0x01;
// SERVICE
public static final int TYPE_UUID16_INC = 0x02;
public static final int TYPE_UUID16 = 0x03;
public static final int TYPE_UUID32_INC = 0x04;
public static final int TYPE_UUID32 = 0x05;
public static final int TYPE_UUID128_INC = 0x06;
public static final int TYPE_UUID128 = 0x07;
// Local name
public static final int TYPE_LOCAL_NAME_SHORT = 0x08;
public static final int TYPE_LOCAL_NAME_COMPLETE = 0x09;
// TX Power Level
public static final int TYPE_TX_POWER_LEVEL = 0x0A;
// SIMPLE PAIRING OPTIONAL OOB TAGS
public static final int TYPE_DEVICE_CLASS = 0x0D;
public static final int TYPE_SIMPLE_PAIRING_HASH_C = 0x0E;
public static final int TYPE_SIMPLE_PAIRING_RANDOMIZER_R = 0x0F;
// SECURITY MANAGER TK VALUE
public static final int TYPE_TK_VALUE = 0x10;
/* SECURITY MANAGER OOB FLAGS
*
* Description: Flag (1 octet)
*
* Information:
* Bit 0: OOB Flags Field: (0 = OOB data not present, 1 = OOB data present)
* Bit 1: LE supported (Host) (i.e. bit 65 of LMP Extended Feature bits Page 1
* Bit 2: Simultaneous LE and BR/EDR to Same Device Capable (Host) (i.e. bit 66 of LMP Extended Feature bits Page 1)
* Bit 3: Address type (0 = Public Address, 1 = Random Address)
* Bits 4-7 Reserved
*/
public static final int TYPE_SECURITY_MANAGER_OOB_FLAGS = 0x11;
/* SLAVE CONNECTION INTERVAL RANGE
*
* Description: Slave Connection Interval Range
*
* Information:
* The first 2 octets defines the minimum value for the connection interval in the following manner:
* connInterval min = Conn_Interval_Min * 1.25 ms
* Conn_Interval_Min range: 0x0006 to 0x0C80
* Value of 0xFFFF indicates no specific minimum.
* Values outside the range are reserved. (excluding 0xFFFF)
*
* The second 2 octets defines the maximum value for the connection interval in the following manner:
* connInterval max = Conn_Interval_Max * 1.25 ms
* Conn_Interval_Max range: 0x0006 to 0x0C80
* Conn_Interval_Max shall be equal to or greater
* than the Conn_Interval_Min.
* Value of 0xFFFF indicates no specific maximum.
* Values outside the range are reserved (excluding 0xFFFF)
*/
public static final int TYPE_CONNECTION_INTERVAL_RANGE = 0x12;
// SERVICE SOLICITATION
public static final int TYPE_SERVICE_UUIDS_LIST_16BIT = 0x14;
public static final int TYPE_SERVICE_UUIDS_LIST_128BIT = 0x15;
/* SERVICE DATA
*
* Description: Service Data (2 or more octets)
* Information: The first 2 octets contain the 16 bit Service UUID followed by additional service data
*/
public static final int TYPE_SERVICE_DATA = 0x16;
/* MANUFACTURER SPECIFIC DATA
*
* Description: Manufacturer Specific Data (2 or more octets)
* Information: The first 2 octets contain the Company Identifier Code followed by additional manufacturer specific data
*/
public static final int TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
/* Model Object Definition */
private final int mLength;
private final int mType;
private final byte[] mData;
public static final Parcelable.Creator<AdRecord> CREATOR = new Parcelable.Creator<AdRecord>() {
public AdRecord createFromParcel(Parcel in) {
return new AdRecord(in);
}
public AdRecord[] newArray(int size) {
return new AdRecord[size];
}
};
public AdRecord(int length, int type, byte[] data) {
mLength = length;
mType = type;
mData = data;
}
public AdRecord(Parcel in) {
final Bundle b = in.readBundle(getClass().getClassLoader());
mLength = b.getInt(PARCEL_RECORD_LENGTH);
mType = b.getInt(PARCEL_RECORD_TYPE);
mData = b.getByteArray(PARCEL_RECORD_DATA);
}
@Override
public int describeContents() {
return 0;
}
public byte[] getData(){
return mData;
}
public String getHumanReadableType(){
return getHumanReadableAdType(mType);
}
public int getLength() {
return mLength;
}
public int getType() {
return mType;
}
@Override
public String toString() {
return "AdRecord [mLength=" + mLength + ", mType=" + mType + ", mData=" + Arrays.toString(mData) + ", getHumanReadableType()=" + getHumanReadableType() + "]";
}
@Override
public void writeToParcel(Parcel parcel, int arg1) {
final Bundle b = new Bundle(getClass().getClassLoader());
b.putInt(PARCEL_RECORD_LENGTH, mLength);
b.putInt(PARCEL_RECORD_TYPE, mType);
b.putByteArray(PARCEL_RECORD_DATA, mData);
parcel.writeBundle(b);
}
private static String getHumanReadableAdType(int type){
switch(type){
case TYPE_CONNECTION_INTERVAL_RANGE:
return "Slave Connection Interval Range";
case TYPE_DEVICE_CLASS:
return "Class of device";
case TYPE_FLAGS:
return "Flags";
case TYPE_MANUFACTURER_SPECIFIC_DATA:
return "Manufacturer Specific Data";
case TYPE_LOCAL_NAME_COMPLETE:
return "Name (Complete)";
case TYPE_LOCAL_NAME_SHORT:
return "Name (Short)";
case TYPE_SECURITY_MANAGER_OOB_FLAGS:
return "Security Manager OOB Flags";
case TYPE_SERVICE_UUIDS_LIST_128BIT:
return "Service UUIDs (128bit)";
case TYPE_SERVICE_UUIDS_LIST_16BIT:
return "Service UUIDs (16bit)";
case TYPE_SERVICE_DATA:
return "Service Data";
case TYPE_SIMPLE_PAIRING_HASH_C:
return "Simple Pairing Hash C";
case TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
return "Simple Pairing Randomizer R";
case TYPE_TK_VALUE:
return "TK Value";
case TYPE_TX_POWER_LEVEL:
return "Transmission Power Level";
case TYPE_UUID128:
return "Complete list of 128-bit UUIDs available";
case TYPE_UUID128_INC:
return "More 128-bit UUIDs available";
case TYPE_UUID16:
return "Complete list of 16-bit UUIDs available";
case TYPE_UUID16_INC:
return "More 16-bit UUIDs available";
case TYPE_UUID32:
return "Complete list of 32-bit UUIDs available";
case TYPE_UUID32_INC:
return "More 32-bit UUIDs available";
default:
return "Unknown AdRecord Structure: " + type;
}
}
}

View File

@@ -1,158 +0,0 @@
package uk.co.alt236.bluetoothlelib.device.adrecord;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
/**
* The Class AdRecordStore.
*/
public class AdRecordStore implements Parcelable{
private final SparseArray<AdRecord> mAdRecords;
private final String mLocalNameComplete;
private final String mLocalNameShort;
public static final Parcelable.Creator<AdRecordStore> CREATOR = new Parcelable.Creator<AdRecordStore>() {
public AdRecordStore createFromParcel(Parcel in) {
return new AdRecordStore(in);
}
public AdRecordStore[] newArray(int size) {
return new AdRecordStore[size];
}
};
public AdRecordStore(Parcel in) {
final Bundle b = in.readBundle(getClass().getClassLoader());
mAdRecords = b.getSparseParcelableArray("records_array");
mLocalNameComplete = b.getString("local_name_complete");
mLocalNameShort = b.getString("local_name_short");
}
/**
* Instantiates a new Bluetooth LE device Ad Record Store.
*
* @param adRecords the ad records
*/
public AdRecordStore(final SparseArray<AdRecord> adRecords){
mAdRecords = adRecords;
mLocalNameComplete = AdRecordUtils.getRecordDataAsString(
mAdRecords.get(AdRecord.TYPE_LOCAL_NAME_COMPLETE));
mLocalNameShort = AdRecordUtils.getRecordDataAsString(
mAdRecords.get(AdRecord.TYPE_LOCAL_NAME_SHORT));
}
/* (non-Javadoc)
* @see android.os.Parcelable#describeContents()
*/
@Override
public int describeContents() {
return 0;
}
/**
* Gets the short local device name.
*
* @return the local name complete
*/
public String getLocalNameComplete() {
return mLocalNameComplete;
}
/**
* Gets the complete local device name.
*
* @return the local name short
*/
public String getLocalNameShort() {
return mLocalNameShort;
}
/**
* retrieves an individual record.
*
* @param record the record
* @return the record
*/
public AdRecord getRecord(int record){
return mAdRecords.get(record);
}
/**
* Gets the record data as string.
*
* @param record the record
* @return the record data as string
*/
public String getRecordDataAsString(int record){
return AdRecordUtils.getRecordDataAsString(
mAdRecords.get(record));
}
/**
* Gets the record as collection.
*
* @return the records as collection
*/
public Collection<AdRecord> getRecordsAsCollection() {
return Collections.unmodifiableCollection(asList(mAdRecords));
}
/**
* Checks if is record present.
*
* @param record the record
* @return true, if is record present
*/
public boolean isRecordPresent(int record){
return mAdRecords.indexOfKey(record) >= 0;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "AdRecordStore [mLocalNameComplete=" + mLocalNameComplete + ", mLocalNameShort=" + mLocalNameShort + "]";
}
/* (non-Javadoc)
* @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
*/
@Override
public void writeToParcel(Parcel parcel, int arg1) {
final Bundle b = new Bundle();
b.putString("local_name_complete", mLocalNameComplete);
b.putString("local_name_short", mLocalNameShort);
b.putSparseParcelableArray("records_array", mAdRecords);
parcel.writeBundle(b);
}
/**
* As list.
*
* @param <C> the generic type
* @param sparseArray the sparse array
* @return the collection
*/
public static <C> Collection<C> asList(SparseArray<C> sparseArray) {
if (sparseArray == null) return null;
final Collection<C> arrayList = new ArrayList<C>(sparseArray.size());
for (int i = 0; i < sparseArray.size(); i++){
arrayList.add(sparseArray.valueAt(i));
}
return arrayList;
}
}

View File

@@ -1,144 +0,0 @@
package uk.co.alt236.bluetoothlelib.device.mfdata;
import java.util.Arrays;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
import uk.co.alt236.bluetoothlelib.util.ByteUtils;
/**
* Parses the Manufactured Data field of an iBeacon
*
* The parsing is based on the following schema:
*
* <p>
* 0 4C - Byte 1 (LSB) of Company identifier code
* 1 00 - Byte 0 (MSB) of Company identifier code (0x004C == Apple)
* 2 02 - Byte 0 of iBeacon advertisement indicator
* 3 15 - Byte 1 of iBeacon advertisement indicator
* 4 e2 |\
* 5 c5 |\\
* 6 6d |#\\
* 7 b5 |##\\
* 8 df |###\\
* 9 fb |####\\
* 10 48 |#####\\
* 11 d2 |#####|| iBeacon proximity UUID
* 12 b0 |#####||
* 13 60 |#####//
* 14 d0 |####//
* 15 f5 |###//
* 16 a7 |##//
* 17 10 |#//
* 18 96 |//
* 19 e0 |/
* 20 00 - major
* 21 00
* 22 00 - minor
* 23 00
* 24 c5 - The 2's complement of the calibrated Tx Power
*
* </p>
*
* @author Alexandros Schillings
*
*/
public final class IBeaconManufacturerData {
private final byte[] mData;
private final int mCalibratedTxPower;
private final int mCompanyIdentidier;
private final int mIBeaconAdvertisment;
private final int mMajor;
private final int mMinor;
private final String mUUID;
public IBeaconManufacturerData(BluetoothLeDevice device){
this(device.getAdRecordStore().getRecord(AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA).getData());
}
/**
* Instantiates a new iBeacon manufacturer data object.
* @param data the {@link #uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA} data array
* @throws IndexOutOfBoundsException if the data array is shorter than expected
*/
public IBeaconManufacturerData(byte[] data){
mData = data;
mCompanyIdentidier = ByteUtils.getIntFrom2ByteArray(
ByteUtils.invertArray(Arrays.copyOfRange(mData, 0, 2)));
mIBeaconAdvertisment = ByteUtils.getIntFrom2ByteArray(Arrays.copyOfRange(mData, 2, 4));
mUUID = calculateUUIDString(Arrays.copyOfRange(mData, 4, 20));
mMajor = ByteUtils.getIntFrom2ByteArray(Arrays.copyOfRange(mData, 20, 22));
mMinor = ByteUtils.getIntFrom2ByteArray(Arrays.copyOfRange(mData, 22, 24));
mCalibratedTxPower = data[24];
}
/**
* Gets the calibrated TX power of the iBeacon device as reported.
*
* @return the calibrated TX power
*/
public int getCalibratedTxPower(){
return mCalibratedTxPower;
}
/**
* Gets the iBeacon company identifier.
*
* @return the company identifier
*/
public int getCompanyIdentifier(){
return mCompanyIdentidier;
}
public int getIBeaconAdvertisement(){
return mIBeaconAdvertisment;
}
/**
* Gets the iBeacon Major value.
*
* @return the Major value
*/
public int getMajor(){
return mMajor;
}
/**
* Gets the iBeacon Minor value.
*
* @return the Minor value
*/
public int getMinor(){
return mMinor;
}
/**
* Gets the iBeacon UUID.
*
* @return the UUID
*/
public String getUUID(){
return mUUID;
}
private static String calculateUUIDString(final byte[] uuid){
final StringBuffer sb = new StringBuffer();
for(int i = 0 ; i< uuid.length; i++){
if(i == 4){sb.append('-');}
if(i == 6){sb.append('-');}
if(i == 8){sb.append('-');}
if(i == 10){sb.append('-');}
sb.append(
Integer.toHexString(ByteUtils.getIntFromByte(uuid[i])));
}
return sb.toString();
}
}

View File

@@ -1,113 +0,0 @@
package uk.co.alt236.bluetoothlelib.resolvers;
import android.bluetooth.BluetoothClass;
public class BluetoothClassResolver {
public static String resolveDeviceClass(int btClass){
switch (btClass){
case BluetoothClass.Device.AUDIO_VIDEO_CAMCORDER:
return "A/V, Camcorder";
case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
return "A/V, Car Audio";
case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
return "A/V, Handsfree";
case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
return "A/V, Headphones";
case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
return "A/V, HiFi Audio";
case BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER:
return "A/V, Loudspeaker";
case BluetoothClass.Device.AUDIO_VIDEO_MICROPHONE:
return "A/V, Microphone";
case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
return "A/V, Portable Audio";
case BluetoothClass.Device.AUDIO_VIDEO_SET_TOP_BOX:
return "A/V, Set Top Box";
case BluetoothClass.Device.AUDIO_VIDEO_UNCATEGORIZED:
return "A/V, Uncategorized";
case BluetoothClass.Device.AUDIO_VIDEO_VCR:
return "A/V, VCR";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_CAMERA:
return "A/V, Video Camera";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_CONFERENCING:
return "A/V, Video Conferencing";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER:
return "A/V, Video Display and Loudspeaker";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_GAMING_TOY:
return "A/V, Video Gaming Toy";
case BluetoothClass.Device.AUDIO_VIDEO_VIDEO_MONITOR:
return "A/V, Video Monitor";
case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
return "A/V, Video Wearable Headset";
case BluetoothClass.Device.COMPUTER_DESKTOP:
return "Computer, Desktop";
case BluetoothClass.Device.COMPUTER_HANDHELD_PC_PDA:
return "Computer, Handheld PC/PDA";
case BluetoothClass.Device.COMPUTER_LAPTOP:
return "Computer, Laptop";
case BluetoothClass.Device.COMPUTER_PALM_SIZE_PC_PDA:
return "Computer, Palm Size PC/PDA";
case BluetoothClass.Device.COMPUTER_SERVER:
return "Computer, Server";
case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
return "Computer, Uncategorized";
case BluetoothClass.Device.COMPUTER_WEARABLE:
return "Computer, Wearable";
case BluetoothClass.Device.HEALTH_BLOOD_PRESSURE:
return "Health, Blood Pressure";
case BluetoothClass.Device.HEALTH_DATA_DISPLAY:
return "Health, Data Display";
case BluetoothClass.Device.HEALTH_GLUCOSE:
return "Health, Glucose";
case BluetoothClass.Device.HEALTH_PULSE_OXIMETER :
return "Health, Pulse Oximeter";
case BluetoothClass.Device.HEALTH_PULSE_RATE :
return "Health, Pulse Rate";
case BluetoothClass.Device.HEALTH_THERMOMETER :
return "Health, Thermometer";
case BluetoothClass.Device.HEALTH_UNCATEGORIZED :
return "Health, Uncategorized";
case BluetoothClass.Device.HEALTH_WEIGHING:
return "Health, Weighting";
case BluetoothClass.Device.PHONE_CELLULAR:
return "Phone, Cellular";
case BluetoothClass.Device.PHONE_CORDLESS:
return "Phone, Cordless";
case BluetoothClass.Device.PHONE_ISDN:
return "Phone, ISDN";
case BluetoothClass.Device.PHONE_MODEM_OR_GATEWAY:
return "Phone, Modem or Gateway";
case BluetoothClass.Device.PHONE_SMART:
return "Phone, Smart";
case BluetoothClass.Device.PHONE_UNCATEGORIZED:
return "Phone, Uncategorized";
case BluetoothClass.Device.TOY_CONTROLLER:
return "Toy, Controller";
case BluetoothClass.Device.TOY_DOLL_ACTION_FIGURE:
return "Toy, Doll/Action Figure";
case BluetoothClass.Device.TOY_GAME:
return "Toy, Game";
case BluetoothClass.Device.TOY_ROBOT:
return "Toy, Robot";
case BluetoothClass.Device.TOY_UNCATEGORIZED:
return "Toy, Uncategorized";
case BluetoothClass.Device.TOY_VEHICLE:
return "Toy, Vehicle";
case BluetoothClass.Device.WEARABLE_GLASSES:
return "Wearable, Glasses";
case BluetoothClass.Device.WEARABLE_HELMET:
return "Wearable, Helmet";
case BluetoothClass.Device.WEARABLE_JACKET:
return "Wearable, Jacket";
case BluetoothClass.Device.WEARABLE_PAGER:
return "Wearable, Pager";
case BluetoothClass.Device.WEARABLE_UNCATEGORIZED:
return "Wearable, Uncategorized";
case BluetoothClass.Device.WEARABLE_WRIST_WATCH:
return "Wearable, Wrist Watch";
default:
return "Unknown, Unknown (class=" + btClass +")";
}
}
}

View File

@@ -1,646 +0,0 @@
package uk.co.alt236.bluetoothlelib.resolvers;
import android.util.SparseArray;
public class CompanyIdentifierResolver {
public static final int ERICSSON_TECHNOLOGY_LICENSING = 0x0000;
public static final int NOKIA_MOBILE_PHONES = 0x0001;
public static final int INTEL_CORP = 0x0002;
public static final int IBM_CORP = 0x0003;
public static final int TOSHIBA_CORP = 0x0004;
public static final int THREE_COM = 0x0005;
public static final int MICROSOFT = 0x0006;
public static final int LUCENT = 0x0007;
public static final int MOTOROLA = 0x0008;
public static final int INFINEON_TECHNOLOGIES_AG = 0x0009;
public static final int CAMBRIDGE_SILICON_RADIO = 0x000A;
public static final int SILICON_WAVE = 0x000B;
public static final int DIGIANSWER_A_S = 0x000C;
public static final int TEXAS_INSTRUMENTS_INC = 0x000D;
public static final int CEVA_INC_FORMERLY_PARTHUS_TECHNOLOGIES_INC = 0x000E;
public static final int BROADCOM_CORPORATION = 0x000F;
public static final int MITEL_SEMICONDUCTOR = 0x0010;
public static final int WIDCOMM_INC = 0x0011;
public static final int ZEEVO_INC = 0x0012;
public static final int ATMEL_CORPORATION = 0x0013;
public static final int MITSUBISHI_ELECTRIC_CORPORATION = 0x0014;
public static final int RTX_TELECOM_A_S = 0x0015;
public static final int KC_TECHNOLOGY_INC = 0x0016;
public static final int NEWLOGIC = 0x0017;
public static final int TRANSILICA_INC = 0x0018;
public static final int ROHDE_SCHWARZ_GMBH_CO_KG = 0x0019;
public static final int TTPCOM_LIMITED = 0x001A;
public static final int SIGNIA_TECHNOLOGIES_INC = 0x001B;
public static final int CONEXANT_SYSTEMS_INC = 0x001C;
public static final int QUALCOMM = 0x001D;
public static final int INVENTEL = 0x001E;
public static final int AVM_BERLIN = 0x001F;
public static final int BANDSPEED_INC = 0x0020;
public static final int MANSELLA_LTD = 0x0021;
public static final int NEC_CORPORATION = 0x0022;
public static final int WAVEPLUS_TECHNOLOGY_CO_LTD = 0x0023;
public static final int ALCATEL = 0x0024;
public static final int PHILIPS_SEMICONDUCTORS = 0x0025;
public static final int C_TECHNOLOGIES = 0x0026;
public static final int OPEN_INTERFACE = 0x0027;
public static final int R_F_MICRO_DEVICES = 0x0028;
public static final int HITACHI_LTD = 0x0029;
public static final int SYMBOL_TECHNOLOGIES_INC = 0x002A;
public static final int TENOVIS = 0x002B;
public static final int MACRONIX_INTERNATIONAL_CO_LTD = 0x002C;
public static final int GCT_SEMICONDUCTOR = 0x002D;
public static final int NORWOOD_SYSTEMS = 0x002E;
public static final int MEWTEL_TECHNOLOGY_INC = 0x002F;
public static final int ST_MICROELECTRONICS = 0x0030;
public static final int SYNOPSIS = 0x0031;
public static final int REDM_COMMUNICATIONS_LTD = 0x0032;
public static final int COMMIL_LTD = 0x0033;
public static final int COMPUTER_ACCESS_TECHNOLOGY_CORPORATION_CATC = 0x0034;
public static final int ECLIPSE_HQ_ESPANA_SL = 0x0035;
public static final int RENESAS_TECHNOLOGY_CORP = 0x0036;
public static final int MOBILIAN_CORPORATION = 0x0037;
public static final int TERAX = 0x0038;
public static final int INTEGRATED_SYSTEM_SOLUTION_CORP = 0x0039;
public static final int MATSUSHITA_ELECTRIC_INDUSTRIAL_CO_LTD = 0x003A;
public static final int GENNUM_CORPORATION = 0x003B;
public static final int RESEARCH_IN_MOTION = 0x003C;
public static final int IPEXTREME_INC = 0x003D;
public static final int SYSTEMS_AND_CHIPS_INC = 0x003E;
public static final int BLUETOOTH_SIG_INC = 0x003F;
public static final int SEIKO_EPSON_CORPORATION = 0x0040;
public static final int INTEGRATED_SILICON_SOLUTION_TAIWAN_INC = 0x0041;
public static final int CONWISE_TECHNOLOGY_CORPORATION_LTD = 0x0042;
public static final int PARROT_SA = 0x0043;
public static final int SOCKET_MOBILE = 0x0044;
public static final int ATHEROS_COMMUNICATIONS_INC = 0x0045;
public static final int MEDIATEK_INC = 0x0046;
public static final int BLUEGIGA = 0x0047;
public static final int MARVELL_TECHNOLOGY_GROUP_LTD = 0x0048;
public static final int THREE_DSP_CORPORATION = 0x0049;
public static final int ACCEL_SEMICONDUCTOR_LTD = 0x004A;
public static final int CONTINENTAL_AUTOMOTIVE_SYSTEMS = 0x004B;
public static final int APPLE_INC = 0x004C;
public static final int STACCATO_COMMUNICATIONS_INC = 0x004D;
public static final int AVAGO_TECHNOLOGIES = 0x004E;
public static final int APT_LICENSING_LTD = 0x004F;
public static final int SIRF_TECHNOLOGY = 0x0050;
public static final int TZERO_TECHNOLOGIES_INC = 0x0051;
public static final int JM_CORPORATION = 0x0052;
public static final int FREE2MOVE_AB = 0x0053;
public static final int THREE_DIJOY_CORPORATION = 0x0054;
public static final int PLANTRONICS_INC = 0x0055;
public static final int SONY_ERICSSON_MOBILE_COMMUNICATIONS = 0x0056;
public static final int HARMAN_INTERNATIONAL_INDUSTRIES_INC = 0x0057;
public static final int VIZIO_INC = 0x0058;
public static final int NORDIC_SEMICONDUCTOR_ASA = 0x0059;
public static final int EM_MICROELECTRONICMARIN_SA = 0x005A;
public static final int RALINK_TECHNOLOGY_CORPORATION = 0x005B;
public static final int BELKIN_INTERNATIONAL_INC = 0x005C;
public static final int REALTEK_SEMICONDUCTOR_CORPORATION = 0x005D;
public static final int STONESTREET_ONE_LLC = 0x005E;
public static final int WICENTRIC_INC = 0x005F;
public static final int RIVIERAWAVES_SAS = 0x0060;
public static final int RDA_MICROELECTRONICS = 0x0061;
public static final int GIBSON_GUITARS = 0x0062;
public static final int MICOMMAND_INC = 0x0063;
public static final int BAND_XI_INTERNATIONAL_LLC = 0x0064;
public static final int HEWLETTPACKARD_COMPANY = 0x0065;
public static final int NINE_SOLUTIONS_OY = 0x0066;
public static final int GN_NETCOM_A_S = 0x0067;
public static final int GENERAL_MOTORS = 0x0068;
public static final int AD_ENGINEERING_INC = 0x0069;
public static final int MINDTREE_LTD = 0x006A;
public static final int POLAR_ELECTRO_OY = 0x006B;
public static final int BEAUTIFUL_ENTERPRISE_CO_LTD = 0x006C;
public static final int BRIARTEK_INC = 0x006D;
public static final int SUMMIT_DATA_COMMUNICATIONS_INC = 0x006E;
public static final int SOUND_ID = 0x006F;
public static final int MONSTER_LLC = 0x0070;
public static final int CONNECTBLUE_AB = 0x0071;
public static final int SHANGHAI_SUPER_SMART_ELECTRONICS_CO_LTD = 0x0072;
public static final int GROUP_SENSE_LTD = 0x0073;
public static final int ZOMM_LLC = 0x0074;
public static final int SAMSUNG_ELECTRONICS_CO_LTD = 0x0075;
public static final int CREATIVE_TECHNOLOGY_LTD = 0x0076;
public static final int LAIRD_TECHNOLOGIES = 0x0077;
public static final int NIKE_INC = 0x0078;
public static final int LESSWIRE_AG = 0x0079;
public static final int MSTAR_SEMICONDUCTOR_INC = 0x007A;
public static final int HANLYNN_TECHNOLOGIES = 0x007B;
public static final int A_R_CAMBRIDGE = 0x007C;
public static final int SEERS_TECHNOLOGY_CO_LTD = 0x007D;
public static final int SPORTS_TRACKING_TECHNOLOGIES_LTD = 0x007E;
public static final int AUTONET_MOBILE = 0x007F;
public static final int DELORME_PUBLISHING_COMPANY_INC = 0x0080;
public static final int WUXI_VIMICRO = 0x0081;
public static final int SENNHEISER_COMMUNICATIONS_A_S = 0x0082;
public static final int TIMEKEEPING_SYSTEMS_INC = 0x0083;
public static final int LUDUS_HELSINKI_LTD = 0x0084;
public static final int BLUERADIOS_INC = 0x0085;
public static final int EQUINOX_AG = 0x0086;
public static final int GARMIN_INTERNATIONAL_INC = 0x0087;
public static final int ECOTEST = 0x0088;
public static final int GN_RESOUND_A_S = 0x0089;
public static final int JAWBONE = 0x008A;
public static final int TOPCORN_POSITIONING_SYSTEMS_LLC = 0x008B;
public static final int QUALCOMM_RETAIL_SOLUTIONS_INC_FORMERLY_QUALCOMM_LABS_INC = 0x008C;
public static final int ZSCAN_SOFTWARE = 0x008D;
public static final int QUINTIC_CORP = 0x008E;
public static final int STOLLMAN_EV_GMBH = 0x008F;
public static final int FUNAI_ELECTRIC_CO_LTD = 0x0090;
public static final int ADVANCED_PANMOBIL_SYSTEMS_GMBH_CO_KG = 0x0091;
public static final int THINKOPTICS_INC = 0x0092;
public static final int UNIVERSAL_ELECTRONICS_INC = 0x0093;
public static final int AIROHA_TECHNOLOGY_CORP = 0x0094;
public static final int NEC_LIGHTING_LTD = 0x0095;
public static final int ODM_TECHNOLOGY_INC = 0x0096;
public static final int CONNECTEDEVICE_LTD = 0x0097;
public static final int ZER01TV_GMBH = 0x0098;
public static final int ITECH_DYNAMIC_GLOBAL_DISTRIBUTION_LTD = 0x0099;
public static final int ALPWISE = 0x009A;
public static final int JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS_CO_LTD = 0x009B;
public static final int COLORFY_INC = 0x009C;
public static final int GEOFORCE_INC = 0x009D;
public static final int BOSE_CORPORATION = 0x009E;
public static final int SUUNTO_OY = 0x009F;
public static final int KENSINGTON_COMPUTER_PRODUCTS_GROUP = 0x00A0;
public static final int SRMEDIZINELEKTRONIK = 0x00A1;
public static final int VERTU_CORPORATION_LIMITED = 0x00A2;
public static final int META_WATCH_LTD = 0x00A3;
public static final int LINAK_A_S = 0x00A4;
public static final int OTL_DYNAMICS_LLC = 0x00A5;
public static final int PANDA_OCEAN_INC = 0x00A6;
public static final int VISTEON_CORPORATION = 0x00A7;
public static final int ARP_DEVICES_LIMITED = 0x00A8;
public static final int MAGNETI_MARELLI_SPA = 0x00A9;
public static final int CAEN_RFID_SRL = 0x00AA;
public static final int INGENIEURSYSTEMGRUPPE_ZAHN_GMBH = 0x00AB;
public static final int GREEN_THROTTLE_GAMES = 0x00AC;
public static final int PETER_SYSTEMTECHNIK_GMBH = 0x00AD;
public static final int OMEGAWAVE_OY = 0x00AE;
public static final int CINETIX = 0x00AF;
public static final int PASSIF_SEMICONDUCTOR_CORP = 0x00B0;
public static final int SARIS_CYCLING_GROUP_INC = 0x00B1;
public static final int BEKEY_A_S = 0x00B2;
public static final int CLARINOX_TECHNOLOGIES_PTY_LTD = 0x00B3;
public static final int BDE_TECHNOLOGY_CO_LTD = 0x00B4;
public static final int SWIRL_NETWORKS = 0x00B5;
public static final int MESO_INTERNATIONAL = 0x00B6;
public static final int TRELAB_LTD = 0x00B7;
public static final int QUALCOMM_INNOVATION_CENTER_INC_QUIC = 0x00B8;
public static final int JOHNSON_CONTROLS_INC = 0x00B9;
public static final int STARKEY_LABORATORIES_INC = 0x00BA;
public static final int SPOWER_ELECTRONICS_LIMITED = 0x00BB;
public static final int ACE_SENSOR_INC = 0x00BC;
public static final int APLIX_CORPORATION = 0x00BD;
public static final int AAMP_OF_AMERICA = 0x00BE;
public static final int STALMART_TECHNOLOGY_LIMITED = 0x00BF;
public static final int AMICCOM_ELECTRONICS_CORPORATION = 0x00C0;
public static final int SHENZHEN_EXCELSECU_DATA_TECHNOLOGY_COLTD = 0x00C1;
public static final int GENEQ_INC = 0x00C2;
public static final int ADIDAS_AG = 0x00C3;
public static final int LG_ELECTRONICS = 0x00C4;
public static final int ONSET_COMPUTER_CORPORATION = 0x00C5;
public static final int SELFLY_BV = 0x00C6;
public static final int QUUPPA_OY = 0x00C7;
public static final int GELO_INC = 0x00C8;
public static final int EVLUMA = 0x00C9;
public static final int MC10 = 0x00CA;
public static final int BINAURIC_SE = 0x00CB;
public static final int BEATS_ELECTRONICS = 0x00CC;
public static final int MICROCHIP_TECHNOLOGY_INC = 0x00CD;
public static final int ELGATO_SYSTEMS_GMBH = 0x00CE;
public static final int ARCHOS_SA = 0x00CF;
public static final int DEXCOM_INC = 0x00D0;
public static final int POLAR_ELECTRO_EUROPE_BV = 0x00D1;
public static final int DIALOG_SEMICONDUCTOR_BV = 0x00D2;
public static final int TAIXINGBANG_TECHNOLOGY_HK_CO_LTD = 0x00D3;
public static final int KAWANTECH = 0x00D4;
public static final int AUSTCO_COMMUNICATION_SYSTEMS = 0x00D5;
public static final int TIMEX_GROUP_USA_INC = 0x00D6;
public static final int QUALCOMM_TECHNOLOGIES_INC = 0x00D7;
public static final int QUALCOMM_CONNECTED_EXPERIENCES_INC = 0x00D8;
public static final int VOYETRA_TURTLE_BEACH = 0x00D9;
public static final int TXTR_GMBH = 0x00DA;
public static final int BIOSENTRONICS = 0x00DB;
public static final int PROCTER_GAMBLE = 0x00DC;
public static final int HOSIDEN_CORPORATION = 0x00DD;
public static final int MUZIK_LLC = 0x00DE;
public static final int MISFIT_WEARABLES_CORP = 0x00DF;
public static final int GOOGLE = 0x00E0;
public static final int DANLERS_LTD = 0x00E1;
public static final int SEMILINK_INC = 0x00E2;
public static final int INMUSIC_BRANDS_INC = 0x00E3;
public static final int LS_RESEARCH_INC = 0x00E4;
public static final int EDEN_SOFTWARE_CONSULTANTS_LTD = 0x00E5;
public static final int FRESHTEMP = 0x00E6;
public static final int KS_TECHNOLOGIES = 0x00E7;
public static final int ACTS_TECHNOLOGIES = 0x00E8;
public static final int VTRACK_SYSTEMS = 0x00E9;
public static final int NIELSENKELLERMAN_COMPANY = 0x00EA;
public static final int SERVER_TECHNOLOGY_INC = 0x00EB;
public static final int BIORESEARCH_ASSOCIATES = 0x00EC;
public static final int JOLLY_LOGIC_LLC = 0x00ED;
public static final int ABOVE_AVERAGE_OUTCOMES_INC = 0x00EE;
public static final int BITSPLITTERS_GMBH = 0x00EF;
public static final int PAYPAL_INC = 0x00F0;
public static final int WITRON_TECHNOLOGY_LIMITED = 0x00F1;
public static final int MORSE_PROJECT_INC = 0x00F2;
public static final int KENT_DISPLAYS_INC = 0x00F3;
public static final int NAUTILUS_INC = 0x00F4;
public static final int SMARTIFIER_OY = 0x00F5;
public static final int ELCOMETER_LIMITED = 0x00F6;
public static final int VSN_TECHNOLOGIES_INC = 0x00F7;
public static final int ACEUNI_CORP_LTD = 0x00F8;
public static final int STICKNFIND = 0x00F9;
public static final int CRYSTAL_CODE_AB = 0x00FA;
public static final int KOUKAAM_AS = 0x00FB;
public static final int DELPHI_CORPORATION = 0x00FC;
public static final int VALENCETECH_LIMITED = 0x00FD;
public static final int RESERVED = 0x00FE;
public static final int TYPO_PRODUCTS_LLC = 0x00FF;
public static final int TOMTOM_INTERNATIONAL_BV = 0x0100;
public static final int FUGOO_INC = 0x0101;
public static final int KEISER_CORPORATION = 0x0102;
public static final int BANG_OLUFSEN_A_S = 0x0103;
public static final int PLUS_LOCATIONS_SYSTEMS_PTY_LTD = 0x0104;
public static final int UBIQUITOUS_COMPUTING_TECHNOLOGY_CORPORATION = 0x0105;
public static final int INNOVATIVE_YACHTTER_SOLUTIONS = 0x0106;
public static final int WILLIAM_DEMANT_HOLDING_A_S = 0x0107;
public static final int CHICONY_ELECTRONICS_CO_LTD = 0x0108;
public static final int ATUS_BV = 0x0109;
public static final int CODEGATE_LTD = 0x010A;
public static final int ERI_INC = 0x010B;
public static final int TRANSDUCERS_DIRECT_LLC = 0x010C;
public static final int FUJITSU_TEN_LIMITED = 0x010D;
public static final int AUDI_AG = 0x010E;
public static final int HISILICON_TECHNOLOGIES_CO_LTD = 0x010F;
public static final int NIPPON_SEIKI_CO_LTD = 0x0110;
public static final int STEELSERIES_APS = 0x0111;
public static final int VYZYBL_INC = 0x0112;
public static final int OPENBRAIN_TECHNOLOGIES_CO_LTD = 0x0113;
public static final int XENSR = 0x0114;
public static final int ESOLUTIONS = 0x0115;
public static final int ONE_OAK_TECHNOLOGIES = 0x0116;
public static final int WIMOTO_TECHNOLOGIES_INC = 0x0117;
public static final int RADIUS_NETWORKS_INC = 0x0118;
public static final int WIZE_TECHNOLOGY_CO_LTD = 0x0119;
public static final int QUALCOMM_LABS_INC = 0x011A;
public static final int ARUBA_NETWORKS = 0x011B;
public static final int BAIDU = 0x011C;
public static final int ARENDI_AG = 0x011D;
public static final int SKODA_AUTO_AS = 0x011E;
public static final int VOLKSWAGON_AG = 0x011F;
public static final int PORSCHE_AG = 0x0120;
public static final int SINO_WEALTH_ELECTRONIC_LTD = 0x0121;
public static final int AIRTURN_INC = 0x0122;
public static final int KINSA_INC = 0x0123;
public static final int HID_GLOBAL = 0x0124;
public static final int SEAT_ES = 0x0125;
public static final int PROMETHEAN_LTD = 0x0126;
public static final int SALUTICA_ALLIED_SOLUTIONS = 0x0127;
public static final int GPSI_GROUP_PTY_LTD = 0x0128;
public static final int NIMBLE_DEVICES_OY = 0x0129;
public static final int CHANGZHOU_YONGSE_INFOTECH_CO_LTD = 0x012A;
public static final int SPORTIQ = 0x012B;
public static final int TEMEC_INSTRUMENTS_BV = 0x012C;
public static final int SONY_CORPORATION = 0x012D;
public static final int ASSA_ABLOY = 0x012E;
public static final int CLARION_CO_LTD = 0x012F;
public static final int WAREHOUSE_INNOVATIONS = 0x0130;
public static final int CYPRESS_SEMICONDUCTOR_CORPORATION = 0x0131;
public static final int MADS_INC = 0x0132;
public static final int BLUE_MAESTRO_LIMITED = 0x0133;
public static final int RESOLUTION_PRODUCTS_INC = 0x0134;
public static final int AIREWEAR_LLC = 0x0135;
public static final int ETC_SP_ZOO = 0x0136;
public static final int PRESTIGIO_PLAZA_LTD = 0x0137;
private static final SparseArray<String> COMPANY_NAME_MAP = populateCompanyNameMap();
public static String getCompanyName(int companyId, String fallback){
final String name = COMPANY_NAME_MAP.get(companyId);
return name == null ? fallback : name;
}
private static SparseArray<String> populateCompanyNameMap() {
final SparseArray<String> map = new SparseArray<String>();
map.put(ERICSSON_TECHNOLOGY_LICENSING , "Ericsson Technology Licensing");
map.put(NOKIA_MOBILE_PHONES , "Nokia Mobile Phones");
map.put(INTEL_CORP , "Intel Corp.");
map.put(IBM_CORP , "IBM Corp.");
map.put(TOSHIBA_CORP , "Toshiba Corp.");
map.put(THREE_COM , "3Com");
map.put(MICROSOFT , "Microsoft");
map.put(LUCENT , "Lucent");
map.put(MOTOROLA , "Motorola");
map.put(INFINEON_TECHNOLOGIES_AG , "Infineon Technologies AG");
map.put(CAMBRIDGE_SILICON_RADIO , "Cambridge Silicon Radio");
map.put(SILICON_WAVE , "Silicon Wave");
map.put(DIGIANSWER_A_S , "Digianswer A/S");
map.put(TEXAS_INSTRUMENTS_INC , "Texas Instruments Inc.");
map.put(CEVA_INC_FORMERLY_PARTHUS_TECHNOLOGIES_INC , "Ceva, Inc. (formerly Parthus Technologies, Inc.)");
map.put(BROADCOM_CORPORATION , "Broadcom Corporation");
map.put(MITEL_SEMICONDUCTOR , "Mitel Semiconductor");
map.put(WIDCOMM_INC , "Widcomm, Inc");
map.put(ZEEVO_INC , "Zeevo, Inc.");
map.put(ATMEL_CORPORATION , "Atmel Corporation");
map.put(MITSUBISHI_ELECTRIC_CORPORATION , "Mitsubishi Electric Corporation");
map.put(RTX_TELECOM_A_S , "RTX Telecom A/S");
map.put(KC_TECHNOLOGY_INC , "KC Technology Inc.");
map.put(NEWLOGIC , "NewLogic");
map.put(TRANSILICA_INC , "Transilica, Inc.");
map.put(ROHDE_SCHWARZ_GMBH_CO_KG , "Rohde & Schwarz GmbH & Co. KG");
map.put(TTPCOM_LIMITED , "TTPCom Limited");
map.put(SIGNIA_TECHNOLOGIES_INC , "Signia Technologies, Inc.");
map.put(CONEXANT_SYSTEMS_INC , "Conexant Systems Inc.");
map.put(QUALCOMM , "Qualcomm");
map.put(INVENTEL , "Inventel");
map.put(AVM_BERLIN , "AVM Berlin");
map.put(BANDSPEED_INC , "BandSpeed, Inc.");
map.put(MANSELLA_LTD , "Mansella Ltd");
map.put(NEC_CORPORATION , "NEC Corporation");
map.put(WAVEPLUS_TECHNOLOGY_CO_LTD , "WavePlus Technology Co., Ltd.");
map.put(ALCATEL , "Alcatel");
map.put(PHILIPS_SEMICONDUCTORS , "Philips Semiconductors");
map.put(C_TECHNOLOGIES , "C Technologies");
map.put(OPEN_INTERFACE , "Open Interface");
map.put(R_F_MICRO_DEVICES , "R F Micro Devices");
map.put(HITACHI_LTD , "Hitachi Ltd");
map.put(SYMBOL_TECHNOLOGIES_INC , "Symbol Technologies, Inc.");
map.put(TENOVIS , "Tenovis");
map.put(MACRONIX_INTERNATIONAL_CO_LTD , "Macronix International Co. Ltd.");
map.put(GCT_SEMICONDUCTOR , "GCT Semiconductor");
map.put(NORWOOD_SYSTEMS , "Norwood Systems");
map.put(MEWTEL_TECHNOLOGY_INC , "MewTel Technology Inc.");
map.put(ST_MICROELECTRONICS , "ST Microelectronics");
map.put(SYNOPSIS , "Synopsis");
map.put(REDM_COMMUNICATIONS_LTD , "Red-M (Communications) Ltd");
map.put(COMMIL_LTD , "Commil Ltd");
map.put(COMPUTER_ACCESS_TECHNOLOGY_CORPORATION_CATC , "Computer Access Technology Corporation (CATC)");
map.put(ECLIPSE_HQ_ESPANA_SL , "Eclipse (HQ Espana) S.L.");
map.put(RENESAS_TECHNOLOGY_CORP , "Renesas Technology Corp.");
map.put(MOBILIAN_CORPORATION , "Mobilian Corporation");
map.put(TERAX , "Terax");
map.put(INTEGRATED_SYSTEM_SOLUTION_CORP , "Integrated System Solution Corp.");
map.put(MATSUSHITA_ELECTRIC_INDUSTRIAL_CO_LTD , "Matsushita Electric Industrial Co., Ltd.");
map.put(GENNUM_CORPORATION , "Gennum Corporation");
map.put(RESEARCH_IN_MOTION , "Research In Motion");
map.put(IPEXTREME_INC , "IPextreme, Inc.");
map.put(SYSTEMS_AND_CHIPS_INC , "Systems and Chips, Inc.");
map.put(BLUETOOTH_SIG_INC , "Bluetooth SIG, Inc.");
map.put(SEIKO_EPSON_CORPORATION , "Seiko Epson Corporation");
map.put(INTEGRATED_SILICON_SOLUTION_TAIWAN_INC , "Integrated Silicon Solution Taiwan, Inc.");
map.put(CONWISE_TECHNOLOGY_CORPORATION_LTD , "CONWISE Technology Corporation Ltd");
map.put(PARROT_SA , "PARROT SA");
map.put(SOCKET_MOBILE , "Socket Mobile");
map.put(ATHEROS_COMMUNICATIONS_INC , "Atheros Communications, Inc.");
map.put(MEDIATEK_INC , "MediaTek, Inc.");
map.put(BLUEGIGA , "Bluegiga");
map.put(MARVELL_TECHNOLOGY_GROUP_LTD , "Marvell Technology Group Ltd.");
map.put(THREE_DSP_CORPORATION , "3DSP Corporation");
map.put(ACCEL_SEMICONDUCTOR_LTD , "Accel Semiconductor Ltd.");
map.put(CONTINENTAL_AUTOMOTIVE_SYSTEMS , "Continental Automotive Systems");
map.put(APPLE_INC , "Apple, Inc.");
map.put(STACCATO_COMMUNICATIONS_INC , "Staccato Communications, Inc.");
map.put(AVAGO_TECHNOLOGIES , "Avago Technologies");
map.put(APT_LICENSING_LTD , "APT Licensing Ltd.");
map.put(SIRF_TECHNOLOGY , "SiRF Technology");
map.put(TZERO_TECHNOLOGIES_INC , "Tzero Technologies, Inc.");
map.put(JM_CORPORATION , "J&M Corporation");
map.put(FREE2MOVE_AB , "Free2move AB");
map.put(THREE_DIJOY_CORPORATION , "3DiJoy Corporation");
map.put(PLANTRONICS_INC , "Plantronics, Inc.");
map.put(SONY_ERICSSON_MOBILE_COMMUNICATIONS , "Sony Ericsson Mobile Communications");
map.put(HARMAN_INTERNATIONAL_INDUSTRIES_INC , "Harman International Industries, Inc.");
map.put(VIZIO_INC , "Vizio, Inc.");
map.put(NORDIC_SEMICONDUCTOR_ASA , "Nordic Semiconductor ASA");
map.put(EM_MICROELECTRONICMARIN_SA , "EM Microelectronic-Marin SA");
map.put(RALINK_TECHNOLOGY_CORPORATION , "Ralink Technology Corporation");
map.put(BELKIN_INTERNATIONAL_INC , "Belkin International, Inc.");
map.put(REALTEK_SEMICONDUCTOR_CORPORATION , "Realtek Semiconductor Corporation");
map.put(STONESTREET_ONE_LLC , "Stonestreet One, LLC");
map.put(WICENTRIC_INC , "Wicentric, Inc.");
map.put(RIVIERAWAVES_SAS , "RivieraWaves S.A.S");
map.put(RDA_MICROELECTRONICS , "RDA Microelectronics");
map.put(GIBSON_GUITARS , "Gibson Guitars");
map.put(MICOMMAND_INC , "MiCommand Inc.");
map.put(BAND_XI_INTERNATIONAL_LLC , "Band XI International, LLC");
map.put(HEWLETTPACKARD_COMPANY , "Hewlett-Packard Company");
map.put(NINE_SOLUTIONS_OY , "9Solutions Oy");
map.put(GN_NETCOM_A_S , "GN Netcom A/S");
map.put(GENERAL_MOTORS , "General Motors");
map.put(AD_ENGINEERING_INC , "A&D Engineering, Inc.");
map.put(MINDTREE_LTD , "MindTree Ltd.");
map.put(POLAR_ELECTRO_OY , "Polar Electro OY");
map.put(BEAUTIFUL_ENTERPRISE_CO_LTD , "Beautiful Enterprise Co., Ltd.");
map.put(BRIARTEK_INC , "BriarTek, Inc.");
map.put(SUMMIT_DATA_COMMUNICATIONS_INC , "Summit Data Communications, Inc.");
map.put(SOUND_ID , "Sound ID");
map.put(MONSTER_LLC , "Monster, LLC");
map.put(CONNECTBLUE_AB , "connectBlue AB");
map.put(SHANGHAI_SUPER_SMART_ELECTRONICS_CO_LTD , "ShangHai Super Smart Electronics Co. Ltd.");
map.put(GROUP_SENSE_LTD , "Group Sense Ltd.");
map.put(ZOMM_LLC , "Zomm, LLC");
map.put(SAMSUNG_ELECTRONICS_CO_LTD , "Samsung Electronics Co. Ltd.");
map.put(CREATIVE_TECHNOLOGY_LTD , "Creative Technology Ltd.");
map.put(LAIRD_TECHNOLOGIES , "Laird Technologies");
map.put(NIKE_INC , "Nike, Inc.");
map.put(LESSWIRE_AG , "lesswire AG");
map.put(MSTAR_SEMICONDUCTOR_INC , "MStar Semiconductor, Inc.");
map.put(HANLYNN_TECHNOLOGIES , "Hanlynn Technologies");
map.put(A_R_CAMBRIDGE , "A & R Cambridge");
map.put(SEERS_TECHNOLOGY_CO_LTD , "Seers Technology Co. Ltd");
map.put(SPORTS_TRACKING_TECHNOLOGIES_LTD , "Sports Tracking Technologies Ltd.");
map.put(AUTONET_MOBILE , "Autonet Mobile");
map.put(DELORME_PUBLISHING_COMPANY_INC , "DeLorme Publishing Company, Inc.");
map.put(WUXI_VIMICRO , "WuXi Vimicro");
map.put(SENNHEISER_COMMUNICATIONS_A_S , "Sennheiser Communications A/S");
map.put(TIMEKEEPING_SYSTEMS_INC , "TimeKeeping Systems, Inc.");
map.put(LUDUS_HELSINKI_LTD , "Ludus Helsinki Ltd.");
map.put(BLUERADIOS_INC , "BlueRadios, Inc.");
map.put(EQUINOX_AG , "equinox AG");
map.put(GARMIN_INTERNATIONAL_INC , "Garmin International, Inc.");
map.put(ECOTEST , "Ecotest");
map.put(GN_RESOUND_A_S , "GN ReSound A/S");
map.put(JAWBONE , "Jawbone");
map.put(TOPCORN_POSITIONING_SYSTEMS_LLC , "Topcorn Positioning Systems, LLC");
map.put(QUALCOMM_RETAIL_SOLUTIONS_INC_FORMERLY_QUALCOMM_LABS_INC , "Qualcomm Retail Solutions, Inc. (formerly Qualcomm Labs, Inc.)");
map.put(ZSCAN_SOFTWARE , "Zscan Software");
map.put(QUINTIC_CORP , "Quintic Corp.");
map.put(STOLLMAN_EV_GMBH , "Stollman E+V GmbH");
map.put(FUNAI_ELECTRIC_CO_LTD , "Funai Electric Co., Ltd.");
map.put(ADVANCED_PANMOBIL_SYSTEMS_GMBH_CO_KG , "Advanced PANMOBIL Systems GmbH & Co. KG");
map.put(THINKOPTICS_INC , "ThinkOptics, Inc.");
map.put(UNIVERSAL_ELECTRONICS_INC , "Universal Electronics, Inc.");
map.put(AIROHA_TECHNOLOGY_CORP , "Airoha Technology Corp.");
map.put(NEC_LIGHTING_LTD , "NEC Lighting, Ltd.");
map.put(ODM_TECHNOLOGY_INC , "ODM Technology, Inc.");
map.put(CONNECTEDEVICE_LTD , "ConnecteDevice Ltd.");
map.put(ZER01TV_GMBH , "zer01.tv GmbH");
map.put(ITECH_DYNAMIC_GLOBAL_DISTRIBUTION_LTD , "i.Tech Dynamic Global Distribution Ltd.");
map.put(ALPWISE , "Alpwise");
map.put(JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS_CO_LTD , "Jiangsu Toppower Automotive Electronics Co., Ltd.");
map.put(COLORFY_INC , "Colorfy, Inc.");
map.put(GEOFORCE_INC , "Geoforce Inc.");
map.put(BOSE_CORPORATION , "Bose Corporation");
map.put(SUUNTO_OY , "Suunto Oy");
map.put(KENSINGTON_COMPUTER_PRODUCTS_GROUP , "Kensington Computer Products Group");
map.put(SRMEDIZINELEKTRONIK , "SR-Medizinelektronik");
map.put(VERTU_CORPORATION_LIMITED , "Vertu Corporation Limited");
map.put(META_WATCH_LTD , "Meta Watch Ltd.");
map.put(LINAK_A_S , "LINAK A/S");
map.put(OTL_DYNAMICS_LLC , "OTL Dynamics LLC");
map.put(PANDA_OCEAN_INC , "Panda Ocean Inc.");
map.put(VISTEON_CORPORATION , "Visteon Corporation");
map.put(ARP_DEVICES_LIMITED , "ARP Devices Limited");
map.put(MAGNETI_MARELLI_SPA , "Magneti Marelli S.p.A");
map.put(CAEN_RFID_SRL , "CAEN RFID srl");
map.put(INGENIEURSYSTEMGRUPPE_ZAHN_GMBH , "Ingenieur-Systemgruppe Zahn GmbH");
map.put(GREEN_THROTTLE_GAMES , "Green Throttle Games");
map.put(PETER_SYSTEMTECHNIK_GMBH , "Peter Systemtechnik GmbH");
map.put(OMEGAWAVE_OY , "Omegawave Oy");
map.put(CINETIX , "Cinetix");
map.put(PASSIF_SEMICONDUCTOR_CORP , "Passif Semiconductor Corp");
map.put(SARIS_CYCLING_GROUP_INC , "Saris Cycling Group, Inc");
map.put(BEKEY_A_S , "Bekey A/S");
map.put(CLARINOX_TECHNOLOGIES_PTY_LTD , "Clarinox Technologies Pty. Ltd.");
map.put(BDE_TECHNOLOGY_CO_LTD , "BDE Technology Co., Ltd.");
map.put(SWIRL_NETWORKS , "Swirl Networks");
map.put(MESO_INTERNATIONAL , "Meso international");
map.put(TRELAB_LTD , "TreLab Ltd");
map.put(QUALCOMM_INNOVATION_CENTER_INC_QUIC , "Qualcomm Innovation Center, Inc. (QuIC)");
map.put(JOHNSON_CONTROLS_INC , "Johnson Controls, Inc.");
map.put(STARKEY_LABORATORIES_INC , "Starkey Laboratories Inc.");
map.put(SPOWER_ELECTRONICS_LIMITED , "S-Power Electronics Limited");
map.put(ACE_SENSOR_INC , "Ace Sensor Inc");
map.put(APLIX_CORPORATION , "Aplix Corporation");
map.put(AAMP_OF_AMERICA , "AAMP of America");
map.put(STALMART_TECHNOLOGY_LIMITED , "Stalmart Technology Limited");
map.put(AMICCOM_ELECTRONICS_CORPORATION , "AMICCOM Electronics Corporation");
map.put(SHENZHEN_EXCELSECU_DATA_TECHNOLOGY_COLTD , "Shenzhen Excelsecu Data Technology Co.,Ltd");
map.put(GENEQ_INC , "Geneq Inc.");
map.put(ADIDAS_AG , "adidas AG");
map.put(LG_ELECTRONICS , "LG Electronics");
map.put(ONSET_COMPUTER_CORPORATION , "Onset Computer Corporation");
map.put(SELFLY_BV , "Selfly BV");
map.put(QUUPPA_OY , "Quuppa Oy.");
map.put(GELO_INC , "GeLo Inc");
map.put(EVLUMA , "Evluma");
map.put(MC10 , "MC10");
map.put(BINAURIC_SE , "Binauric SE");
map.put(BEATS_ELECTRONICS , "Beats Electronics");
map.put(MICROCHIP_TECHNOLOGY_INC , "Microchip Technology Inc.");
map.put(ELGATO_SYSTEMS_GMBH , "Elgato Systems GmbH");
map.put(ARCHOS_SA , "ARCHOS SA");
map.put(DEXCOM_INC , "Dexcom, Inc.");
map.put(POLAR_ELECTRO_EUROPE_BV , "Polar Electro Europe B.V.");
map.put(DIALOG_SEMICONDUCTOR_BV , "Dialog Semiconductor B.V.");
map.put(TAIXINGBANG_TECHNOLOGY_HK_CO_LTD , "Taixingbang Technology (HK) Co,. LTD.");
map.put(KAWANTECH , "Kawantech");
map.put(AUSTCO_COMMUNICATION_SYSTEMS , "Austco Communication Systems");
map.put(TIMEX_GROUP_USA_INC , "Timex Group USA, Inc.");
map.put(QUALCOMM_TECHNOLOGIES_INC , "Qualcomm Technologies, Inc.");
map.put(QUALCOMM_CONNECTED_EXPERIENCES_INC , "Qualcomm Connected Experiences, Inc.");
map.put(VOYETRA_TURTLE_BEACH , "Voyetra Turtle Beach");
map.put(TXTR_GMBH , "txtr GmbH");
map.put(BIOSENTRONICS , "Biosentronics");
map.put(PROCTER_GAMBLE , "Procter & Gamble");
map.put(HOSIDEN_CORPORATION , "Hosiden Corporation");
map.put(MUZIK_LLC , "Muzik LLC");
map.put(MISFIT_WEARABLES_CORP , "Misfit Wearables Corp");
map.put(GOOGLE , "Google");
map.put(DANLERS_LTD , "Danlers Ltd");
map.put(SEMILINK_INC , "Semilink Inc");
map.put(INMUSIC_BRANDS_INC , "inMusic Brands, Inc");
map.put(LS_RESEARCH_INC , "L.S. Research Inc.");
map.put(EDEN_SOFTWARE_CONSULTANTS_LTD , "Eden Software Consultants Ltd.");
map.put(FRESHTEMP , "Freshtemp");
map.put(KS_TECHNOLOGIES , "KS Technologies");
map.put(ACTS_TECHNOLOGIES , "ACTS Technologies");
map.put(VTRACK_SYSTEMS , "Vtrack Systems");
map.put(NIELSENKELLERMAN_COMPANY , "Nielsen-Kellerman Company");
map.put(SERVER_TECHNOLOGY_INC , "Server Technology, Inc.");
map.put(BIORESEARCH_ASSOCIATES , "BioResearch Associates");
map.put(JOLLY_LOGIC_LLC , "Jolly Logic, LLC");
map.put(ABOVE_AVERAGE_OUTCOMES_INC , "Above Average Outcomes, Inc.");
map.put(BITSPLITTERS_GMBH , "Bitsplitters GmbH");
map.put(PAYPAL_INC , "PayPal, Inc.");
map.put(WITRON_TECHNOLOGY_LIMITED , "Witron Technology Limited");
map.put(MORSE_PROJECT_INC , "Morse Project Inc.");
map.put(KENT_DISPLAYS_INC , "Kent Displays Inc.");
map.put(NAUTILUS_INC , "Nautilus Inc.");
map.put(SMARTIFIER_OY , "Smartifier Oy");
map.put(ELCOMETER_LIMITED , "Elcometer Limited");
map.put(VSN_TECHNOLOGIES_INC , "VSN Technologies Inc.");
map.put(ACEUNI_CORP_LTD , "AceUni Corp., Ltd.");
map.put(STICKNFIND , "StickNFind");
map.put(CRYSTAL_CODE_AB , "Crystal Code AB");
map.put(KOUKAAM_AS , "KOUKAAM a.s.");
map.put(DELPHI_CORPORATION , "Delphi Corporation");
map.put(VALENCETECH_LIMITED , "ValenceTech Limited");
map.put(RESERVED , "Reserved");
map.put(TYPO_PRODUCTS_LLC , "Typo Products, LLC");
map.put(TOMTOM_INTERNATIONAL_BV , "TomTom International BV");
map.put(FUGOO_INC , "Fugoo, Inc");
map.put(KEISER_CORPORATION , "Keiser Corporation");
map.put(BANG_OLUFSEN_A_S , "Bang & Olufsen A/S");
map.put(PLUS_LOCATIONS_SYSTEMS_PTY_LTD , "PLUS Locations Systems Pty Ltd");
map.put(UBIQUITOUS_COMPUTING_TECHNOLOGY_CORPORATION , "Ubiquitous Computing Technology Corporation");
map.put(INNOVATIVE_YACHTTER_SOLUTIONS , "Innovative Yachtter Solutions");
map.put(WILLIAM_DEMANT_HOLDING_A_S , "William Demant Holding A/S");
map.put(CHICONY_ELECTRONICS_CO_LTD , "Chicony Electronics Co., Ltd.");
map.put(ATUS_BV , "Atus BV");
map.put(CODEGATE_LTD , "Codegate Ltd.");
map.put(ERI_INC , "ERi, Inc.");
map.put(TRANSDUCERS_DIRECT_LLC , "Transducers Direct, LLC");
map.put(FUJITSU_TEN_LIMITED , "Fujitsu Ten Limited");
map.put(AUDI_AG , "Audi AG");
map.put(HISILICON_TECHNOLOGIES_CO_LTD , "HiSilicon Technologies Co., Ltd.");
map.put(NIPPON_SEIKI_CO_LTD , "Nippon Seiki Co., Ltd.");
map.put(STEELSERIES_APS , "Steelseries ApS");
map.put(VYZYBL_INC , "vyzybl Inc.");
map.put(OPENBRAIN_TECHNOLOGIES_CO_LTD , "Openbrain Technologies, Co., Ltd.");
map.put(XENSR , "Xensr");
map.put(ESOLUTIONS , "e.solutions");
map.put(ONE_OAK_TECHNOLOGIES , "1OAK Technologies");
map.put(WIMOTO_TECHNOLOGIES_INC , "Wimoto Technologies Inc");
map.put(RADIUS_NETWORKS_INC , "Radius Networks, Inc.");
map.put(WIZE_TECHNOLOGY_CO_LTD , "Wize Technology Co., Ltd.");
map.put(QUALCOMM_LABS_INC , "Qualcomm Labs, Inc.");
map.put(ARUBA_NETWORKS , "Aruba Networks");
map.put(BAIDU , "Baidu");
map.put(ARENDI_AG , "Arendi AG");
map.put(SKODA_AUTO_AS , "Skoda Auto a.s.");
map.put(VOLKSWAGON_AG , "Volkswagon AG");
map.put(PORSCHE_AG , "Porsche AG");
map.put(SINO_WEALTH_ELECTRONIC_LTD , "Sino Wealth Electronic Ltd.");
map.put(AIRTURN_INC , "AirTurn, Inc.");
map.put(KINSA_INC , "Kinsa, Inc.");
map.put(HID_GLOBAL , "HID Global");
map.put(SEAT_ES , "SEAT es");
map.put(PROMETHEAN_LTD , "Promethean Ltd.");
map.put(SALUTICA_ALLIED_SOLUTIONS , "Salutica Allied Solutions");
map.put(GPSI_GROUP_PTY_LTD , "GPSI Group Pty Ltd");
map.put(NIMBLE_DEVICES_OY , "Nimble Devices Oy");
map.put(CHANGZHOU_YONGSE_INFOTECH_CO_LTD , "Changzhou Yongse Infotech Co., Ltd");
map.put(SPORTIQ , "SportIQ");
map.put(TEMEC_INSTRUMENTS_BV , "TEMEC Instruments B.V.");
map.put(SONY_CORPORATION , "Sony Corporation");
map.put(ASSA_ABLOY , "ASSA ABLOY");
map.put(CLARION_CO_LTD , "Clarion Co., Ltd.");
map.put(WAREHOUSE_INNOVATIONS , "Warehouse Innovations");
map.put(CYPRESS_SEMICONDUCTOR_CORPORATION , "Cypress Semiconductor Corporation");
map.put(MADS_INC , "MADS Inc");
map.put(BLUE_MAESTRO_LIMITED , "Blue Maestro Limited");
map.put(RESOLUTION_PRODUCTS_INC , "Resolution Products, Inc.");
map.put(AIREWEAR_LLC , "Airewear LLC");
map.put(ETC_SP_ZOO , "ETC sp. z.o.o.");
map.put(PRESTIGIO_PLAZA_LTD , "Prestigio Plaza Ltd.");
return map;
}
}

View File

@@ -1,386 +0,0 @@
package uk.co.alt236.bluetoothlelib.resolvers;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
*
* The UUIDS have been collected from the following sources:
*
* - http://developer.nokia.com/community/wiki/Bluetooth_Services_for_Windows_Phone
* - The Bluez project
*
* @author Alexandros Schillings
*
*/
public class GattAttributeResolver {
public static final String BASE_GUID = "00000001-0000-1000-8000-00805f9b34fb";
public static final String SERVICE_DISCOVERY_PROTOCOL_SDP = "00000002-0000-1000-8000-00805f9b34fb";
public static final String USER_DATAGRAM_PROTOCOL_UDP = "00000003-0000-1000-8000-00805f9b34fb";
public static final String RADIO_FREQUENCY_COMMUNICATION_PROTOCOL_RFCOMM = "00000004-0000-1000-8000-00805f9b34fb";
public static final String TCP = "00000005-0000-1000-8000-00805f9b34fb";
public static final String TCSBIN = "00000006-0000-1000-8000-00805f9b34fb";
public static final String TCSAT = "00000008-0000-1000-8000-00805f9b34fb";
public static final String OBJECT_EXCHANGE_PROTOCOL_OBEX = "00000009-0000-1000-8000-00805f9b34fb";
public static final String IP = "0000000a-0000-1000-8000-00805f9b34fb";
public static final String FTP = "0000000c-0000-1000-8000-00805f9b34fb";
public static final String HTTP = "0000000e-0000-1000-8000-00805f9b34fb";
public static final String WSP = "0000000f-0000-1000-8000-00805f9b34fb";
public static final String BNEP_SVC = "00000010-0000-1000-8000-00805f9b34fb";
public static final String UPNP_PROTOCOL = "00000011-0000-1000-8000-00805f9b34fb";
public static final String HIDP = "00000012-0000-1000-8000-00805f9b34fb";
public static final String HARDCOPY_CONTROL_CHANNEL_PROTOCOL = "00000014-0000-1000-8000-00805f9b34fb";
public static final String HARDCOPY_DATA_CHANNEL_PROTOCOL = "00000016-0000-1000-8000-00805f9b34fb";
public static final String HARDCOPY_NOTIFICATION_PROTOCOL = "00000017-0000-1000-8000-00805f9b34fb";
public static final String VCTP_PROTOCOL = "00000019-0000-1000-8000-00805f9b34fb";
public static final String VDTP_PROTOCOL = "0000001b-0000-1000-8000-00805f9b34fb";
public static final String CMPT_PROTOCOL = "0000001d-0000-1000-8000-00805f9b34fb";
public static final String UDI_C_PLANE_PROTOCOL = "0000001e-0000-1000-8000-00805f9b34fb";
public static final String MCAP_CONTROL_CHANNEL = "0000001f-0000-1000-8000-00805f9b34fb";
public static final String MCAP_DATA_CHANNEL = "00000100-0000-1000-8000-00805f9b34fb";
public static final String L2CAP = "00001000-0000-1000-8000-00805f9b34fb";
public static final String SERVICE_DISCOVERY_SERVER = "00001001-0000-1000-8000-00805f9b34fb";
public static final String BROWSE_GROUP_DESCRIPTOR = "00001002-0000-1000-8000-00805f9b34fb";
public static final String PUBLIC_BROWSE_GROUP = "00001101-0000-1000-8000-00805f9b34fb";
public static final String SPP = "00001102-0000-1000-8000-00805f9b34fb";
public static final String LAN_ACCESS_USING_PPP = "00001103-0000-1000-8000-00805f9b34fb";
public static final String DUN_GW = "00001104-0000-1000-8000-00805f9b34fb";
public static final String OBEX_SYNC = "00001105-0000-1000-8000-00805f9b34fb";
public static final String OBEX_OBJECT_PUSH = "00001106-0000-1000-8000-00805f9b34fb";
public static final String OBEX_FILE_TRANSFER = "00001107-0000-1000-8000-00805f9b34fb";
public static final String IRMC_SYNC_COMMAND = "00001108-0000-1000-8000-00805f9b34fb";
public static final String HSP_HS = "00001109-0000-1000-8000-00805f9b34fb";
public static final String CORDLESS_TELEPHONY = "0000110a-0000-1000-8000-00805f9b34fb";
public static final String AUDIO_SOURCE = "0000110b-0000-1000-8000-00805f9b34fb";
public static final String AUDIO_SINK = "0000110c-0000-1000-8000-00805f9b34fb";
public static final String AV_REMOTE_CONTROL_TARGET = "0000110d-0000-1000-8000-00805f9b34fb";
public static final String ADVANCED_AUDIO = "0000110e-0000-1000-8000-00805f9b34fb";
public static final String AVRCP_REMOTE = "0000110f-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_CONFERENCING = "00001110-0000-1000-8000-00805f9b34fb";
public static final String INTERCOM = "00001111-0000-1000-8000-00805f9b34fb";
public static final String FAX = "00001112-0000-1000-8000-00805f9b34fb";
public static final String HEADSET_PROFILE_HSP_AUDIO_GATEWAY = "00001113-0000-1000-8000-00805f9b34fb";
public static final String WAP = "00001114-0000-1000-8000-00805f9b34fb";
public static final String WAP_CLIENT = "00001115-0000-1000-8000-00805f9b34fb";
public static final String PANU = "00001116-0000-1000-8000-00805f9b34fb";
public static final String NAP = "00001117-0000-1000-8000-00805f9b34fb";
public static final String GN = "00001118-0000-1000-8000-00805f9b34fb";
public static final String DIRECT_PRINTING = "00001119-0000-1000-8000-00805f9b34fb";
public static final String REFERENCE_PRINTING = "0000111a-0000-1000-8000-00805f9b34fb";
public static final String IMAGING = "0000111b-0000-1000-8000-00805f9b34fb";
public static final String IMAGING_RESPONDER = "0000111c-0000-1000-8000-00805f9b34fb";
public static final String IMAGING_AUTOMATIC_ARCHIVE = "0000111d-0000-1000-8000-00805f9b34fb";
public static final String IMAGING_REFERENCE_OBJECTS = "0000111e-0000-1000-8000-00805f9b34fb";
public static final String HANDS_FREE_PROFILE_HFP = "0000111f-0000-1000-8000-00805f9b34fb";
public static final String HANDS_FREE_PROFILE_HFP_AUDIO_GATEWAY = "00001120-0000-1000-8000-00805f9b34fb";
public static final String DIRECT_PRINTING_REFERENCE_OBJECTS = "00001121-0000-1000-8000-00805f9b34fb";
public static final String REFLECTED_UI = "00001122-0000-1000-8000-00805f9b34fb";
public static final String BASIC_PRINTING = "00001123-0000-1000-8000-00805f9b34fb";
public static final String PRINTING_STATUS = "00001124-0000-1000-8000-00805f9b34fb";
public static final String HID = "00001125-0000-1000-8000-00805f9b34fb";
public static final String HARDCOPY_CABLE_REPLACEMENT = "00001126-0000-1000-8000-00805f9b34fb";
public static final String HCR_PRINT = "00001127-0000-1000-8000-00805f9b34fb";
public static final String HCR_SCAN = "00001128-0000-1000-8000-00805f9b34fb";
public static final String COMMON_ISDN_ACCESS = "00001129-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_CONFERENCING_GATEWAY = "0000112a-0000-1000-8000-00805f9b34fb";
public static final String UDIMT = "0000112b-0000-1000-8000-00805f9b34fb";
public static final String UDITA = "0000112c-0000-1000-8000-00805f9b34fb";
public static final String AUDIO_VIDEO = "0000112d-0000-1000-8000-00805f9b34fb";
public static final String SIM_ACCESS = "0000112e-0000-1000-8000-00805f9b34fb";
public static final String OBEX_PCE = "0000112f-0000-1000-8000-00805f9b34fb";
public static final String OBEX_PSE = "00001130-0000-1000-8000-00805f9b34fb";
public static final String OBEX_PBAP = "00001132-0000-1000-8000-00805f9b34fb";
public static final String OBEX_MAS = "00001133-0000-1000-8000-00805f9b34fb";
public static final String OBEX_MNS = "00001134-0000-1000-8000-00805f9b34fb";
public static final String OBEX_MAP = "00001200-0000-1000-8000-00805f9b34fb";
public static final String PNP = "00001201-0000-1000-8000-00805f9b34fb";
public static final String GENERIC_NETWORKING = "00001202-0000-1000-8000-00805f9b34fb";
public static final String GENERIC_FILE_TRANSFER = "00001203-0000-1000-8000-00805f9b34fb";
public static final String GENERIC_AUDIO = "00001204-0000-1000-8000-00805f9b34fb";
public static final String GENERIC_TELEPHONY = "00001205-0000-1000-8000-00805f9b34fb";
public static final String UPNP = "00001206-0000-1000-8000-00805f9b34fb";
public static final String UPNP_IP = "00001300-0000-1000-8000-00805f9b34fb";
public static final String ESDP_UPNP_IP_PAN = "00001301-0000-1000-8000-00805f9b34fb";
public static final String ESDP_UPNP_IP_LAP = "00001302-0000-1000-8000-00805f9b34fb";
public static final String ESDP_UPNP_L2CAP = "00001303-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_DISTRIBUTION_PROFILE_VDP_SOURCE = "00001304-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_DISTRIBUTION_PROFILE_VDP_SINK = "00001305-0000-1000-8000-00805f9b34fb";
public static final String VIDEO_DISTRIBUTION_PROFILE_VDP = "00001400-0000-1000-8000-00805f9b34fb";
public static final String HEALTH_DEVICE_PROFILE_HDP = "00001401-0000-1000-8000-00805f9b34fb";
public static final String HEALTH_DEVICE_PROFILE_HDP_SOURCE = "00001402-0000-1000-8000-00805f9b34fb";
public static final String HEALTH_DEVICE_PROFILE_HDP_SINK = "00001800-0000-1000-8000-00805f9b34fb";
public static final String GAP = "00001801-0000-1000-8000-00805f9b34fb";
public static final String GATT = "00001802-0000-1000-8000-00805f9b34fb";
public static final String IMMEDIATE_ALERT = "00001803-0000-1000-8000-00805f9b34fb";
public static final String LINK_LOSS = "00001804-0000-1000-8000-00805f9b34fb";
public static final String TX_POWER = "00001809-0000-1000-8000-00805f9b34fb";
public static final String HEALTH_THERMOMETER = "0000180a-0000-1000-8000-00805f9b34fb";
public static final String DEVICE_INFORMATION = "0000180d-0000-1000-8000-00805f9b34fb";
public static final String HEART_RATE = "00001816-0000-1000-8000-00805f9b34fb";
public static final String CYCLING_SC = "00002902-0000-1000-8000-00805f9b34fb";
public static final String CLIENT_CHARACTERISTIC_CONFIG = "00002a00-0000-1000-8000-00805f9b34fb";
public static final String DEVICE_NAME = "00002a01-0000-1000-8000-00805f9b34fb";
public static final String APPEARANCE = "00002a02-0000-1000-8000-00805f9b34fb";
public static final String PERIPHERAL_PRIVACY_FLAG = "00002a03-0000-1000-8000-00805f9b34fb";
public static final String RECONNECTION_ADDRESS = "00002a04-0000-1000-8000-00805f9b34fb";
public static final String PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS = "00002a05-0000-1000-8000-00805f9b34fb";
public static final String SERVICE_CHANGED = "00002a06-0000-1000-8000-00805f9b34fb";
public static final String ALERT_LEVEL = "00002a07-0000-1000-8000-00805f9b34fb";
public static final String TX_POWER_LEVEL = "00002a08-0000-1000-8000-00805f9b34fb";
public static final String DATE_TIME = "00002a09-0000-1000-8000-00805f9b34fb";
public static final String DAY_OF_WEEK = "00002a0a-0000-1000-8000-00805f9b34fb";
public static final String DAY_DATE_TIME = "00002a0c-0000-1000-8000-00805f9b34fb";
public static final String EXACT_TIME_256 = "00002a0d-0000-1000-8000-00805f9b34fb";
public static final String DST_OFFSET = "00002a0e-0000-1000-8000-00805f9b34fb";
public static final String TIME_ZONE = "00002a0f-0000-1000-8000-00805f9b34fb";
public static final String LOCAL_TIME_INFORMATION = "00002a11-0000-1000-8000-00805f9b34fb";
public static final String TIME_WITH_DST = "00002a12-0000-1000-8000-00805f9b34fb";
public static final String TIME_ACCURACY = "00002a13-0000-1000-8000-00805f9b34fb";
public static final String TIME_SOURCE = "00002a14-0000-1000-8000-00805f9b34fb";
public static final String REFERENCE_TIME_INFORMATION = "00002a16-0000-1000-8000-00805f9b34fb";
public static final String TIME_UPDATE_CONTROL_POINT = "00002a17-0000-1000-8000-00805f9b34fb";
public static final String TIME_UPDATE_STATE = "00002a1c-0000-1000-8000-00805f9b34fb";
public static final String TEMPERATURE_MEASUREMENT = "00002a1d-0000-1000-8000-00805f9b34fb";
public static final String TEMPERATURE_TYPE = "00002a1e-0000-1000-8000-00805f9b34fb";
public static final String INTERMEDIATE_TEMPERATURE = "00002a21-0000-1000-8000-00805f9b34fb";
public static final String MEASUREMENT_INTERVAL = "00002a23-0000-1000-8000-00805f9b34fb";
public static final String SYSTEM_ID = "00002a24-0000-1000-8000-00805f9b34fb";
public static final String MODEL_NUMBER_STRING = "00002a25-0000-1000-8000-00805f9b34fb";
public static final String SERIAL_NUMBER_STRING = "00002a26-0000-1000-8000-00805f9b34fb";
public static final String FIRMWARE_REVISION_STRING = "00002a27-0000-1000-8000-00805f9b34fb";
public static final String HARDWARE_REVISION_STRING = "00002a28-0000-1000-8000-00805f9b34fb";
public static final String SOFTWARE_REVISION_STRING = "00002a29-0000-1000-8000-00805f9b34fb";
public static final String MANUFACTURER_NAME_STRING = "00002a2a-0000-1000-8000-00805f9b34fb";
public static final String IEEE_1107320601_REGULATORY = "00002a2b-0000-1000-8000-00805f9b34fb";
public static final String CURRENT_TIME = "00002a35-0000-1000-8000-00805f9b34fb";
public static final String BLOOD_PRESSURE_MEASUREMENT = "00002a36-0000-1000-8000-00805f9b34fb";
public static final String INTERMEDIATE_CUFF_PRESSURE = "00002a37-0000-1000-8000-00805f9b34fb";
public static final String HEART_RATE_MEASUREMENT = "00002a38-0000-1000-8000-00805f9b34fb";
public static final String BODY_SENSOR_LOCATION = "00002a39-0000-1000-8000-00805f9b34fb";
public static final String HEART_RATE_CONTROL_POINT = "00002a3f-0000-1000-8000-00805f9b34fb";
public static final String ALERT_STATUS = "00002a40-0000-1000-8000-00805f9b34fb";
public static final String RINGER_CONTROL_POINT = "00002a41-0000-1000-8000-00805f9b34fb";
public static final String RINGER_SETTING = "00002a42-0000-1000-8000-00805f9b34fb";
public static final String ALERT_CATEGORY_ID_BIT_MASK = "00002a43-0000-1000-8000-00805f9b34fb";
public static final String ALERT_CATEGORY_ID = "00002a44-0000-1000-8000-00805f9b34fb";
public static final String ALERT_NOTIFICATION_CONTROL_POINT = "00002a45-0000-1000-8000-00805f9b34fb";
public static final String UNREAD_ALERT_STATUS = "00002a46-0000-1000-8000-00805f9b34fb";
public static final String NEW_ALERT = "00002a47-0000-1000-8000-00805f9b34fb";
public static final String SUPPORTED_NEW_ALERT_CATEGORY = "00002a48-0000-1000-8000-00805f9b34fb";
public static final String SUPPORTED_UNREAD_ALERT_CATEGORY = "00002a49-0000-1000-8000-00805f9b34fb";
public static final String BLOOD_PRESSURE_FEATURE = "00002a50-0000-1000-8000-00805f9b34fb";
public static final String PNPID = "00002a55-0000-1000-8000-00805f9b34fb";
public static final String SC_CONTROL_POINT = "00002a5b-0000-1000-8000-00805f9b34fb";
public static final String CSC_MEASUREMENT = "00002a5c-0000-1000-8000-00805f9b34fb";
public static final String CSC_FEATURE = "00002a5d-0000-1000-8000-00805f9b34fb";
public static final String SENSOR_LOCATION = "831c4071-7bc8-4a9c-a01c-15df25a4adbc";
public static final String ACTIVESYNC = "831c4071-7bc8-4a9c-a01c-15df25a4adbc";
public static final String ESTIMOTE_SERVICE = "b9403000-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_UUID = "b9403003-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_MAJOR = "b9403001-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_MINOR = "b9403002-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_BATTERY = "b9403041-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_TEMPERATURE = "b9403021-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_POWER = "b9403011-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_ADVERTISING_INTERVAL = "b9403012-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_VERSION_SERVICE = "b9404000-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_SOFTWARE_VERSION = "b9404001-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_HARDWARE_VERSION = "b9404002-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_AUTHENTICATION_SERVICE = "b9402000-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_ADVERTISING_SEED = "b9402001-f5f8-466e-aff9-25556b57fe6d";
public static final String ESTIMOTE_ADVERTISING_VECTOR = "b9402002-f5f8-466e-aff9-25556b57fe6d";
private final static Map<String, String> sGattAttributesMap = populateGattAttributesMap();
public static String getAttributeName(String uuid, String fallback){
final String name = sGattAttributesMap.get(uuid.toLowerCase(Locale.US));
return name == null ? fallback : name;
}
private static Map<String, String> populateGattAttributesMap() {
final Map<String, String> map = new HashMap<String, String>();
map.put(BASE_GUID , "Service Discovery Protocol (SDP)");
map.put(SERVICE_DISCOVERY_PROTOCOL_SDP , "User Datagram Protocol (UDP)");
map.put(USER_DATAGRAM_PROTOCOL_UDP , "Radio Frequency Communication Protocol (RFCOMM)");
map.put(RADIO_FREQUENCY_COMMUNICATION_PROTOCOL_RFCOMM , "TCP");
map.put(TCP , "TCSBIN");
map.put(TCSBIN , "TCSAT");
map.put(TCSAT , "Object Exchange Protocol (OBEX)");
map.put(OBJECT_EXCHANGE_PROTOCOL_OBEX , "IP");
map.put(IP , "FTP");
map.put(FTP , "HTTP");
map.put(HTTP , "WSP");
map.put(WSP , "BNEP_SVC");
map.put(BNEP_SVC , "UPNP Protocol");
map.put(UPNP_PROTOCOL , "HIDP");
map.put(HIDP , "Hardcopy Control Channel Protocol");
map.put(HARDCOPY_CONTROL_CHANNEL_PROTOCOL , "Hardcopy Data Channel Protocol");
map.put(HARDCOPY_DATA_CHANNEL_PROTOCOL , "Hardcopy Notification Protocol");
map.put(HARDCOPY_NOTIFICATION_PROTOCOL , "VCTP Protocol");
map.put(VCTP_PROTOCOL , "VDTP Protocol");
map.put(VDTP_PROTOCOL , "CMPT Protocol");
map.put(CMPT_PROTOCOL , "UDI C Plane Protocol");
map.put(UDI_C_PLANE_PROTOCOL , "MCAP Control Channel");
map.put(MCAP_CONTROL_CHANNEL , "MCAP Data Channel");
map.put(MCAP_DATA_CHANNEL , "L2CAP");
map.put(L2CAP , "Service Discovery Server");
map.put(SERVICE_DISCOVERY_SERVER , "Browse Group Descriptor");
map.put(BROWSE_GROUP_DESCRIPTOR , "Public Browse Group");
map.put(PUBLIC_BROWSE_GROUP , "SPP");
map.put(SPP , "LAN Access Using PPP");
map.put(LAN_ACCESS_USING_PPP , "DUN_GW");
map.put(DUN_GW , "OBEX_SYNC");
map.put(OBEX_SYNC , "OBEX Object Push");
map.put(OBEX_OBJECT_PUSH , "OBEX File Transfer");
map.put(OBEX_FILE_TRANSFER , "IrMC Sync Command");
map.put(IRMC_SYNC_COMMAND , "HSP_HS");
map.put(HSP_HS , "Cordless Telephony");
map.put(CORDLESS_TELEPHONY , "Audio Source");
map.put(AUDIO_SOURCE , "Audio Sink");
map.put(AUDIO_SINK , "AV Remote Control Target");
map.put(AV_REMOTE_CONTROL_TARGET , "ADVANCED_AUDIO");
map.put(ADVANCED_AUDIO , "AVRCP_REMOTE");
map.put(AVRCP_REMOTE , "Video Conferencing");
map.put(VIDEO_CONFERENCING , "Intercom");
map.put(INTERCOM , "FAX");
map.put(FAX , "Headset Profile (HSP) - Audio Gateway");
map.put(HEADSET_PROFILE_HSP_AUDIO_GATEWAY , "WAP");
map.put(WAP , "WAP Client");
map.put(WAP_CLIENT , "PANU");
map.put(PANU , "NAP");
map.put(NAP , "GN");
map.put(GN , "Direct Printing");
map.put(DIRECT_PRINTING , "Reference Printing");
map.put(REFERENCE_PRINTING , "Imaging");
map.put(IMAGING , "Imaging Responder");
map.put(IMAGING_RESPONDER , "Imaging Automatic Archive");
map.put(IMAGING_AUTOMATIC_ARCHIVE , "Imaging Reference Objects");
map.put(IMAGING_REFERENCE_OBJECTS , "Hands Free Profile (HFP)");
map.put(HANDS_FREE_PROFILE_HFP , "Hands Free Profile (HFP) Audio Gateway");
map.put(HANDS_FREE_PROFILE_HFP_AUDIO_GATEWAY , "Direct Printing Reference Objects");
map.put(DIRECT_PRINTING_REFERENCE_OBJECTS , "Reflected UI");
map.put(REFLECTED_UI , "Basic Printing");
map.put(BASIC_PRINTING , "Printing Status");
map.put(PRINTING_STATUS , "HID");
map.put(HID , "Hardcopy Cable Replacement");
map.put(HARDCOPY_CABLE_REPLACEMENT , "HCR Print");
map.put(HCR_PRINT , "HCR Scan");
map.put(HCR_SCAN , "Common ISDN Access");
map.put(COMMON_ISDN_ACCESS , "Video Conferencing Gateway");
map.put(VIDEO_CONFERENCING_GATEWAY , "UDIMT");
map.put(UDIMT , "UDITA");
map.put(UDITA , "Audio Video");
map.put(AUDIO_VIDEO , "SIM Access");
map.put(SIM_ACCESS , "OBEX PCE");
map.put(OBEX_PCE , "OBEX PSE");
map.put(OBEX_PSE , "OBEX PBAP");
map.put(OBEX_PBAP , "OBEX MAS");
map.put(OBEX_MAS , "OBEX MNS");
map.put(OBEX_MNS , "OBEX MAP");
map.put(OBEX_MAP , "PNP");
map.put(PNP , "Generic Networking");
map.put(GENERIC_NETWORKING , "Generic File Transfer");
map.put(GENERIC_FILE_TRANSFER , "Generic Audio");
map.put(GENERIC_AUDIO , "Generic Telephony");
map.put(GENERIC_TELEPHONY , "UPNP");
map.put(UPNP , "UPNP IP");
map.put(UPNP_IP , "ESDP UPnP IP PAN");
map.put(ESDP_UPNP_IP_PAN , "ESDP UPnP IP LAP");
map.put(ESDP_UPNP_IP_LAP , "ESDP Upnp L2CAP");
map.put(ESDP_UPNP_L2CAP , "Video Distribution Profile (VDP) - Source");
map.put(VIDEO_DISTRIBUTION_PROFILE_VDP_SOURCE , "Video Distribution Profile (VDP) - Sink");
map.put(VIDEO_DISTRIBUTION_PROFILE_VDP_SINK , "Video Distribution Profile (VDP)");
map.put(VIDEO_DISTRIBUTION_PROFILE_VDP , "Health Device Profile (HDP)");
map.put(HEALTH_DEVICE_PROFILE_HDP , "Health Device Profile (HDP) - Source");
map.put(HEALTH_DEVICE_PROFILE_HDP_SOURCE , "Health Device Profile (HDP) - Sink");
map.put(HEALTH_DEVICE_PROFILE_HDP_SINK , "GAP");
map.put(GAP , "GATT");
map.put(GATT , "IMMEDIATE_ALERT");
map.put(IMMEDIATE_ALERT , "LINK_LOSS");
map.put(LINK_LOSS , "TX_POWER");
map.put(TX_POWER , "Health Thermometer");
map.put(HEALTH_THERMOMETER , "Device Information");
map.put(DEVICE_INFORMATION , "HEART_RATE");
map.put(HEART_RATE , "CYCLING_SC");
map.put(CYCLING_SC , "CLIENT_CHARACTERISTIC_CONFIG");
map.put(CLIENT_CHARACTERISTIC_CONFIG , "Device Name");
map.put(DEVICE_NAME , "Appearance");
map.put(APPEARANCE , "Peripheral Privacy Flag");
map.put(PERIPHERAL_PRIVACY_FLAG , "Reconnection Address");
map.put(RECONNECTION_ADDRESS , "Peripheral Preferred Connection Parameters");
map.put(PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS , "Service Changed");
map.put(SERVICE_CHANGED , "Alert Level");
map.put(ALERT_LEVEL , "Tx Power Level");
map.put(TX_POWER_LEVEL , "Date Time");
map.put(DATE_TIME , "Day of Week");
map.put(DAY_OF_WEEK , "Day Date Time");
map.put(DAY_DATE_TIME , "Exact Time 256");
map.put(EXACT_TIME_256 , "DST Offset");
map.put(DST_OFFSET , "Time Zone");
map.put(TIME_ZONE , "Local Time Information");
map.put(LOCAL_TIME_INFORMATION , "Time with DST");
map.put(TIME_WITH_DST , "Time Accuracy");
map.put(TIME_ACCURACY , "Time Source");
map.put(TIME_SOURCE , "Reference Time Information");
map.put(REFERENCE_TIME_INFORMATION , "Time Update Control Point");
map.put(TIME_UPDATE_CONTROL_POINT , "Time Update State");
map.put(TIME_UPDATE_STATE , "Temperature Measurement");
map.put(TEMPERATURE_MEASUREMENT , "Temperature Type");
map.put(TEMPERATURE_TYPE , "Intermediate Temperature");
map.put(INTERMEDIATE_TEMPERATURE , "Measurement Interval");
map.put(MEASUREMENT_INTERVAL , "System ID");
map.put(SYSTEM_ID , "Model Number String");
map.put(MODEL_NUMBER_STRING , "Serial Number String");
map.put(SERIAL_NUMBER_STRING , "Firmware Revision String");
map.put(FIRMWARE_REVISION_STRING , "Hardware Revision String");
map.put(HARDWARE_REVISION_STRING , "Software Revision String");
map.put(SOFTWARE_REVISION_STRING , "Manufacturer Name String");
map.put(MANUFACTURER_NAME_STRING , "IEEE 11073-20601 Regulatory");
map.put(IEEE_1107320601_REGULATORY , "Current Time");
map.put(CURRENT_TIME , "Blood Pressure Measurement");
map.put(BLOOD_PRESSURE_MEASUREMENT , "Intermediate Cuff Pressure");
map.put(INTERMEDIATE_CUFF_PRESSURE , "Heart Rate Measurement");
map.put(HEART_RATE_MEASUREMENT , "Body Sensor Location");
map.put(BODY_SENSOR_LOCATION , "Heart Rate Control Point");
map.put(HEART_RATE_CONTROL_POINT , "Alert Status");
map.put(ALERT_STATUS , "Ringer Control Point");
map.put(RINGER_CONTROL_POINT , "Ringer Setting");
map.put(RINGER_SETTING , "Alert Category ID Bit Mask");
map.put(ALERT_CATEGORY_ID_BIT_MASK , "Alert Category ID");
map.put(ALERT_CATEGORY_ID , "Alert Notification Control Point");
map.put(ALERT_NOTIFICATION_CONTROL_POINT , "Unread Alert Status");
map.put(UNREAD_ALERT_STATUS , "New Alert");
map.put(NEW_ALERT , "Supported New Alert Category");
map.put(SUPPORTED_NEW_ALERT_CATEGORY , "Supported Unread Alert Category");
map.put(SUPPORTED_UNREAD_ALERT_CATEGORY , "Blood Pressure Feature");
map.put(BLOOD_PRESSURE_FEATURE , "PNPID");
map.put(PNPID , "SC_CONTROL_POINT");
map.put(SC_CONTROL_POINT , "CSC_MEASUREMENT");
map.put(CSC_MEASUREMENT , "CSC_FEATURE");
map.put(CSC_FEATURE , "SENSOR_LOCATION");
map.put(SENSOR_LOCATION , "ActiveSync");
map.put(ACTIVESYNC , "ActiveSync");
map.put(ESTIMOTE_SERVICE , "Estimote Service");
map.put(ESTIMOTE_UUID , "Estimote UUID");
map.put(ESTIMOTE_MAJOR , "Estimote Major");
map.put(ESTIMOTE_MINOR , "Estimote Minor");
map.put(ESTIMOTE_BATTERY , "Estimote Battery");
map.put(ESTIMOTE_TEMPERATURE , "Estimote Temperature");
map.put(ESTIMOTE_POWER , "Estimote Power");
map.put(ESTIMOTE_ADVERTISING_INTERVAL , "Estimote Advertising Interval");
map.put(ESTIMOTE_VERSION_SERVICE , "Estimote Version Service");
map.put(ESTIMOTE_SOFTWARE_VERSION , "Estimote Software Version");
map.put(ESTIMOTE_HARDWARE_VERSION , "Estimote Hardware Version");
map.put(ESTIMOTE_AUTHENTICATION_SERVICE , "Estimote Authentication Service");
map.put(ESTIMOTE_ADVERTISING_SEED , "Estimote Advertising Seed");
map.put(ESTIMOTE_ADVERTISING_VECTOR , "Estimote Advertising Vector");
return map;
}
}

View File

@@ -1,120 +0,0 @@
package uk.co.alt236.bluetoothlelib.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
import android.annotation.SuppressLint;
import android.util.SparseArray;
public class AdRecordUtils {
public static String getRecordDataAsString(final AdRecord nameRecord) {
if(nameRecord == null){return new String();}
return new String(nameRecord.getData());
}
public static byte[] getServiceData(final AdRecord serviceData) {
if (serviceData == null) {return null;}
if (serviceData.getType() != AdRecord.TYPE_SERVICE_DATA) return null;
final byte[] raw = serviceData.getData();
//Chop out the uuid
return Arrays.copyOfRange(raw, 2, raw.length);
}
public static int getServiceDataUuid(final AdRecord serviceData) {
if (serviceData == null) {return -1;}
if (serviceData.getType() != AdRecord.TYPE_SERVICE_DATA) return -1;
final byte[] raw = serviceData.getData();
//Find UUID data in byte array
int uuid = (raw[1] & 0xFF) << 8;
uuid += (raw[0] & 0xFF);
return uuid;
}
/*
* Read out all the AD structures from the raw scan record
*/
public static List<AdRecord> parseScanRecordAsList(final byte[] scanRecord) {
final List<AdRecord> records = new ArrayList<AdRecord>();
int index = 0;
while (index < scanRecord.length) {
final int length = scanRecord[index++];
//Done once we run out of records
if (length == 0) break;
final int type = ByteUtils.getIntFromByte(scanRecord[index]);
//Done if our record isn't a valid type
if (type == 0) break;
final byte[] data = Arrays.copyOfRange(scanRecord, index+1, index+length);
records.add(new AdRecord(length, type, data));
//Advance
index += length;
}
return Collections.unmodifiableList(records);
}
@SuppressLint("UseSparseArrays")
public static Map<Integer, AdRecord> parseScanRecordAsMap(final byte[] scanRecord) {
final Map<Integer, AdRecord> records = new HashMap<Integer, AdRecord>();
int index = 0;
while (index < scanRecord.length) {
final int length = scanRecord[index++];
//Done once we run out of records
if (length == 0) break;
final int type = ByteUtils.getIntFromByte(scanRecord[index]);
//Done if our record isn't a valid type
if (type == 0) break;
final byte[] data = Arrays.copyOfRange(scanRecord, index+1, index+length);
records.put(type, new AdRecord(length, type, data));
//Advance
index += length;
}
return Collections.unmodifiableMap(records);
}
public static SparseArray<AdRecord> parseScanRecordAsSparseArray(byte[] scanRecord) {
final SparseArray<AdRecord> records = new SparseArray<AdRecord>();
int index = 0;
while (index < scanRecord.length) {
final int length = scanRecord[index++];
//Done once we run out of records
if (length == 0) break;
final int type = ByteUtils.getIntFromByte(scanRecord[index]);
//Done if our record isn't a valid type
if (type == 0) break;
final byte[] data = Arrays.copyOfRange(scanRecord, index+1, index+length);
records.put(type, new AdRecord(length, type, data));
//Advance
index += length;
}
return records;
}
}

View File

@@ -1,124 +0,0 @@
package uk.co.alt236.bluetoothlelib.util;
import java.nio.ByteBuffer;
public class ByteUtils {
/** The Constant HEXES. */
private static final String HEXES = "0123456789ABCDEF";
/**
* Gets a pretty representation of a Byte Array as a HEX String.
*
* Sample output: [01, 30, FF, AA]
*
* @param array the array
* @return the string
*/
public static String byteArrayToHexString(final byte[] array){
final StringBuffer sb = new StringBuffer();
boolean firstEntry = true;
sb.append('[');
for ( final byte b : array ) {
if(!firstEntry){
sb.append(", ");
}
sb.append(HEXES.charAt((b & 0xF0) >> 4));
sb.append(HEXES.charAt((b & 0x0F)));
firstEntry = false;
}
sb.append(']');
return sb.toString();
}
/**
* Checks to see if a byte arry starts with another byte array.
*
* @param array the array
* @param prefix the prefix
* @return true, if successful
*/
public static boolean doesArrayBeginWith(byte[] array, byte[] prefix){
if(array.length < prefix.length){return false;}
for(int i = 0; i < prefix.length; i++){
if(array[i] != prefix[i]){
return false;
}
}
return true;
}
/**
* Converts a byte array with a length of 2 into an int
*
* @param input the input
* @return the int from the array
*/
public static int getIntFrom2ByteArray(byte[] input){
final byte[] result = new byte[4];
result[0] = 0;
result[1] = 0;
result[2] = input[0];
result[3] = input[1];
return ByteUtils.getIntFromByteArray(result);
}
/**
* Converts a byte to an int, preserving the sign.
*
* For example, FF will be converted to 255 and not -1.
*
* @param bite the bite
* @return the int from byte
*/
public static int getIntFromByte(final byte bite){
return Integer.valueOf(bite & 0xFF);
}
/**
* Converts a byte array to an int.
*
* @param bytes the bytes
* @return the int from byte array
*/
public static int getIntFromByteArray(final byte[] bytes) {
return ByteBuffer.wrap(bytes).getInt();
}
/**
* Converts a byte array to a long.
*
* @param bytes the bytes
* @return the long from byte array
*/
public static long getLongFromByteArray(final byte[] bytes) {
return ByteBuffer.wrap(bytes).getLong();
}
/**
* Inverts an array
*
* @param array the array
* @return the byte[]
*/
public static byte[] invertArray(byte[] array){
final int size = array.length;
byte temp;
for (int i = 0; i < size/2; i++)
{
temp = array[i];
array[i] = array[size-1 - i];
array[size-1 - i] = temp;
}
return array;
}
}

View File

@@ -1,89 +0,0 @@
package uk.co.alt236.bluetoothlelib.util;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
public class IBeaconUtils {
private static final double DISTANCE_THRESHOLD_WTF = 0.0;
private static final double DISTANCE_THRESHOLD_IMMEDIATE = 0.5;
private static final double DISTANCE_THRESHOLD_NEAR = 3.0;
private static final byte[] MANUFACTURER_DATA_IBEACON_PREFIX = new byte[]{0x4C, 0x00, 0x02, 0x15};
public static IBeaconDistanceDescriptor getDistanceDescriptor(double accuracy){
if(accuracy < DISTANCE_THRESHOLD_WTF){
return IBeaconDistanceDescriptor.UNKNOWN;
}
if(accuracy < DISTANCE_THRESHOLD_IMMEDIATE){
return IBeaconDistanceDescriptor.IMMEDIATE;
}
if(accuracy < DISTANCE_THRESHOLD_NEAR){
return IBeaconDistanceDescriptor.NEAR;
}
return IBeaconDistanceDescriptor.FAR;
}
/**
* Calculates the accuracy of an RSSI reading.
*
* The code was taken from {@link http://stackoverflow.com/questions/20416218/understanding-ibeacon-distancing}
*
* @param txPower the calibrated TX power of an iBeacon
* @param rssi the RSSI value of the iBeacon
* @return
*/
public static double calculateAccuracy(int txPower, double rssi) {
if (rssi == 0) {
return -1.0; // if we cannot determine accuracy, return -1.
}
double ratio = rssi*1.0/txPower;
if (ratio < 1.0) {
return Math.pow(ratio,10);
}
else {
final double accuracy = (0.89976)*Math.pow(ratio,7.7095) + 0.111;
return accuracy;
}
}
/**
* Ascertains whether a {@link uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice} is an iBeacon;
*
* @param device a {@link uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice} device.
* @return
*/
public static boolean isThisAnIBeacon(BluetoothLeDevice device){
return isThisAnIBeacon(
device.getAdRecordStore().getRecordDataAsString(AdRecord.TYPE_MANUFACTURER_SPECIFIC_DATA).getBytes());
}
/**
* Ascertains whether a Manufacturer Data byte array belongs to an iBeacon;
*
* @param scanRecord a Bluetooth LE device's manufacturerData.
* @return
*/
public static boolean isThisAnIBeacon(byte[] manufacturerData){
if(manufacturerData == null){return false;}
// An iBeacon record must be at least 25 chars long
if(!(manufacturerData.length >= 25)){return false;}
if(ByteUtils.doesArrayBeginWith(manufacturerData, MANUFACTURER_DATA_IBEACON_PREFIX)){
return true;
}
return false;
}
public enum IBeaconDistanceDescriptor{
IMMEDIATE,
NEAR,
FAR,
UNKNOWN,
}
}

View File

@@ -1,20 +0,0 @@
package uk.co.alt236.bluetoothlelib.util;
import java.util.LinkedHashMap;
import java.util.Map;
public class LimitedLinkHashMap<K, V> extends LinkedHashMap<K, V>{
private static final long serialVersionUID = -5375660288461724925L;
private final int mMaxSize;
public LimitedLinkHashMap(int maxSize){
super(maxSize + 1, 1, false);
mMaxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return this.size() > mMaxSize;
}
}

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="src" path=".apt_generated">
<attributes>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@@ -1,3 +0,0 @@
<factorypath>
<factorypathentry kind="WKSPJAR" id="/Bluetooth LE Scanner/libs/butterknife-4.0.1.jar" enabled="true" runInBatchMode="false"/>
</factorypath>

View File

@@ -1,6 +1 @@
/bin
/gen
local.properties
.idea/
lint.xml
/.apt_generated
/build

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Bluetooth LE Scanner</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -1,4 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.apt.aptEnabled=true
org.eclipse.jdt.apt.genSrcDir=.apt_generated
org.eclipse.jdt.apt.reconcileEnabled=true

View File

@@ -1,5 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.processAnnotations=enabled
org.eclipse.jdt.core.compiler.source=1.6

64
sample_app/build.gradle Normal file
View File

@@ -0,0 +1,64 @@
apply plugin: 'com.android.application'
final int versionMajor = 1
final int versionMinor = 1
final int versionPatch = 1
final int androidVersionCode = 7
final int targetSdk = rootProject.targetSdkVersion;
final int minSdkRed = rootProject.minSdkVersion;
final String semanticVersion = "${versionMajor}.${versionMinor}.${versionPatch}"
repositories {
maven {
url "https://repo.commonsware.com.s3.amazonaws.com"
}
maven {
url "https://s3.amazonaws.com/repo.commonsware.com"
}
maven {
url "https://dl.bintray.com/alt236/maven"
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile project(':library')
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:recyclerview-v7:24.2.0'
compile 'com.anthonycr.grant:permissions:1.0'
compile 'uk.co.alt236:easycursor-android:1.0.0'
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-all:1.9.5'
}
android {
compileSdkVersion rootProject.compileSdkVersion
buildToolsVersion rootProject.buildToolsVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
defaultConfig {
minSdkVersion minSdkRed
targetSdkVersion targetSdk
versionCode androidVersionCode
versionName semanticVersion
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

View File

@@ -1,11 +1,8 @@
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
# in /home/alex/Dev/android-sdk-linux/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

View File

@@ -1,15 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=Google Inc.:Google APIs:19
android.library.reference.1=../library

Binary file not shown.

Before

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Some files were not shown because too many files have changed in this diff Show More