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;
+ }
+
+
+}
diff --git a/library/src/main/java/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolver.java b/library/src/main/java/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolver.java
new file mode 100644
index 0000000..429ffef
--- /dev/null
+++ b/library/src/main/java/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolver.java
@@ -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:
+ *
+ * - 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 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 populateGattAttributesMap() {
+ final Map 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;
+ }
+}
diff --git a/library/src/main/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java b/library/src/main/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java
new file mode 100644
index 0000000..c872f82
--- /dev/null
+++ b/library/src/main/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java
@@ -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 parseScanRecordAsList(final byte[] scanRecord) {
+ final List 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 parseScanRecordAsMap(final byte[] scanRecord) {
+ final Map 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 parseScanRecordAsSparseArray(final byte[] scanRecord) {
+ final SparseArray 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;
+ }
+}
diff --git a/library/src/main/java/uk/co/alt236/bluetoothlelib/util/ByteUtils.java b/library/src/main/java/uk/co/alt236/bluetoothlelib/util/ByteUtils.java
new file mode 100644
index 0000000..c13dbf9
--- /dev/null
+++ b/library/src/main/java/uk/co/alt236/bluetoothlelib/util/ByteUtils.java
@@ -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.
+ *
+ * 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.
+ *
+ * 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;
+ }
+ }
+}
diff --git a/library/src/main/java/uk/co/alt236/bluetoothlelib/util/LimitedLinkHashMap.java b/library/src/main/java/uk/co/alt236/bluetoothlelib/util/LimitedLinkHashMap.java
new file mode 100644
index 0000000..f7c4136
--- /dev/null
+++ b/library/src/main/java/uk/co/alt236/bluetoothlelib/util/LimitedLinkHashMap.java
@@ -0,0 +1,20 @@
+package uk.co.alt236.bluetoothlelib.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class LimitedLinkHashMap extends LinkedHashMap {
+ 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 eldest) {
+ return this.size() > mMaxSize;
+ }
+}
diff --git a/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/BeaconUtilsTest.java b/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/BeaconUtilsTest.java
new file mode 100644
index 0000000..1de810e
--- /dev/null
+++ b/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/BeaconUtilsTest.java
@@ -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]));
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconManufacturerDataTest.java b/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconManufacturerDataTest.java
new file mode 100644
index 0000000..cef150b
--- /dev/null
+++ b/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconManufacturerDataTest.java
@@ -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
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconUtilsTest.java b/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconUtilsTest.java
new file mode 100644
index 0000000..7399ed0
--- /dev/null
+++ b/library/src/test/java/uk/co/alt236/bluetoothlelib/device/beacon/ibeacon/IBeaconUtilsTest.java
@@ -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));
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolverTest.java b/library/src/test/java/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolverTest.java
new file mode 100644
index 0000000..6b482c9
--- /dev/null
+++ b/library/src/test/java/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolverTest.java
@@ -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));
+
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtilsTest.java b/library/src/test/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtilsTest.java
new file mode 100644
index 0000000..d528dd8
--- /dev/null
+++ b/library/src/test/java/uk/co/alt236/bluetoothlelib/util/AdRecordUtilsTest.java
@@ -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 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 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 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());
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/uk/co/alt236/bluetoothlelib/util/ByteUtilsTest.java b/library/src/test/java/uk/co/alt236/bluetoothlelib/util/ByteUtilsTest.java
new file mode 100644
index 0000000..e0705e9
--- /dev/null
+++ b/library/src/test/java/uk/co/alt236/bluetoothlelib/util/ByteUtilsTest.java
@@ -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]);
+ }
+}
\ No newline at end of file
diff --git a/library/src/uk/co/alt236/bluetoothlelib/device/BluetoothLeDevice.java b/library/src/uk/co/alt236/bluetoothlelib/device/BluetoothLeDevice.java
deleted file mode 100644
index e8ed154..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/device/BluetoothLeDevice.java
+++ /dev/null
@@ -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 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 CREATOR = new Parcelable.Creator() {
- 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(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) 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 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 it1 = mRssiLog.keySet().iterator();
-
- while(it1.hasNext()){
- count ++;
- sum += mRssiLog.get(it1.next());
- }
- }
- // for(final Map.Entry 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";
- }
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/device/IBeaconDevice.java b/library/src/uk/co/alt236/bluetoothlelib/device/IBeaconDevice.java
deleted file mode 100644
index 9a4b90f..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/device/IBeaconDevice.java
+++ /dev/null
@@ -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.");
- }
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/device/adrecord/AdRecord.java b/library/src/uk/co/alt236/bluetoothlelib/device/adrecord/AdRecord.java
deleted file mode 100644
index ac8cc0c..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/device/adrecord/AdRecord.java
+++ /dev/null
@@ -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 CREATOR = new Parcelable.Creator() {
- 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;
- }
- }
-}
\ No newline at end of file
diff --git a/library/src/uk/co/alt236/bluetoothlelib/device/adrecord/AdRecordStore.java b/library/src/uk/co/alt236/bluetoothlelib/device/adrecord/AdRecordStore.java
deleted file mode 100644
index 21b5984..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/device/adrecord/AdRecordStore.java
+++ /dev/null
@@ -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 mAdRecords;
- private final String mLocalNameComplete;
- private final String mLocalNameShort;
-
- public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
- 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 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 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 the generic type
- * @param sparseArray the sparse array
- * @return the collection
- */
- public static Collection asList(SparseArray sparseArray) {
- if (sparseArray == null) return null;
-
- final Collection arrayList = new ArrayList(sparseArray.size());
- for (int i = 0; i < sparseArray.size(); i++){
- arrayList.add(sparseArray.valueAt(i));
- }
-
- return arrayList;
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/device/mfdata/IBeaconManufacturerData.java b/library/src/uk/co/alt236/bluetoothlelib/device/mfdata/IBeaconManufacturerData.java
deleted file mode 100644
index 07888d9..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/device/mfdata/IBeaconManufacturerData.java
+++ /dev/null
@@ -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:
- *
- *
- * 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
- *
- *
- *
- * @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();
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/resolvers/BluetoothClassResolver.java b/library/src/uk/co/alt236/bluetoothlelib/resolvers/BluetoothClassResolver.java
deleted file mode 100644
index 46a408d..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/resolvers/BluetoothClassResolver.java
+++ /dev/null
@@ -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 +")";
- }
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/resolvers/CompanyIdentifierResolver.java b/library/src/uk/co/alt236/bluetoothlelib/resolvers/CompanyIdentifierResolver.java
deleted file mode 100644
index 231cfad..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/resolvers/CompanyIdentifierResolver.java
+++ /dev/null
@@ -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 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 populateCompanyNameMap() {
- final SparseArray 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;
- }
-
-
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolver.java b/library/src/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolver.java
deleted file mode 100644
index a30cca8..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/resolvers/GattAttributeResolver.java
+++ /dev/null
@@ -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 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 populateGattAttributesMap() {
- final Map map = new HashMap();
-
- 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;
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java b/library/src/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java
deleted file mode 100644
index 2509751..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/util/AdRecordUtils.java
+++ /dev/null
@@ -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 parseScanRecordAsList(final byte[] scanRecord) {
- final List 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 parseScanRecordAsMap(final byte[] scanRecord) {
- final Map 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 parseScanRecordAsSparseArray(byte[] scanRecord) {
- final SparseArray 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;
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/util/ByteUtils.java b/library/src/uk/co/alt236/bluetoothlelib/util/ByteUtils.java
deleted file mode 100644
index 7745688..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/util/ByteUtils.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/util/IBeaconUtils.java b/library/src/uk/co/alt236/bluetoothlelib/util/IBeaconUtils.java
deleted file mode 100644
index 2fe5e1c..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/util/IBeaconUtils.java
+++ /dev/null
@@ -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,
- }
-}
diff --git a/library/src/uk/co/alt236/bluetoothlelib/util/LimitedLinkHashMap.java b/library/src/uk/co/alt236/bluetoothlelib/util/LimitedLinkHashMap.java
deleted file mode 100644
index a95cc35..0000000
--- a/library/src/uk/co/alt236/bluetoothlelib/util/LimitedLinkHashMap.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package uk.co.alt236.bluetoothlelib.util;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-public class LimitedLinkHashMap extends LinkedHashMap{
- 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 eldest) {
- return this.size() > mMaxSize;
- }
-}
diff --git a/sample_app/.classpath b/sample_app/.classpath
deleted file mode 100644
index c54e8eb..0000000
--- a/sample_app/.classpath
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/sample_app/.factorypath b/sample_app/.factorypath
deleted file mode 100644
index 946a26f..0000000
--- a/sample_app/.factorypath
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/sample_app/.gitignore b/sample_app/.gitignore
index 47ab45a..796b96d 100644
--- a/sample_app/.gitignore
+++ b/sample_app/.gitignore
@@ -1,6 +1 @@
-/bin
-/gen
-local.properties
-.idea/
-lint.xml
-/.apt_generated
+/build
diff --git a/sample_app/.project b/sample_app/.project
deleted file mode 100644
index f0df143..0000000
--- a/sample_app/.project
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
- Bluetooth LE Scanner
-
-
-
-
-
- com.android.ide.eclipse.adt.ResourceManagerBuilder
-
-
-
-
- com.android.ide.eclipse.adt.PreCompilerBuilder
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- com.android.ide.eclipse.adt.ApkBuilder
-
-
-
-
-
- com.android.ide.eclipse.adt.AndroidNature
- org.eclipse.jdt.core.javanature
-
-
diff --git a/sample_app/.settings/org.eclipse.jdt.apt.core.prefs b/sample_app/.settings/org.eclipse.jdt.apt.core.prefs
deleted file mode 100644
index 7d52ece..0000000
--- a/sample_app/.settings/org.eclipse.jdt.apt.core.prefs
+++ /dev/null
@@ -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
diff --git a/sample_app/.settings/org.eclipse.jdt.core.prefs b/sample_app/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index f2b863f..0000000
--- a/sample_app/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -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
diff --git a/sample_app/build.gradle b/sample_app/build.gradle
new file mode 100644
index 0000000..38e6eb0
--- /dev/null
+++ b/sample_app/build.gradle
@@ -0,0 +1,50 @@
+apply plugin: 'com.android.application'
+
+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}"
+
+repositories {
+ maven {
+ url "https://repo.commonsware.com.s3.amazonaws.com"
+ }
+}
+
+dependencies {
+ compile 'com.jakewharton:butterknife:7.0.1'
+ compile 'com.android.support:appcompat-v7:22.2.0'
+ compile 'com.commonsware.cwac:merge:1.1.0'
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+ compile project(':library')
+}
+
+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 {
+ }
+}
diff --git a/sample_app/libs/android-support-v4.jar b/sample_app/libs/android-support-v4.jar
deleted file mode 100644
index 96644ed..0000000
Binary files a/sample_app/libs/android-support-v4.jar and /dev/null differ
diff --git a/sample_app/libs/butterknife-4.0.1.jar b/sample_app/libs/butterknife-4.0.1.jar
deleted file mode 100644
index e048516..0000000
Binary files a/sample_app/libs/butterknife-4.0.1.jar and /dev/null differ
diff --git a/sample_app/libs/merge-1.0.1.jar b/sample_app/libs/merge-1.0.1.jar
deleted file mode 100644
index fb49c15..0000000
Binary files a/sample_app/libs/merge-1.0.1.jar and /dev/null differ
diff --git a/sample_app/libs/sacklist-1.0.0.jar b/sample_app/libs/sacklist-1.0.0.jar
deleted file mode 100644
index 3a49a76..0000000
Binary files a/sample_app/libs/sacklist-1.0.0.jar and /dev/null differ
diff --git a/sample_app/proguard-project.txt b/sample_app/proguard-rules.pro
similarity index 62%
rename from sample_app/proguard-project.txt
rename to sample_app/proguard-rules.pro
index f2fe155..f8c620f 100644
--- a/sample_app/proguard-project.txt
+++ b/sample_app/proguard-rules.pro
@@ -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
diff --git a/sample_app/project.properties b/sample_app/project.properties
deleted file mode 100644
index 3a06472..0000000
--- a/sample_app/project.properties
+++ /dev/null
@@ -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
diff --git a/sample_app/res/layout/actionbar_progress_indeterminate.xml b/sample_app/res/layout/actionbar_progress_indeterminate.xml
deleted file mode 100644
index ba1c316..0000000
--- a/sample_app/res/layout/actionbar_progress_indeterminate.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/sample_app/res/layout/activity_details.xml b/sample_app/res/layout/activity_details.xml
deleted file mode 100644
index e853847..0000000
--- a/sample_app/res/layout/activity_details.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/sample_app/res/layout/list_item_view_device_info.xml b/sample_app/res/layout/list_item_view_device_info.xml
deleted file mode 100644
index 1ae0aac..0000000
--- a/sample_app/res/layout/list_item_view_device_info.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/sample_app/res/layout/list_item_view_textview.xml b/sample_app/res/layout/list_item_view_textview.xml
deleted file mode 100644
index 1f00684..0000000
--- a/sample_app/res/layout/list_item_view_textview.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/sample_app/res/values/colors.xml b/sample_app/res/values/colors.xml
deleted file mode 100644
index b8f6e52..0000000
--- a/sample_app/res/values/colors.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
- #66e0e0e0
-
diff --git a/sample_app/sample_app.iml b/sample_app/sample_app.iml
new file mode 100644
index 0000000..756895c
--- /dev/null
+++ b/sample_app/sample_app.iml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample_app/AndroidManifest.xml b/sample_app/src/main/AndroidManifest.xml
similarity index 66%
rename from sample_app/AndroidManifest.xml
rename to sample_app/src/main/AndroidManifest.xml
index bfcd7a6..7546b22 100644
--- a/sample_app/AndroidManifest.xml
+++ b/sample_app/src/main/AndroidManifest.xml
@@ -1,43 +1,38 @@
-
+ xmlns:android="http://schemas.android.com/apk/res/android">
-
-
-
-
+
+
+ android:required="false"/>
+ android:theme="@style/AppTheme">
+ android:label="@string/app_name">
-
+
-
+
+ android:label="@string/app_name">
-
+
+ android:enabled="true"/>
\ No newline at end of file
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/activities/DeviceControlActivity.java b/sample_app/src/main/java/uk/co/alt236/btlescan/activities/DeviceControlActivity.java
new file mode 100644
index 0000000..5e3753b
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/activities/DeviceControlActivity.java
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.alt236.btlescan.activities;
+
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ExpandableListView;
+import android.widget.SimpleExpandableListAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
+import uk.co.alt236.bluetoothlelib.resolvers.GattAttributeResolver;
+import uk.co.alt236.bluetoothlelib.util.ByteUtils;
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.services.BluetoothLeService;
+
+/**
+ * For a given BLE device, this Activity provides the user interface to connect, display data,
+ * and display GATT services and characteristics supported by the device. The Activity
+ * communicates with {@code BluetoothLeService}, which in turn interacts with the
+ * Bluetooth LE API.
+ */
+public class DeviceControlActivity extends AppCompatActivity {
+ public static final String EXTRA_DEVICE = "extra_device";
+ private final static String TAG = DeviceControlActivity.class.getSimpleName();
+ private static final String LIST_NAME = "NAME";
+ private static final String LIST_UUID = "UUID";
+ @Bind(R.id.gatt_services_list)
+ protected ExpandableListView mGattServicesList;
+ @Bind(R.id.connection_state)
+ protected TextView mConnectionState;
+ @Bind(R.id.uuid)
+ protected TextView mGattUUID;
+ @Bind(R.id.description)
+ protected TextView mGattUUIDDesc;
+ @Bind(R.id.data_as_string)
+ protected TextView mDataAsString;
+ @Bind(R.id.data_as_array)
+ protected TextView mDataAsArray;
+ private BluetoothGattCharacteristic mNotifyCharacteristic;
+ private BluetoothLeService mBluetoothLeService;
+ private List> mGattCharacteristics = new ArrayList<>();
+ // If a given GATT characteristic is selected, check for supported features. This sample
+ // demonstrates 'Read' and 'Notify' features. See
+ // http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
+ // list of supported characteristic features.
+ private final ExpandableListView.OnChildClickListener servicesListClickListner = new ExpandableListView.OnChildClickListener() {
+ @Override
+ public boolean onChildClick(final ExpandableListView parent, final View v, final int groupPosition, final int childPosition, final long id) {
+ if (mGattCharacteristics != null) {
+ final BluetoothGattCharacteristic characteristic = mGattCharacteristics.get(groupPosition).get(childPosition);
+ final int charaProp = characteristic.getProperties();
+ if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
+ // If there is an active notification on a characteristic, clear
+ // it first so it doesn't update the data field on the user interface.
+ if (mNotifyCharacteristic != null) {
+ mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
+ mNotifyCharacteristic = null;
+ }
+ mBluetoothLeService.readCharacteristic(characteristic);
+ }
+ if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
+ mNotifyCharacteristic = characteristic;
+ mBluetoothLeService.setCharacteristicNotification(characteristic, true);
+ }
+ return true;
+ }
+ return false;
+ }
+ };
+ private String mDeviceAddress;
+ // Code to manage Service lifecycle.
+ private final ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(final ComponentName componentName, final IBinder service) {
+ mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
+ if (!mBluetoothLeService.initialize()) {
+ Log.e(TAG, "Unable to initialize Bluetooth");
+ finish();
+ }
+ // Automatically connects to the device upon successful start-up initialization.
+ mBluetoothLeService.connect(mDeviceAddress);
+ }
+
+ @Override
+ public void onServiceDisconnected(final ComponentName componentName) {
+ mBluetoothLeService = null;
+ }
+ };
+ private String mDeviceName;
+ private boolean mConnected = false;
+ private String mExportString;
+ // Handles various events fired by the Service.
+ // ACTION_GATT_CONNECTED: connected to a GATT server.
+ // ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
+ // ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
+ // ACTION_DATA_AVAILABLE: received data from the device.
+ // this can be a result of read or notification operations.
+ private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ final String action = intent.getAction();
+ if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
+ mConnected = true;
+ updateConnectionState(R.string.connected);
+ invalidateOptionsMenu();
+ } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
+ mConnected = false;
+ updateConnectionState(R.string.disconnected);
+ invalidateOptionsMenu();
+ clearUI();
+ } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
+ // Show all the supported services and characteristics on the user interface.
+ displayGattServices(mBluetoothLeService.getSupportedGattServices());
+ } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
+ final String noData = getString(R.string.no_data);
+ final String uuid = intent.getStringExtra(BluetoothLeService.EXTRA_UUID_CHAR);
+ final byte[] dataArr = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA_RAW);
+
+ mGattUUID.setText(tryString(uuid, noData));
+ mGattUUIDDesc.setText(GattAttributeResolver.getAttributeName(uuid, getString(R.string.unknown)));
+ mDataAsArray.setText(ByteUtils.byteArrayToHexString(dataArr));
+ mDataAsString.setText(new String(dataArr));
+ }
+ }
+ };
+
+ private void clearUI() {
+ mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
+ mGattUUID.setText(R.string.no_data);
+ mGattUUIDDesc.setText(R.string.no_data);
+ mDataAsArray.setText(R.string.no_data);
+ mDataAsString.setText(R.string.no_data);
+ }
+
+ // Demonstrates how to iterate through the supported GATT Services/Characteristics.
+ // In this sample, we populate the data structure that is bound to the ExpandableListView
+ // on the UI.
+ private void displayGattServices(final List gattServices) {
+ if (gattServices == null) return;
+ generateExportString(gattServices);
+
+ String uuid = null;
+ final String unknownServiceString = getResources().getString(R.string.unknown_service);
+ final String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
+ final List> gattServiceData = new ArrayList<>();
+ final List>> gattCharacteristicData = new ArrayList<>();
+ mGattCharacteristics = new ArrayList<>();
+
+ // Loops through available GATT Services.
+ for (final BluetoothGattService gattService : gattServices) {
+ final Map currentServiceData = new HashMap<>();
+ uuid = gattService.getUuid().toString();
+ currentServiceData.put(LIST_NAME, GattAttributeResolver.getAttributeName(uuid, unknownServiceString));
+ currentServiceData.put(LIST_UUID, uuid);
+ gattServiceData.add(currentServiceData);
+
+ final List> gattCharacteristicGroupData = new ArrayList<>();
+ final List gattCharacteristics = gattService.getCharacteristics();
+ final List charas = new ArrayList<>();
+
+ // Loops through available Characteristics.
+ for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
+ charas.add(gattCharacteristic);
+ final Map currentCharaData = new HashMap<>();
+ uuid = gattCharacteristic.getUuid().toString();
+ currentCharaData.put(LIST_NAME, GattAttributeResolver.getAttributeName(uuid, unknownCharaString));
+ currentCharaData.put(LIST_UUID, uuid);
+ gattCharacteristicGroupData.add(currentCharaData);
+ }
+
+ mGattCharacteristics.add(charas);
+ gattCharacteristicData.add(gattCharacteristicGroupData);
+ }
+
+ final SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
+ this,
+ gattServiceData,
+ android.R.layout.simple_expandable_list_item_2,
+ new String[]{LIST_NAME, LIST_UUID},
+ new int[]{android.R.id.text1, android.R.id.text2},
+ gattCharacteristicData,
+ android.R.layout.simple_expandable_list_item_2,
+ new String[]{LIST_NAME, LIST_UUID},
+ new int[]{android.R.id.text1, android.R.id.text2}
+ );
+
+ mGattServicesList.setAdapter(gattServiceAdapter);
+ invalidateOptionsMenu();
+ }
+
+ private void generateExportString(final List gattServices) {
+ final String unknownServiceString = getResources().getString(R.string.unknown_service);
+ final String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
+ final StringBuilder exportBuilder = new StringBuilder();
+
+ exportBuilder.append("Device Name: ");
+ exportBuilder.append(mDeviceName);
+ exportBuilder.append('\n');
+ exportBuilder.append("Device Address: ");
+ exportBuilder.append(mDeviceAddress);
+ exportBuilder.append('\n');
+ exportBuilder.append('\n');
+
+ exportBuilder.append("Services:");
+ exportBuilder.append("--------------------------");
+ exportBuilder.append('\n');
+
+ String uuid = null;
+ for (final BluetoothGattService gattService : gattServices) {
+ uuid = gattService.getUuid().toString();
+
+ exportBuilder.append(GattAttributeResolver.getAttributeName(uuid, unknownServiceString));
+ exportBuilder.append(" (");
+ exportBuilder.append(uuid);
+ exportBuilder.append(')');
+ exportBuilder.append('\n');
+
+ final List gattCharacteristics = gattService.getCharacteristics();
+ for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
+ uuid = gattCharacteristic.getUuid().toString();
+
+ exportBuilder.append('\t');
+ exportBuilder.append(GattAttributeResolver.getAttributeName(uuid, unknownCharaString));
+ exportBuilder.append(" (");
+ exportBuilder.append(uuid);
+ exportBuilder.append(')');
+ exportBuilder.append('\n');
+ }
+
+ exportBuilder.append('\n');
+ exportBuilder.append('\n');
+ }
+
+ exportBuilder.append("--------------------------");
+ exportBuilder.append('\n');
+
+ mExportString = exportBuilder.toString();
+ }
+
+ @Override
+ public void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_gatt_services);
+
+ final Intent intent = getIntent();
+ final BluetoothLeDevice device = intent.getParcelableExtra(EXTRA_DEVICE);
+ mDeviceName = device.getName();
+ mDeviceAddress = device.getAddress();
+
+ ButterKnife.bind(this);
+
+ // Sets up UI references.
+ ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
+ mGattServicesList.setOnChildClickListener(servicesListClickListner);
+
+ getSupportActionBar().setTitle(mDeviceName);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+ final Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
+ bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ getMenuInflater().inflate(R.menu.gatt_services, menu);
+ if (mConnected) {
+ menu.findItem(R.id.menu_connect).setVisible(false);
+ menu.findItem(R.id.menu_disconnect).setVisible(true);
+ } else {
+ menu.findItem(R.id.menu_connect).setVisible(true);
+ menu.findItem(R.id.menu_disconnect).setVisible(false);
+ }
+
+ if (mExportString == null) {
+ menu.findItem(R.id.menu_share).setVisible(false);
+ } else {
+ menu.findItem(R.id.menu_share).setVisible(true);
+ }
+
+ return true;
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ unbindService(mServiceConnection);
+ mBluetoothLeService = null;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_connect:
+ mBluetoothLeService.connect(mDeviceAddress);
+ return true;
+ case R.id.menu_disconnect:
+ mBluetoothLeService.disconnect();
+ return true;
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.menu_share:
+ final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
+ final String subject = getString(R.string.exporter_email_device_services_subject, mDeviceName, mDeviceAddress);
+
+ intent.setType("text/plain");
+ intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
+ intent.putExtra(android.content.Intent.EXTRA_TEXT, mExportString);
+
+ startActivity(Intent.createChooser(
+ intent,
+ getString(R.string.exporter_email_device_list_picker_text)));
+
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ unregisterReceiver(mGattUpdateReceiver);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
+ if (mBluetoothLeService != null) {
+ final boolean result = mBluetoothLeService.connect(mDeviceAddress);
+ Log.d(TAG, "Connect request result=" + result);
+ }
+ }
+
+ private void updateConnectionState(final int resourceId) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ final int colourId;
+
+ switch (resourceId) {
+ case R.string.connected:
+ colourId = android.R.color.holo_green_dark;
+ break;
+ case R.string.disconnected:
+ colourId = android.R.color.holo_red_dark;
+ break;
+ default:
+ colourId = android.R.color.black;
+ break;
+ }
+
+ mConnectionState.setText(resourceId);
+ mConnectionState.setTextColor(getResources().getColor(colourId));
+ }
+ });
+ }
+
+ private static IntentFilter makeGattUpdateIntentFilter() {
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
+ intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
+ intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
+ intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
+ return intentFilter;
+ }
+
+ private static String tryString(final String string, final String fallback) {
+ if (string == null) {
+ return fallback;
+ } else {
+ return string;
+ }
+ }
+}
\ No newline at end of file
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java b/sample_app/src/main/java/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java
new file mode 100644
index 0000000..1e3e10f
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java
@@ -0,0 +1,240 @@
+package uk.co.alt236.btlescan.activities;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.commonsware.cwac.merge.MergeAdapter;
+
+import java.util.Collection;
+import java.util.Locale;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
+import uk.co.alt236.bluetoothlelib.device.BluetoothService;
+import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
+import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
+import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
+import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconManufacturerData;
+import uk.co.alt236.bluetoothlelib.resolvers.CompanyIdentifierResolver;
+import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
+import uk.co.alt236.bluetoothlelib.util.ByteUtils;
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.util.TimeFormatter;
+
+public class DeviceDetailsActivity extends AppCompatActivity {
+ public static final String EXTRA_DEVICE = "extra_device";
+ @Bind(android.R.id.list)
+ protected ListView mList;
+ @Nullable
+ @Bind(android.R.id.empty)
+ protected View mEmpty;
+ private BluetoothLeDevice mDevice;
+
+ private void appendAdRecordView(final MergeAdapter adapter, final String title, final AdRecord record) {
+ final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_adrecord, null);
+ final TextView tvString = (TextView) lt.findViewById(R.id.data_as_string);
+ final TextView tvArray = (TextView) lt.findViewById(R.id.data_as_array);
+ final TextView tvTitle = (TextView) lt.findViewById(R.id.title);
+
+ tvTitle.setText(title);
+ tvString.setText("'" + AdRecordUtils.getRecordDataAsString(record) + "'");
+ tvArray.setText("'" + ByteUtils.byteArrayToHexString(record.getData()) + "'");
+
+ adapter.addView(lt);
+ }
+
+ private void appendDeviceInfo(final MergeAdapter adapter, final BluetoothLeDevice device) {
+ final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_device_info, null);
+ final TextView tvName = (TextView) lt.findViewById(R.id.deviceName);
+ final TextView tvAddress = (TextView) lt.findViewById(R.id.deviceAddress);
+ final TextView tvClass = (TextView) lt.findViewById(R.id.deviceClass);
+ final TextView tvMajorClass = (TextView) lt.findViewById(R.id.deviceMajorClass);
+ final TextView tvServices = (TextView) lt.findViewById(R.id.deviceServiceList);
+ final TextView tvBondingState = (TextView) lt.findViewById(R.id.deviceBondingState);
+
+ tvName.setText(device.getName());
+ tvAddress.setText(device.getAddress());
+ tvClass.setText(device.getBluetoothDeviceClassName());
+ tvMajorClass.setText(device.getBluetoothDeviceMajorClassName());
+ tvBondingState.setText(device.getBluetoothDeviceBondState());
+
+ final String supportedServices;
+ if(device.getBluetoothDeviceKnownSupportedServices().isEmpty()){
+ supportedServices = getString(R.string.no_known_services);
+ } else {
+ final StringBuilder sb = new StringBuilder();
+
+ for(final BluetoothService service : device.getBluetoothDeviceKnownSupportedServices()){
+ if(sb.length() > 0){
+ sb.append(", ");
+ }
+
+ sb.append(service);
+ }
+ supportedServices = sb.toString();
+ }
+
+ tvServices.setText(supportedServices);
+
+ adapter.addView(lt);
+ }
+
+ private void appendHeader(final MergeAdapter adapter, final String title) {
+ final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_header, null);
+ final TextView tvTitle = (TextView) lt.findViewById(R.id.title);
+ tvTitle.setText(title);
+
+ adapter.addView(lt);
+ }
+
+ private void appendIBeaconInfo(final MergeAdapter adapter, final IBeaconManufacturerData iBeaconData) {
+ final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_ibeacon_details, null);
+ final TextView tvCompanyId = (TextView) lt.findViewById(R.id.companyId);
+ final TextView tvAdvert = (TextView) lt.findViewById(R.id.advertisement);
+ final TextView tvUUID = (TextView) lt.findViewById(R.id.uuid);
+ final TextView tvMajor = (TextView) lt.findViewById(R.id.major);
+ final TextView tvMinor = (TextView) lt.findViewById(R.id.minor);
+ final TextView tvTxPower = (TextView) lt.findViewById(R.id.txpower);
+
+ tvCompanyId.setText(
+ CompanyIdentifierResolver.getCompanyName(iBeaconData.getCompanyIdentifier(), getString(R.string.unknown))
+ + " (" + hexEncode(iBeaconData.getCompanyIdentifier()) + ")");
+ tvAdvert.setText(iBeaconData.getIBeaconAdvertisement() + " (" + hexEncode(iBeaconData.getIBeaconAdvertisement()) + ")");
+ tvUUID.setText(iBeaconData.getUUID());
+ tvMajor.setText(iBeaconData.getMajor() + " (" + hexEncode(iBeaconData.getMajor()) + ")");
+ tvMinor.setText(iBeaconData.getMinor() + " (" + hexEncode(iBeaconData.getMinor()) + ")");
+ tvTxPower.setText(iBeaconData.getCalibratedTxPower() + " (" + hexEncode(iBeaconData.getCalibratedTxPower()) + ")");
+
+ adapter.addView(lt);
+ }
+
+ private void appendRssiInfo(final MergeAdapter adapter, final BluetoothLeDevice device) {
+ final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_rssi_info, null);
+ final TextView tvFirstTimestamp = (TextView) lt.findViewById(R.id.firstTimestamp);
+ final TextView tvFirstRssi = (TextView) lt.findViewById(R.id.firstRssi);
+ final TextView tvLastTimestamp = (TextView) lt.findViewById(R.id.lastTimestamp);
+ final TextView tvLastRssi = (TextView) lt.findViewById(R.id.lastRssi);
+ final TextView tvRunningAverageRssi = (TextView) lt.findViewById(R.id.runningAverageRssi);
+
+ tvFirstTimestamp.setText(formatTime(device.getFirstTimestamp()));
+ tvFirstRssi.setText(formatRssi(device.getFirstRssi()));
+ tvLastTimestamp.setText(formatTime(device.getTimestamp()));
+ tvLastRssi.setText(formatRssi(device.getRssi()));
+ tvRunningAverageRssi.setText(formatRssi(device.getRunningAverageRssi()));
+
+ adapter.addView(lt);
+ }
+
+ private void appendSimpleText(final MergeAdapter adapter, final byte[] data) {
+ appendSimpleText(adapter, ByteUtils.byteArrayToHexString(data));
+ }
+
+ private void appendSimpleText(final MergeAdapter adapter, final String data) {
+ final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_textview, null);
+ final TextView tvData = (TextView) lt.findViewById(R.id.data);
+
+ tvData.setText(data);
+
+ adapter.addView(lt);
+ }
+
+
+ private String formatRssi(final double rssi) {
+ return getString(R.string.formatter_db, String.valueOf(rssi));
+ }
+
+ private String formatRssi(final int rssi) {
+ return getString(R.string.formatter_db, String.valueOf(rssi));
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_details);
+ ButterKnife.bind(this);
+
+ mList.setEmptyView(mEmpty);
+
+ mDevice = getIntent().getParcelableExtra(EXTRA_DEVICE);
+
+ pupulateDetails(mDevice);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ getMenuInflater().inflate(R.menu.details, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_connect:
+
+ final Intent intent = new Intent(this, DeviceControlActivity.class);
+ intent.putExtra(DeviceControlActivity.EXTRA_DEVICE, mDevice);
+
+ startActivity(intent);
+
+ break;
+ }
+ return true;
+ }
+
+ private void pupulateDetails(final BluetoothLeDevice device) {
+ final MergeAdapter adapter = new MergeAdapter();
+
+ if (device == null) {
+ appendHeader(adapter, getString(R.string.header_device_info));
+ appendSimpleText(adapter, getString(R.string.invalid_device_data));
+ } else {
+ appendHeader(adapter, getString(R.string.header_device_info));
+ appendDeviceInfo(adapter, device);
+
+ appendHeader(adapter, getString(R.string.header_rssi_info));
+ appendRssiInfo(adapter, device);
+
+ appendHeader(adapter, getString(R.string.header_scan_record));
+ appendSimpleText(adapter, device.getScanRecord());
+
+ final Collection adRecords = device.getAdRecordStore().getRecordsAsCollection();
+ if (adRecords.size() > 0) {
+ appendHeader(adapter, getString(R.string.header_raw_ad_records));
+
+ for (final AdRecord record : adRecords) {
+
+ appendAdRecordView(
+ adapter,
+ "#" + record.getType() + " " + record.getHumanReadableType(),
+ record);
+ }
+ }
+
+ final boolean isIBeacon = BeaconUtils.getBeaconType(device) == BeaconType.IBEACON;
+ if (isIBeacon) {
+ final IBeaconManufacturerData iBeaconData = new IBeaconManufacturerData(device);
+ appendHeader(adapter, getString(R.string.header_ibeacon_data));
+ appendIBeaconInfo(adapter, iBeaconData);
+ }
+
+ }
+ mList.setAdapter(adapter);
+ }
+
+ private static String formatTime(final long time) {
+ return TimeFormatter.getIsoDateTime(time);
+ }
+
+ private static String hexEncode(final int integer) {
+ return "0x" + Integer.toHexString(integer).toUpperCase(Locale.US);
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/activities/MainActivity.java b/sample_app/src/main/java/uk/co/alt236/btlescan/activities/MainActivity.java
new file mode 100644
index 0000000..153f522
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/activities/MainActivity.java
@@ -0,0 +1,206 @@
+package uk.co.alt236.btlescan.activities;
+
+import android.app.AlertDialog;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.text.SpannableString;
+import android.text.method.LinkMovementMethod;
+import android.text.util.Linkify;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.adapters.LeDeviceListAdapter;
+import uk.co.alt236.btlescan.containers.BluetoothLeDeviceStore;
+import uk.co.alt236.btlescan.util.BluetoothLeScanner;
+import uk.co.alt236.btlescan.util.BluetoothUtils;
+import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
+
+public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
+ @Bind(R.id.tvBluetoothLe)
+ protected TextView mTvBluetoothLeStatus;
+ @Bind(R.id.tvBluetoothStatus)
+ protected TextView mTvBluetoothStatus;
+ @Bind(R.id.tvItemCount)
+ protected TextView mTvItemCount;
+ @Bind(android.R.id.list)
+ protected ListView mList;
+ @Bind(android.R.id.empty)
+ protected View mEmpty;
+
+ private BluetoothUtils mBluetoothUtils;
+ private BluetoothLeScanner mScanner;
+ private LeDeviceListAdapter mLeDeviceListAdapter;
+ private BluetoothLeDeviceStore mDeviceStore;
+
+ private final BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
+ @Override
+ public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
+
+ final BluetoothLeDevice deviceLe = new BluetoothLeDevice(device, rssi, scanRecord, System.currentTimeMillis());
+ mDeviceStore.addDevice(deviceLe);
+ final EasyObjectCursor c = mDeviceStore.getDeviceCursor();
+
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mLeDeviceListAdapter.swapCursor(c);
+ updateItemCount(mLeDeviceListAdapter.getCount());
+ }
+ });
+ }
+ };
+
+ private void displayAboutDialog() {
+ // REALLY REALLY LAZY LINKIFIED DIALOG
+ final int paddingSizeDp = 5;
+ final float scale = getResources().getDisplayMetrics().density;
+ final int dpAsPixels = (int) (paddingSizeDp * scale + 0.5f);
+
+ final TextView textView = new TextView(this);
+ final SpannableString text = new SpannableString(getString(R.string.about_dialog_text));
+
+ textView.setText(text);
+ textView.setAutoLinkMask(RESULT_OK);
+ textView.setMovementMethod(LinkMovementMethod.getInstance());
+ textView.setPadding(dpAsPixels, dpAsPixels, dpAsPixels, dpAsPixels);
+
+ Linkify.addLinks(text, Linkify.ALL);
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.menu_about)
+ .setCancelable(false)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(final DialogInterface dialog, final int id) {
+ }
+ })
+ .setView(textView)
+ .show();
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ ButterKnife.bind(this);
+ mList.setEmptyView(mEmpty);
+ mList.setOnItemClickListener(this);
+ mDeviceStore = new BluetoothLeDeviceStore();
+ mBluetoothUtils = new BluetoothUtils(this);
+ mScanner = new BluetoothLeScanner(mLeScanCallback, mBluetoothUtils);
+ updateItemCount(0);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ getMenuInflater().inflate(R.menu.main, menu);
+ if (!mScanner.isScanning()) {
+ menu.findItem(R.id.menu_stop).setVisible(false);
+ menu.findItem(R.id.menu_scan).setVisible(true);
+ menu.findItem(R.id.menu_refresh).setActionView(null);
+ } else {
+ menu.findItem(R.id.menu_stop).setVisible(true);
+ menu.findItem(R.id.menu_scan).setVisible(false);
+ menu.findItem(R.id.menu_refresh).setActionView(R.layout.actionbar_progress_indeterminate);
+ }
+
+ if (mList.getCount() > 0) {
+ menu.findItem(R.id.menu_share).setVisible(true);
+ } else {
+ menu.findItem(R.id.menu_share).setVisible(false);
+ }
+
+ return true;
+ }
+
+ @Override
+ public void onItemClick(AdapterView> adapterView, View view, int position, long l) {
+ final BluetoothLeDevice device = mLeDeviceListAdapter.getItem(position);
+ if (device == null) return;
+
+ final Intent intent = new Intent(this, DeviceDetailsActivity.class);
+ intent.putExtra(DeviceDetailsActivity.EXTRA_DEVICE, device);
+
+ startActivity(intent);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_scan:
+ startScan();
+ break;
+ case R.id.menu_stop:
+ mScanner.scanLeDevice(-1, false);
+ invalidateOptionsMenu();
+ break;
+ case R.id.menu_about:
+ displayAboutDialog();
+ break;
+ case R.id.menu_share:
+ mDeviceStore.shareDataAsEmail(this);
+ }
+ return true;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mScanner.scanLeDevice(-1, false);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ final boolean mIsBluetoothOn = mBluetoothUtils.isBluetoothOn();
+ final boolean mIsBluetoothLePresent = mBluetoothUtils.isBluetoothLeSupported();
+
+ if (mIsBluetoothOn) {
+ mTvBluetoothStatus.setText(R.string.on);
+ } else {
+ mTvBluetoothStatus.setText(R.string.off);
+ }
+
+ if (mIsBluetoothLePresent) {
+ mTvBluetoothLeStatus.setText(R.string.supported);
+ } else {
+ mTvBluetoothLeStatus.setText(R.string.not_supported);
+ }
+
+ invalidateOptionsMenu();
+ }
+
+ private void startScan() {
+ final boolean mIsBluetoothOn = mBluetoothUtils.isBluetoothOn();
+ final boolean mIsBluetoothLePresent = mBluetoothUtils.isBluetoothLeSupported();
+ mDeviceStore.clear();
+ updateItemCount(0);
+
+ mLeDeviceListAdapter = new LeDeviceListAdapter(this, mDeviceStore.getDeviceCursor());
+ mList.setAdapter(mLeDeviceListAdapter);
+
+ mBluetoothUtils.askUserToEnableBluetoothIfNeeded();
+ if (mIsBluetoothOn && mIsBluetoothLePresent) {
+ mScanner.scanLeDevice(-1, true);
+ invalidateOptionsMenu();
+ }
+ }
+
+ private void updateItemCount(final int count) {
+ mTvItemCount.setText(
+ getString(
+ R.string.formatter_item_count,
+ String.valueOf(count)));
+ }
+
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/adapters/LeDeviceListAdapter.java b/sample_app/src/main/java/uk/co/alt236/btlescan/adapters/LeDeviceListAdapter.java
new file mode 100644
index 0000000..97cbdbc
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/adapters/LeDeviceListAdapter.java
@@ -0,0 +1,126 @@
+package uk.co.alt236.btlescan.adapters;
+
+import android.app.Activity;
+import android.support.v4.widget.SimpleCursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
+import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
+import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
+import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconDevice;
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.util.Constants;
+import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
+
+// Adapter for holding devices found through scanning.
+public class LeDeviceListAdapter extends SimpleCursorAdapter {
+ private final LayoutInflater mInflator;
+ private final Activity mActivity;
+
+ public LeDeviceListAdapter(final Activity activity, final EasyObjectCursor cursor) {
+ super(activity, R.layout.list_item_device, cursor, new String[0], new int[0], 0);
+ mInflator = activity.getLayoutInflater();
+ mActivity = activity;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public EasyObjectCursor getCursor() {
+ return ((EasyObjectCursor) super.getCursor());
+ }
+
+ @Override
+ public BluetoothLeDevice getItem(final int i) {
+ return getCursor().getItem(i);
+ }
+
+ @Override
+ public long getItemId(final int i) {
+ return i;
+ }
+
+ @Override
+ public View getView(final int i, View view, final ViewGroup viewGroup) {
+ final ViewHolder viewHolder;
+ // General ListView optimization code.
+ if (view == null) {
+ view = mInflator.inflate(R.layout.list_item_device, null);
+ viewHolder = new ViewHolder();
+ viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
+ viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
+ viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi);
+ viewHolder.deviceIcon = (ImageView) view.findViewById(R.id.device_icon);
+ viewHolder.deviceLastUpdated = (TextView) view.findViewById(R.id.device_last_update);
+ viewHolder.ibeaconMajor = (TextView) view.findViewById(R.id.ibeacon_major);
+ viewHolder.ibeaconMinor = (TextView) view.findViewById(R.id.ibeacon_minor);
+ viewHolder.ibeaconDistance = (TextView) view.findViewById(R.id.ibeacon_distance);
+ viewHolder.ibeaconUUID = (TextView) view.findViewById(R.id.ibeacon_uuid);
+ viewHolder.ibeaconTxPower = (TextView) view.findViewById(R.id.ibeacon_tx_power);
+ viewHolder.ibeaconSection = view.findViewById(R.id.ibeacon_section);
+ viewHolder.ibeaconDistanceDescriptor = (TextView) view.findViewById(R.id.ibeacon_distance_descriptor);
+ view.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) view.getTag();
+ }
+
+ final BluetoothLeDevice device = getCursor().getItem(i);
+ final String deviceName = device.getName();
+ final double rssi = device.getRssi();
+
+ if (deviceName != null && deviceName.length() > 0) {
+ viewHolder.deviceName.setText(deviceName);
+ } else {
+ viewHolder.deviceName.setText(R.string.unknown_device);
+ }
+
+ if (BeaconUtils.getBeaconType(device) == BeaconType.IBEACON) {
+ final IBeaconDevice iBeacon = new IBeaconDevice(device);
+ final String accuracy = Constants.DOUBLE_TWO_DIGIT_ACCURACY.format(iBeacon.getAccuracy());
+
+ viewHolder.deviceIcon.setImageResource(R.drawable.ic_device_ibeacon);
+ viewHolder.ibeaconSection.setVisibility(View.VISIBLE);
+ viewHolder.ibeaconMajor.setText(String.valueOf(iBeacon.getMajor()));
+ viewHolder.ibeaconMinor.setText(String.valueOf(iBeacon.getMinor()));
+ viewHolder.ibeaconTxPower.setText(String.valueOf(iBeacon.getCalibratedTxPower()));
+ viewHolder.ibeaconUUID.setText(iBeacon.getUUID());
+ viewHolder.ibeaconDistance.setText(
+ mActivity.getString(R.string.formatter_meters, accuracy));
+ viewHolder.ibeaconDistanceDescriptor.setText(iBeacon.getDistanceDescriptor().toString());
+ } else {
+ viewHolder.deviceIcon.setImageResource(R.drawable.ic_bluetooth);
+ viewHolder.ibeaconSection.setVisibility(View.GONE);
+ }
+
+ final String rssiString =
+ mActivity.getString(R.string.formatter_db, String.valueOf(rssi));
+ final String runningAverageRssiString =
+ mActivity.getString(R.string.formatter_db, String.valueOf(device.getRunningAverageRssi()));
+
+ viewHolder.deviceLastUpdated.setText(
+ android.text.format.DateFormat.format(
+ Constants.TIME_FORMAT, new java.util.Date(device.getTimestamp())));
+ viewHolder.deviceAddress.setText(device.getAddress());
+ viewHolder.deviceRssi.setText(rssiString + " / " + runningAverageRssiString);
+ return view;
+ }
+
+ static class ViewHolder {
+ TextView deviceName;
+ TextView deviceAddress;
+ TextView deviceRssi;
+ TextView ibeaconUUID;
+ TextView ibeaconMajor;
+ TextView ibeaconMinor;
+ TextView ibeaconTxPower;
+ TextView ibeaconDistance;
+ TextView ibeaconDistanceDescriptor;
+ TextView deviceLastUpdated;
+ View ibeaconSection;
+ ImageView deviceIcon;
+ }
+
+}
\ No newline at end of file
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/containers/BluetoothLeDeviceStore.java b/sample_app/src/main/java/uk/co/alt236/btlescan/containers/BluetoothLeDeviceStore.java
new file mode 100644
index 0000000..8b99033
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/containers/BluetoothLeDeviceStore.java
@@ -0,0 +1,181 @@
+package uk.co.alt236.btlescan.containers;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
+import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
+import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
+import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconDevice;
+import uk.co.alt236.bluetoothlelib.util.ByteUtils;
+import uk.co.alt236.btlescan.R;
+import uk.co.alt236.btlescan.util.CsvWriterHelper;
+import uk.co.alt236.btlescan.util.TimeFormatter;
+import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
+
+public class BluetoothLeDeviceStore {
+ private final Map mDeviceMap;
+
+
+ public BluetoothLeDeviceStore() {
+ mDeviceMap = new HashMap<>();
+ }
+
+ public void addDevice(final BluetoothLeDevice device) {
+ if (mDeviceMap.containsKey(device.getAddress())) {
+ mDeviceMap.get(device.getAddress()).updateRssiReading(device.getTimestamp(), device.getRssi());
+ } else {
+ mDeviceMap.put(device.getAddress(), device);
+ }
+ }
+
+ public void clear() {
+ mDeviceMap.clear();
+ }
+
+ public EasyObjectCursor getDeviceCursor() {
+ return new EasyObjectCursor<>(
+ BluetoothLeDevice.class,
+ getDeviceList(),
+ "address");
+ }
+
+ public List getDeviceList() {
+ final List methodResult = new ArrayList<>(mDeviceMap.values());
+
+ Collections.sort(methodResult, new Comparator() {
+
+ @Override
+ public int compare(final BluetoothLeDevice arg0, final BluetoothLeDevice arg1) {
+ return arg0.getAddress().compareToIgnoreCase(arg1.getAddress());
+ }
+ });
+
+ return methodResult;
+ }
+
+ private String getListAsCsv() {
+ final List list = getDeviceList();
+ final StringBuilder sb = new StringBuilder();
+ sb.append(CsvWriterHelper.addStuff("mac"));
+ sb.append(CsvWriterHelper.addStuff("name"));
+ sb.append(CsvWriterHelper.addStuff("firstTimestamp"));
+ sb.append(CsvWriterHelper.addStuff("firstRssi"));
+ sb.append(CsvWriterHelper.addStuff("currentTimestamp"));
+ sb.append(CsvWriterHelper.addStuff("currentRssi"));
+ sb.append(CsvWriterHelper.addStuff("adRecord"));
+ sb.append(CsvWriterHelper.addStuff("iBeacon"));
+ sb.append(CsvWriterHelper.addStuff("uuid"));
+ sb.append(CsvWriterHelper.addStuff("major"));
+ sb.append(CsvWriterHelper.addStuff("minor"));
+ sb.append(CsvWriterHelper.addStuff("txPower"));
+ sb.append(CsvWriterHelper.addStuff("distance"));
+ sb.append(CsvWriterHelper.addStuff("accuracy"));
+ sb.append('\n');
+
+ for (final BluetoothLeDevice device : list) {
+ sb.append(CsvWriterHelper.addStuff(device.getAddress()));
+ sb.append(CsvWriterHelper.addStuff(device.getName()));
+ sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getFirstTimestamp())));
+ sb.append(CsvWriterHelper.addStuff(device.getFirstRssi()));
+ sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getTimestamp())));
+ sb.append(CsvWriterHelper.addStuff(device.getRssi()));
+ sb.append(CsvWriterHelper.addStuff(ByteUtils.byteArrayToHexString(device.getScanRecord())));
+ final boolean isIBeacon = BeaconUtils.getBeaconType(device) == BeaconType.IBEACON;
+ final String uuid;
+ final String minor;
+ final String major;
+ final String txPower;
+ final String distance;
+ final String accuracy;
+
+ if (isIBeacon) {
+ final IBeaconDevice beacon = new IBeaconDevice(device);
+ uuid = String.valueOf(beacon.getUUID());
+ minor = String.valueOf(beacon.getMinor());
+ major = String.valueOf(beacon.getMajor());
+ txPower = String.valueOf(beacon.getCalibratedTxPower());
+ distance = beacon.getDistanceDescriptor().toString().toLowerCase(Locale.US);
+ accuracy = String.valueOf(beacon.getAccuracy());
+ } else {
+ uuid = "";
+ minor = "";
+ major = "";
+ txPower = "";
+ distance = "";
+ accuracy = "";
+ }
+
+ sb.append(CsvWriterHelper.addStuff(isIBeacon));
+ sb.append(CsvWriterHelper.addStuff(uuid));
+ sb.append(CsvWriterHelper.addStuff(minor));
+ sb.append(CsvWriterHelper.addStuff(major));
+ sb.append(CsvWriterHelper.addStuff(txPower));
+ sb.append(CsvWriterHelper.addStuff(distance));
+ sb.append(CsvWriterHelper.addStuff(accuracy));
+
+ sb.append('\n');
+ }
+
+ return sb.toString();
+ }
+
+ public void shareDataAsEmail(final Context context) {
+ final long timeInMillis = System.currentTimeMillis();
+
+ final String to = null;
+ final String subject = context.getString(
+ R.string.exporter_email_device_list_subject,
+ TimeFormatter.getIsoDateTime(timeInMillis));
+
+ final String message = context.getString(R.string.exporter_email_device_list_body);
+
+ final Intent i = new Intent(Intent.ACTION_SEND);
+ i.setType("plain/text");
+ try {
+ final File outputDir = context.getCacheDir();
+ final File outputFile = File.createTempFile("bluetooth_le_" + timeInMillis, ".csv", outputDir);
+ outputFile.setReadable(true, false);
+ generateFile(outputFile, getListAsCsv());
+ i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(outputFile));
+ i.putExtra(Intent.EXTRA_EMAIL, new String[]{to});
+ i.putExtra(Intent.EXTRA_SUBJECT, subject);
+ i.putExtra(Intent.EXTRA_TEXT, message);
+ context.startActivity(Intent.createChooser(i, context.getString(R.string.exporter_email_device_list_picker_text)));
+
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static FileWriter generateFile(final File file, final String contents) {
+ FileWriter writer = null;
+ try {
+ writer = new FileWriter(file);
+ writer.append(contents);
+ writer.flush();
+
+ } catch (final IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ writer.close();
+ } catch (final IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return writer;
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/services/BluetoothLeService.java b/sample_app/src/main/java/uk/co/alt236/btlescan/services/BluetoothLeService.java
new file mode 100644
index 0000000..bc33610
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/services/BluetoothLeService.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.co.alt236.btlescan.services;
+
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * Service for managing connection and data communication with a GATT server hosted on a
+ * given Bluetooth LE device.
+ */
+public class BluetoothLeService extends Service {
+ public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
+ public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
+ public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
+ public final static String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
+ public final static String EXTRA_DATA_RAW = "com.example.bluetooth.le.EXTRA_DATA_RAW";
+ public final static String EXTRA_UUID_CHAR = "com.example.bluetooth.le.EXTRA_UUID_CHAR";
+ private final static String TAG = BluetoothLeService.class.getSimpleName();
+ private static final int STATE_DISCONNECTED = 0;
+ private static final int STATE_CONNECTING = 1;
+ private static final int STATE_CONNECTED = 2;
+ private final IBinder mBinder = new LocalBinder();
+ private BluetoothManager mBluetoothManager;
+ private BluetoothAdapter mBluetoothAdapter;
+ private String mBluetoothDeviceAddress;
+ private BluetoothGatt mBluetoothGatt;
+ private int mConnectionState = STATE_DISCONNECTED;
+ // Implements callback methods for GATT events that the app cares about. For example,
+ // connection change and services discovered.
+ private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
+ @Override
+ public void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
+ broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
+ }
+
+ @Override
+ public void onCharacteristicRead(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) {
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
+ }
+ }
+
+ @Override
+ public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
+ final String intentAction;
+ if (newState == BluetoothProfile.STATE_CONNECTED) {
+ intentAction = ACTION_GATT_CONNECTED;
+ mConnectionState = STATE_CONNECTED;
+ broadcastUpdate(intentAction);
+ Log.i(TAG, "Connected to GATT server.");
+ // Attempts to discover services after successful connection.
+ Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
+
+ } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
+ intentAction = ACTION_GATT_DISCONNECTED;
+ mConnectionState = STATE_DISCONNECTED;
+ Log.i(TAG, "Disconnected from GATT server.");
+ broadcastUpdate(intentAction);
+ }
+ }
+
+ @Override
+ public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
+ } else {
+ Log.w(TAG, "onServicesDiscovered received: " + status);
+ }
+ }
+ };
+
+ private void broadcastUpdate(final String action) {
+ final Intent intent = new Intent(action);
+ sendBroadcast(intent);
+ }
+
+ private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
+ final Intent intent = new Intent(action);
+ intent.putExtra(EXTRA_UUID_CHAR, characteristic.getUuid().toString());
+
+ // Always try to add the RAW value
+ final byte[] data = characteristic.getValue();
+ if (data != null && data.length > 0) {
+ intent.putExtra(EXTRA_DATA_RAW, data);
+ }
+
+ sendBroadcast(intent);
+ }
+
+ /**
+ * After using a given BLE device, the app must call this method to ensure resources are
+ * released properly.
+ */
+ public void close() {
+ if (mBluetoothGatt == null) {
+ return;
+ }
+ mBluetoothGatt.close();
+ mBluetoothGatt = null;
+ }
+
+ /**
+ * Connects to the GATT server hosted on the Bluetooth LE device.
+ *
+ * @param address The device address of the destination device.
+ * @return Return true if the connection is initiated successfully. The connection result
+ * is reported asynchronously through the
+ * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
+ * callback.
+ */
+ public boolean connect(final String address) {
+ if (mBluetoothAdapter == null || address == null) {
+ Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
+ return false;
+ }
+
+ // Previously connected device. Try to reconnect.
+ if (mBluetoothDeviceAddress != null
+ && address.equals(mBluetoothDeviceAddress)
+ && mBluetoothGatt != null) {
+
+ Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
+ if (mBluetoothGatt.connect()) {
+ mConnectionState = STATE_CONNECTING;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
+ if (device == null) {
+ Log.w(TAG, "Device not found. Unable to connect.");
+ return false;
+ }
+ // We want to directly connect to the device, so we are setting the autoConnect
+ // parameter to false.
+ mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
+ Log.d(TAG, "Trying to create a new connection.");
+ mBluetoothDeviceAddress = address;
+ mConnectionState = STATE_CONNECTING;
+ return true;
+ }
+
+ /**
+ * Disconnects an existing connection or cancel a pending connection. The disconnection result
+ * is reported asynchronously through the
+ * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
+ * callback.
+ */
+ public void disconnect() {
+ if (mBluetoothAdapter == null || mBluetoothGatt == null) {
+ Log.w(TAG, "BluetoothAdapter not initialized");
+ return;
+ }
+ mBluetoothGatt.disconnect();
+ }
+
+ /**
+ * Retrieves a list of supported GATT services on the connected device. This should be
+ * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
+ *
+ * @return A {@code List} of supported services.
+ */
+ public List getSupportedGattServices() {
+ if (mBluetoothGatt == null) return null;
+
+ return mBluetoothGatt.getServices();
+ }
+
+ /**
+ * Initializes a reference to the local Bluetooth adapter.
+ *
+ * @return Return true if the initialization is successful.
+ */
+ public boolean initialize() {
+ // For API level 18 and above, get a reference to BluetoothAdapter through
+ // BluetoothManager.
+ if (mBluetoothManager == null) {
+ mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ if (mBluetoothManager == null) {
+ Log.e(TAG, "Unable to initialize BluetoothManager.");
+ return false;
+ }
+ }
+
+ mBluetoothAdapter = mBluetoothManager.getAdapter();
+ if (mBluetoothAdapter == null) {
+ Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public IBinder onBind(final Intent intent) {
+ return mBinder;
+ }
+
+ @Override
+ public boolean onUnbind(final Intent intent) {
+ // After using a given device, you should make sure that BluetoothGatt.close() is called
+ // such that resources are cleaned up properly. In this particular example, close() is
+ // invoked when the UI is disconnected from the Service.
+ close();
+ return super.onUnbind(intent);
+ }
+
+ /**
+ * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
+ * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
+ * callback.
+ *
+ * @param characteristic The characteristic to read from.
+ */
+ public void readCharacteristic(final BluetoothGattCharacteristic characteristic) {
+ if (mBluetoothAdapter == null || mBluetoothGatt == null) {
+ Log.w(TAG, "BluetoothAdapter not initialized");
+ return;
+ }
+ mBluetoothGatt.readCharacteristic(characteristic);
+ }
+
+ /**
+ * Enables or disables notification on a give characteristic.
+ *
+ * @param characteristic Characteristic to act on.
+ * @param enabled If true, enable notification. False otherwise.
+ */
+ public void setCharacteristicNotification(final BluetoothGattCharacteristic characteristic, final boolean enabled) {
+ if (mBluetoothAdapter == null || mBluetoothGatt == null) {
+ Log.w(TAG, "BluetoothAdapter not initialized");
+ return;
+ }
+ mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
+ }
+
+ public class LocalBinder extends Binder {
+ public BluetoothLeService getService() {
+ return BluetoothLeService.this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/util/BluetoothLeScanner.java b/sample_app/src/main/java/uk/co/alt236/btlescan/util/BluetoothLeScanner.java
new file mode 100644
index 0000000..b08c13d
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/util/BluetoothLeScanner.java
@@ -0,0 +1,48 @@
+package uk.co.alt236.btlescan.util;
+
+import android.bluetooth.BluetoothAdapter;
+import android.os.Handler;
+import android.util.Log;
+
+public class BluetoothLeScanner {
+ private final Handler mHandler;
+ private final BluetoothAdapter.LeScanCallback mLeScanCallback;
+ private final BluetoothUtils mBluetoothUtils;
+ private boolean mScanning;
+
+ public BluetoothLeScanner(final BluetoothAdapter.LeScanCallback leScanCallback, final BluetoothUtils bluetoothUtils) {
+ mHandler = new Handler();
+ mLeScanCallback = leScanCallback;
+ mBluetoothUtils = bluetoothUtils;
+ }
+
+ public boolean isScanning() {
+ return mScanning;
+ }
+
+ public void scanLeDevice(final int duration, final boolean enable) {
+ if (enable) {
+ if (mScanning) {
+ return;
+ }
+ Log.d("TAG", "~ Starting Scan");
+ // Stops scanning after a pre-defined scan period.
+ if (duration > 0) {
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ Log.d("TAG", "~ Stopping Scan (timeout)");
+ mScanning = false;
+ mBluetoothUtils.getBluetoothAdapter().stopLeScan(mLeScanCallback);
+ }
+ }, duration);
+ }
+ mScanning = true;
+ mBluetoothUtils.getBluetoothAdapter().startLeScan(mLeScanCallback);
+ } else {
+ Log.d("TAG", "~ Stopping Scan");
+ mScanning = false;
+ mBluetoothUtils.getBluetoothAdapter().stopLeScan(mLeScanCallback);
+ }
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/util/BluetoothUtils.java b/sample_app/src/main/java/uk/co/alt236/btlescan/util/BluetoothUtils.java
new file mode 100644
index 0000000..87d5bda
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/util/BluetoothUtils.java
@@ -0,0 +1,43 @@
+package uk.co.alt236.btlescan.util;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+
+public final class BluetoothUtils {
+ public final static int REQUEST_ENABLE_BT = 2001;
+ private final Activity mActivity;
+ private final BluetoothAdapter mBluetoothAdapter;
+
+ public BluetoothUtils(final Activity activity) {
+ mActivity = activity;
+ final BluetoothManager btManager = (BluetoothManager) mActivity.getSystemService(Context.BLUETOOTH_SERVICE);
+ mBluetoothAdapter = btManager.getAdapter();
+ }
+
+ public void askUserToEnableBluetoothIfNeeded() {
+ if (isBluetoothLeSupported() && (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled())) {
+ final Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ mActivity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+ }
+ }
+
+ public BluetoothAdapter getBluetoothAdapter() {
+ return mBluetoothAdapter;
+ }
+
+ public boolean isBluetoothLeSupported() {
+ return mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
+ }
+
+ public boolean isBluetoothOn() {
+ if (mBluetoothAdapter == null) {
+ return false;
+ } else {
+ return mBluetoothAdapter.isEnabled();
+ }
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/util/Constants.java b/sample_app/src/main/java/uk/co/alt236/btlescan/util/Constants.java
new file mode 100644
index 0000000..f0b7b59
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/util/Constants.java
@@ -0,0 +1,8 @@
+package uk.co.alt236.btlescan.util;
+
+import java.text.DecimalFormat;
+
+public class Constants {
+ public static final DecimalFormat DOUBLE_TWO_DIGIT_ACCURACY = new DecimalFormat("#.##");
+ public static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/util/CsvWriterHelper.java b/sample_app/src/main/java/uk/co/alt236/btlescan/util/CsvWriterHelper.java
new file mode 100644
index 0000000..f8bff7d
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/util/CsvWriterHelper.java
@@ -0,0 +1,26 @@
+package uk.co.alt236.btlescan.util;
+
+public class CsvWriterHelper {
+ private static final String QUOTE = "\"";
+
+ public static String addStuff(final Integer text) {
+ return QUOTE + text + QUOTE + ",";
+ }
+
+ public static String addStuff(final Long text) {
+ return QUOTE + text + QUOTE + ",";
+ }
+
+ public static String addStuff(final boolean value) {
+ return QUOTE + value + QUOTE + ",";
+ }
+
+ public static String addStuff(String text) {
+ if (text == null) {
+ text = "";
+ }
+ text = text.replace(QUOTE, "'");
+
+ return QUOTE + text.trim() + QUOTE + ",";
+ }
+}
diff --git a/sample_app/src/main/java/uk/co/alt236/btlescan/util/TimeFormatter.java b/sample_app/src/main/java/uk/co/alt236/btlescan/util/TimeFormatter.java
new file mode 100644
index 0000000..7d43826
--- /dev/null
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/util/TimeFormatter.java
@@ -0,0 +1,18 @@
+package uk.co.alt236.btlescan.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class TimeFormatter {
+ private final static String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
+ private final static SimpleDateFormat ISO_FORMATTER = new UtcDateFormatter(ISO_FORMAT, Locale.US);
+
+ public static String getIsoDateTime(final Date date) {
+ return ISO_FORMATTER.format(date);
+ }
+
+ public static String getIsoDateTime(final long millis) {
+ return getIsoDateTime(new Date(millis));
+ }
+}
diff --git a/sample_app/src/uk/co/alt236/btlescan/util/UtcDateFormatter.java b/sample_app/src/main/java/uk/co/alt236/btlescan/util/UtcDateFormatter.java
similarity index 50%
rename from sample_app/src/uk/co/alt236/btlescan/util/UtcDateFormatter.java
rename to sample_app/src/main/java/uk/co/alt236/btlescan/util/UtcDateFormatter.java
index f0dca69..0b7176b 100644
--- a/sample_app/src/uk/co/alt236/btlescan/util/UtcDateFormatter.java
+++ b/sample_app/src/main/java/uk/co/alt236/btlescan/util/UtcDateFormatter.java
@@ -1,72 +1,74 @@
-/*******************************************************************************
+/**
+ * ****************************************************************************
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
+ *
* GenieConnect Ltd. ("COMPANY") CONFIDENTIAL
* Unpublished Copyright (c) 2010-2013 GenieConnect Ltd., All Rights Reserved.
- *
+ *
* NOTICE:
- * All information contained herein is, and remains the property of COMPANY.
- * The intellectual and technical concepts contained herein are proprietary to
- * COMPANY and may be covered by U.S. and Foreign Patents, patents in process, and
- * are protected by trade secret or copyright law. Dissemination of this
- * information or reproduction of this material is strictly forbidden unless prior
- * written permission is obtained from COMPANY. Access to the source code
- * contained herein is hereby forbidden to anyone except current COMPANY employees,
+ * All information contained herein is, and remains the property of COMPANY.
+ * The intellectual and technical concepts contained herein are proprietary to
+ * COMPANY and may be covered by U.S. and Foreign Patents, patents in process, and
+ * are protected by trade secret or copyright law. Dissemination of this
+ * information or reproduction of this material is strictly forbidden unless prior
+ * written permission is obtained from COMPANY. Access to the source code
+ * contained herein is hereby forbidden to anyone except current COMPANY employees,
* managers or contractors who have executed Confidentiality and Non-disclosure
* agreements explicitly covering such access.
- *
- * The copyright notice above does not evidence any actual or intended publication
- * or disclosure of this source code, which includes information that is
+ *
+ * The copyright notice above does not evidence any actual or intended publication
+ * or disclosure of this source code, which includes information that is
* confidential and/or proprietary, and is a trade secret, of COMPANY.
- *
- * ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE, OR PUBLIC
- * DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT THE EXPRESS WRITTEN
- * CONSENT OF COMPANY IS STRICTLY PROHIBITED, AND IN VIOLATION OF APPLICABLE LAWS
- * AND INTERNATIONAL TREATIES. THE RECEIPT OR POSSESSION OF THIS SOURCE CODE
- * AND/OR RELATED INFORMATION DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE,
- * DISCLOSE OR DISTRIBUTE ITS CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING
+ *
+ * ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE, OR PUBLIC
+ * DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT THE EXPRESS WRITTEN
+ * CONSENT OF COMPANY IS STRICTLY PROHIBITED, AND IN VIOLATION OF APPLICABLE LAWS
+ * AND INTERNATIONAL TREATIES. THE RECEIPT OR POSSESSION OF THIS SOURCE CODE
+ * AND/OR RELATED INFORMATION DOES NOT CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE,
+ * DISCLOSE OR DISTRIBUTE ITS CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING
* THAT IT MAY DESCRIBE, IN WHOLE OR IN PART.
- ******************************************************************************/
+ * ****************************************************************************
+ */
package uk.co.alt236.btlescan.util;
+import android.annotation.SuppressLint;
+
import java.text.DateFormatSymbols;
import java.util.Locale;
import java.util.TimeZone;
-import android.annotation.SuppressLint;
+public class UtcDateFormatter extends java.text.SimpleDateFormat {
+ private static final long serialVersionUID = 1L;
-public class UtcDateFormatter extends java.text.SimpleDateFormat{
- private static final long serialVersionUID = 1L;
-
- private static final String TIME_ZONE_STRING = "UTC";
- private static final TimeZone TIME_ZONE_UTC = TimeZone.getTimeZone(TIME_ZONE_STRING);
-
- @SuppressLint("SimpleDateFormat")
- public UtcDateFormatter(String template){
- super(template);
- super.setTimeZone(TIME_ZONE_UTC);
- }
-
- @SuppressLint("SimpleDateFormat")
- public UtcDateFormatter(String template, DateFormatSymbols symbols){
- super(template, symbols);
- super.setTimeZone(TIME_ZONE_UTC);
- }
-
- public UtcDateFormatter(String template, Locale locale){
- super(template, locale);
- super.setTimeZone(TIME_ZONE_UTC);
- }
-
- /*
- * This function will throw an UnsupportedOperationException.
- * You are not be able to change the TimeZone of this object
- *
- * (non-Javadoc)
- * @see java.text.DateFormat#setTimeZone(java.util.TimeZone)
- */
- @Override
- public void setTimeZone(TimeZone timezone){
- throw new UnsupportedOperationException("This SimpleDateFormat can only be in " + TIME_ZONE_STRING);
- }
+ private static final String TIME_ZONE_STRING = "UTC";
+ private static final TimeZone TIME_ZONE_UTC = TimeZone.getTimeZone(TIME_ZONE_STRING);
+
+ @SuppressLint("SimpleDateFormat")
+ public UtcDateFormatter(final String template) {
+ super(template);
+ super.setTimeZone(TIME_ZONE_UTC);
+ }
+
+ @SuppressLint("SimpleDateFormat")
+ public UtcDateFormatter(final String template, final DateFormatSymbols symbols) {
+ super(template, symbols);
+ super.setTimeZone(TIME_ZONE_UTC);
+ }
+
+ public UtcDateFormatter(final String template, final Locale locale) {
+ super(template, locale);
+ super.setTimeZone(TIME_ZONE_UTC);
+ }
+
+ /*
+ * This function will throw an UnsupportedOperationException.
+ * You are not be able to change the TimeZone of this object
+ *
+ * (non-Javadoc)
+ * @see java.text.DateFormat#setTimeZone(java.util.TimeZone)
+ */
+ @Override
+ public void setTimeZone(final TimeZone timezone) {
+ throw new UnsupportedOperationException("This SimpleDateFormat can only be in " + TIME_ZONE_STRING);
+ }
}
diff --git a/sample_app/res/drawable-hdpi/ic_action_share.png b/sample_app/src/main/res/drawable-hdpi/ic_action_share.png
similarity index 100%
rename from sample_app/res/drawable-hdpi/ic_action_share.png
rename to sample_app/src/main/res/drawable-hdpi/ic_action_share.png
diff --git a/sample_app/res/drawable-hdpi/ic_launcher.png b/sample_app/src/main/res/drawable-hdpi/ic_launcher.png
similarity index 100%
rename from sample_app/res/drawable-hdpi/ic_launcher.png
rename to sample_app/src/main/res/drawable-hdpi/ic_launcher.png
diff --git a/sample_app/res/drawable-mdpi/ic_action_share.png b/sample_app/src/main/res/drawable-mdpi/ic_action_share.png
similarity index 100%
rename from sample_app/res/drawable-mdpi/ic_action_share.png
rename to sample_app/src/main/res/drawable-mdpi/ic_action_share.png
diff --git a/sample_app/res/drawable-mdpi/ic_launcher.png b/sample_app/src/main/res/drawable-mdpi/ic_launcher.png
similarity index 100%
rename from sample_app/res/drawable-mdpi/ic_launcher.png
rename to sample_app/src/main/res/drawable-mdpi/ic_launcher.png
diff --git a/sample_app/res/drawable-xhdpi/ic_action_share.png b/sample_app/src/main/res/drawable-xhdpi/ic_action_share.png
similarity index 100%
rename from sample_app/res/drawable-xhdpi/ic_action_share.png
rename to sample_app/src/main/res/drawable-xhdpi/ic_action_share.png
diff --git a/sample_app/res/drawable-xhdpi/ic_bluetooth.png b/sample_app/src/main/res/drawable-xhdpi/ic_bluetooth.png
similarity index 100%
rename from sample_app/res/drawable-xhdpi/ic_bluetooth.png
rename to sample_app/src/main/res/drawable-xhdpi/ic_bluetooth.png
diff --git a/sample_app/res/drawable-xhdpi/ic_bluetooth_on.png b/sample_app/src/main/res/drawable-xhdpi/ic_bluetooth_on.png
similarity index 100%
rename from sample_app/res/drawable-xhdpi/ic_bluetooth_on.png
rename to sample_app/src/main/res/drawable-xhdpi/ic_bluetooth_on.png
diff --git a/sample_app/res/drawable-xhdpi/ic_device_ibeacon.png b/sample_app/src/main/res/drawable-xhdpi/ic_device_ibeacon.png
similarity index 100%
rename from sample_app/res/drawable-xhdpi/ic_device_ibeacon.png
rename to sample_app/src/main/res/drawable-xhdpi/ic_device_ibeacon.png
diff --git a/sample_app/res/drawable-xhdpi/ic_launcher.png b/sample_app/src/main/res/drawable-xhdpi/ic_launcher.png
similarity index 100%
rename from sample_app/res/drawable-xhdpi/ic_launcher.png
rename to sample_app/src/main/res/drawable-xhdpi/ic_launcher.png
diff --git a/sample_app/res/drawable-xxhdpi/ic_action_share.png b/sample_app/src/main/res/drawable-xxhdpi/ic_action_share.png
similarity index 100%
rename from sample_app/res/drawable-xxhdpi/ic_action_share.png
rename to sample_app/src/main/res/drawable-xxhdpi/ic_action_share.png
diff --git a/sample_app/res/drawable-xxhdpi/ic_launcher.png b/sample_app/src/main/res/drawable-xxhdpi/ic_launcher.png
similarity index 100%
rename from sample_app/res/drawable-xxhdpi/ic_launcher.png
rename to sample_app/src/main/res/drawable-xxhdpi/ic_launcher.png
diff --git a/sample_app/src/main/res/layout/actionbar_progress_indeterminate.xml b/sample_app/src/main/res/layout/actionbar_progress_indeterminate.xml
new file mode 100644
index 0000000..e408d2b
--- /dev/null
+++ b/sample_app/src/main/res/layout/actionbar_progress_indeterminate.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/sample_app/src/main/res/layout/activity_details.xml b/sample_app/src/main/res/layout/activity_details.xml
new file mode 100644
index 0000000..3100292
--- /dev/null
+++ b/sample_app/src/main/res/layout/activity_details.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/sample_app/res/layout/activity_gatt_services.xml b/sample_app/src/main/res/layout/activity_gatt_services.xml
similarity index 69%
rename from sample_app/res/layout/activity_gatt_services.xml
rename to sample_app/src/main/res/layout/activity_gatt_services.xml
index b60e56f..af806fb 100644
--- a/sample_app/res/layout/activity_gatt_services.xml
+++ b/sample_app/src/main/res/layout/activity_gatt_services.xml
@@ -15,13 +15,13 @@
limitations under the License.
-->
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin">
+ android:useDefaultMargins="true">
+ android:text="@string/label_device_address"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_state"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:background="@android:color/holo_blue_dark"/>
+ android:useDefaultMargins="true">
+ android:text="@string/label_uuid"/>
+ style="@style/GridLayoutDataTextViewMonospace"/>
+ android:text="@string/label_desc"/>
+ style="@style/GridLayoutDataTextViewMonospace"/>
+ android:text="@string/label_as_string"/>
+ style="@style/GridLayoutDataTextViewMonospace"/>
+ android:text="@string/label_as_array"/>
+ style="@style/GridLayoutDataTextViewMonospace"/>
+ android:background="@android:color/holo_blue_dark"/>
+ android:layout_below="@id/upperSepparator"/>
\ No newline at end of file
diff --git a/sample_app/res/layout/activity_main.xml b/sample_app/src/main/res/layout/activity_main.xml
similarity index 73%
rename from sample_app/res/layout/activity_main.xml
rename to sample_app/src/main/res/layout/activity_main.xml
index 995149d..ca783c9 100644
--- a/sample_app/res/layout/activity_main.xml
+++ b/sample_app/src/main/res/layout/activity_main.xml
@@ -1,20 +1,20 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context=".MainActivity">
+ android:paddingBottom="@dimen/activity_vertical_margin">
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
+ android:background="@android:color/holo_blue_dark"/>
+ android:orientation="vertical">
+ android:orientation="vertical">
+ android:background="@android:color/holo_blue_dark"/>
+ android:text="@string/formatter_item_count"/>
+ android:layout_alignParentTop="true"
+ android:orientation="vertical">
+ android:layout_height="match_parent"/>
+ android:text="@string/no_data"/>
diff --git a/sample_app/res/layout/list_item_device.xml b/sample_app/src/main/res/layout/list_item_device.xml
similarity index 82%
rename from sample_app/res/layout/list_item_device.xml
rename to sample_app/src/main/res/layout/list_item_device.xml
index 62be902..4a2bc2d 100644
--- a/sample_app/res/layout/list_item_device.xml
+++ b/sample_app/src/main/res/layout/list_item_device.xml
@@ -15,34 +15,34 @@
limitations under the License.
-->
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="top"
+ android:orientation="horizontal">
+ android:paddingTop="5dp"
+ android:src="@drawable/ic_bluetooth"/>
+ android:orientation="vertical">
+ android:textSize="24sp"/>
+ android:columnCount="2">
+ android:textStyle="bold"/>
+ android:typeface="monospace"/>
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
+ android:columnCount="4">
@@ -105,7 +105,7 @@
android:paddingRight="5dp"
android:text="@string/label_uuid"
android:textSize="12sp"
- android:textStyle="bold" />
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
@@ -123,14 +123,14 @@
android:paddingRight="5dp"
android:text="@string/label_major"
android:textSize="12sp"
- android:textStyle="bold" />
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
@@ -156,14 +156,14 @@
android:paddingRight="5dp"
android:text="@string/label_tx_power"
android:textSize="12sp"
- android:textStyle="bold" />
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
@@ -187,9 +187,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dp"
- android:text="Descriptor:"
+ android:text="@string/label_decriptor"
android:textSize="12sp"
- android:textStyle="bold" />
+ android:textStyle="bold"/>
+ android:textSize="12sp"/>
diff --git a/sample_app/res/layout/list_item_view_adrecord.xml b/sample_app/src/main/res/layout/list_item_view_adrecord.xml
similarity index 62%
rename from sample_app/res/layout/list_item_view_adrecord.xml
rename to sample_app/src/main/res/layout/list_item_view_adrecord.xml
index e5cd158..b020ead 100644
--- a/sample_app/res/layout/list_item_view_adrecord.xml
+++ b/sample_app/src/main/res/layout/list_item_view_adrecord.xml
@@ -1,43 +1,43 @@
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="top"
+ android:orientation="vertical"
+ android:paddingBottom="5dp">
+ android:textStyle="bold"/>
+ android:useDefaultMargins="true">
+ android:text="@string/label_as_string"/>
+ style="@style/GridLayoutDataTextViewMonospace"/>
+ android:text="@string/label_as_array"/>
+ style="@style/GridLayoutDataTextViewMonospace"/>
\ No newline at end of file
diff --git a/sample_app/src/main/res/layout/list_item_view_device_info.xml b/sample_app/src/main/res/layout/list_item_view_device_info.xml
new file mode 100644
index 0000000..239480f
--- /dev/null
+++ b/sample_app/src/main/res/layout/list_item_view_device_info.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample_app/res/layout/list_item_view_header.xml b/sample_app/src/main/res/layout/list_item_view_header.xml
similarity index 58%
rename from sample_app/res/layout/list_item_view_header.xml
rename to sample_app/src/main/res/layout/list_item_view_header.xml
index b218ade..e92024e 100644
--- a/sample_app/res/layout/list_item_view_header.xml
+++ b/sample_app/src/main/res/layout/list_item_view_header.xml
@@ -1,10 +1,10 @@
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="top"
+ android:orientation="vertical"
+ android:paddingBottom="5dp">
+ android:textStyle="bold"/>
+ android:background="@android:color/holo_blue_dark"/>
\ No newline at end of file
diff --git a/sample_app/res/layout/list_item_view_ibeacon_details.xml b/sample_app/src/main/res/layout/list_item_view_ibeacon_details.xml
similarity index 64%
rename from sample_app/res/layout/list_item_view_ibeacon_details.xml
rename to sample_app/src/main/res/layout/list_item_view_ibeacon_details.xml
index dc6ddf6..aaddcc1 100644
--- a/sample_app/res/layout/list_item_view_ibeacon_details.xml
+++ b/sample_app/src/main/res/layout/list_item_view_ibeacon_details.xml
@@ -1,76 +1,76 @@
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="top"
+ android:orientation="vertical"
+ android:paddingBottom="5dp">
+ android:useDefaultMargins="true">
+ android:text="@string/label_company_id"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_advertisement"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_uuid"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_major"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_minor"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_tx_power"/>
+ style="@style/GridLayoutDataTextView"/>
\ No newline at end of file
diff --git a/sample_app/res/layout/list_item_view_rssi_info.xml b/sample_app/src/main/res/layout/list_item_view_rssi_info.xml
similarity index 63%
rename from sample_app/res/layout/list_item_view_rssi_info.xml
rename to sample_app/src/main/res/layout/list_item_view_rssi_info.xml
index 2bc97c5..4e1163d 100644
--- a/sample_app/res/layout/list_item_view_rssi_info.xml
+++ b/sample_app/src/main/res/layout/list_item_view_rssi_info.xml
@@ -1,66 +1,66 @@
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="top"
+ android:orientation="vertical"
+ android:paddingBottom="5dp">
+ android:useDefaultMargins="true">
+ android:text="@string/label_first_timestamp"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_first_rssi"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_last_timestamp"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_last_rssi"/>
+ style="@style/GridLayoutDataTextView"/>
+ android:text="@string/label_running_average_rssi"/>
+ style="@style/GridLayoutDataTextView"/>
\ No newline at end of file
diff --git a/sample_app/src/main/res/layout/list_item_view_textview.xml b/sample_app/src/main/res/layout/list_item_view_textview.xml
new file mode 100644
index 0000000..5131ef2
--- /dev/null
+++ b/sample_app/src/main/res/layout/list_item_view_textview.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample_app/res/menu/details.xml b/sample_app/src/main/res/menu/details.xml
similarity index 84%
rename from sample_app/res/menu/details.xml
rename to sample_app/src/main/res/menu/details.xml
index 4bf3056..dde8544 100644
--- a/sample_app/res/menu/details.xml
+++ b/sample_app/src/main/res/menu/details.xml
@@ -14,14 +14,15 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
+ android:title="@string/menu_connect"
+ app:showAsAction="always|withText"/>
\ No newline at end of file
diff --git a/sample_app/res/menu/gatt_services.xml b/sample_app/src/main/res/menu/gatt_services.xml
similarity index 75%
rename from sample_app/res/menu/gatt_services.xml
rename to sample_app/src/main/res/menu/gatt_services.xml
index 5c2909b..f5ed52b 100644
--- a/sample_app/res/menu/gatt_services.xml
+++ b/sample_app/src/main/res/menu/gatt_services.xml
@@ -14,28 +14,30 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
+ android:title=""
+ app:showAsAction="always"/>
+ android:title="@string/menu_share"
+ app:showAsAction="ifRoom"/>
+ android:title="@string/menu_connect"
+ app:showAsAction="ifRoom|withText"/>
+ android:title="@string/menu_disconnect"
+ app:showAsAction="ifRoom|withText"/>
\ No newline at end of file
diff --git a/sample_app/res/menu/main.xml b/sample_app/src/main/res/menu/main.xml
similarity index 73%
rename from sample_app/res/menu/main.xml
rename to sample_app/src/main/res/menu/main.xml
index c1afc17..e0858d8 100644
--- a/sample_app/res/menu/main.xml
+++ b/sample_app/src/main/res/menu/main.xml
@@ -14,33 +14,36 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
+
+ android:title=""
+ app:showAsAction="always"/>
+
+ android:title="@string/menu_scan"
+ app:showAsAction="ifRoom|withText"/>
+ android:title="@string/menu_stop"
+ app:showAsAction="ifRoom|withText"/>
+ android:orderInCategory="102"
+ android:title="@string/menu_share"
+ app:showAsAction="ifRoom"/>
+ android:title="@string/menu_about"
+ app:showAsAction="never"/>
\ No newline at end of file
diff --git a/sample_app/res/values-sw600dp/dimens.xml b/sample_app/src/main/res/values-sw600dp/dimens.xml
similarity index 100%
rename from sample_app/res/values-sw600dp/dimens.xml
rename to sample_app/src/main/res/values-sw600dp/dimens.xml
diff --git a/sample_app/res/values-sw720dp-land/dimens.xml b/sample_app/src/main/res/values-sw720dp-land/dimens.xml
similarity index 100%
rename from sample_app/res/values-sw720dp-land/dimens.xml
rename to sample_app/src/main/res/values-sw720dp-land/dimens.xml
diff --git a/sample_app/res/values-v11/styles.xml b/sample_app/src/main/res/values-v11/styles.xml
similarity index 77%
rename from sample_app/res/values-v11/styles.xml
rename to sample_app/src/main/res/values-v11/styles.xml
index 3c02242..c0ef0ed 100644
--- a/sample_app/res/values-v11/styles.xml
+++ b/sample_app/src/main/res/values-v11/styles.xml
@@ -4,7 +4,7 @@
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
-->
-
diff --git a/sample_app/res/values-v14/styles.xml b/sample_app/src/main/res/values-v14/styles.xml
similarity index 79%
rename from sample_app/res/values-v14/styles.xml
rename to sample_app/src/main/res/values-v14/styles.xml
index a91fd03..664f4f1 100644
--- a/sample_app/res/values-v14/styles.xml
+++ b/sample_app/src/main/res/values-v14/styles.xml
@@ -5,7 +5,7 @@
AppBaseTheme from BOTH res/values/styles.xml and
res/values-v11/styles.xml on API 14+ devices.
-->
-
diff --git a/sample_app/src/main/res/values/colors.xml b/sample_app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..c64f146
--- /dev/null
+++ b/sample_app/src/main/res/values/colors.xml
@@ -0,0 +1,3 @@
+
+ #66e0e0e0
+
diff --git a/sample_app/res/values/dimens.xml b/sample_app/src/main/res/values/dimens.xml
similarity index 100%
rename from sample_app/res/values/dimens.xml
rename to sample_app/src/main/res/values/dimens.xml
diff --git a/sample_app/res/values/strings.xml b/sample_app/src/main/res/values/strings.xml
similarity index 92%
rename from sample_app/res/values/strings.xml
rename to sample_app/src/main/res/values/strings.xml
index 7d0bf1d..84c3f4f 100644
--- a/sample_app/res/values/strings.xml
+++ b/sample_app/src/main/res/values/strings.xml
@@ -15,6 +15,7 @@
Unknown characteristic
Unknown device
Unknown service
+ No known services
%sm
@@ -53,6 +54,8 @@
Desc:
Device address:
Device Class:
+ Major Class:
+ Services:
Device Name:
Distance:
First RSSI:
@@ -67,5 +70,6 @@
State:
TX Power:
UUID:
-
+ Updated:
+ Descriptor:
\ No newline at end of file
diff --git a/sample_app/res/values/styles.xml b/sample_app/src/main/res/values/styles.xml
similarity index 85%
rename from sample_app/res/values/styles.xml
rename to sample_app/src/main/res/values/styles.xml
index 9cf5fd9..c503b3f 100644
--- a/sample_app/res/values/styles.xml
+++ b/sample_app/src/main/res/values/styles.xml
@@ -4,7 +4,7 @@
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
-
-
-
diff --git a/sample_app/src/uk/co/alt236/btlescan/activities/DeviceControlActivity.java b/sample_app/src/uk/co/alt236/btlescan/activities/DeviceControlActivity.java
deleted file mode 100644
index 314f41e..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/activities/DeviceControlActivity.java
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package uk.co.alt236.btlescan.activities;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
-import uk.co.alt236.bluetoothlelib.resolvers.GattAttributeResolver;
-import uk.co.alt236.bluetoothlelib.util.ByteUtils;
-import uk.co.alt236.btlescan.R;
-import uk.co.alt236.btlescan.services.BluetoothLeService;
-import android.app.Activity;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ExpandableListView;
-import android.widget.SimpleExpandableListAdapter;
-import android.widget.TextView;
-import butterknife.ButterKnife;
-import butterknife.InjectView;
-
-/**
- * For a given BLE device, this Activity provides the user interface to connect, display data,
- * and display GATT services and characteristics supported by the device. The Activity
- * communicates with {@code BluetoothLeService}, which in turn interacts with the
- * Bluetooth LE API.
- */
-public class DeviceControlActivity extends Activity {
- private final static String TAG = DeviceControlActivity.class.getSimpleName();
- public static final String EXTRA_DEVICE = "extra_device";
-
- private static final String LIST_NAME = "NAME";
- private static final String LIST_UUID = "UUID";
-
- private BluetoothGattCharacteristic mNotifyCharacteristic;
- private BluetoothLeService mBluetoothLeService;
- private List> mGattCharacteristics = new ArrayList>();
- private String mDeviceAddress;
- private String mDeviceName;
-
- @InjectView(R.id.gatt_services_list) ExpandableListView mGattServicesList;
- @InjectView(R.id.connection_state) TextView mConnectionState;
-
- @InjectView(R.id.uuid) TextView mGattUUID;
- @InjectView(R.id.description) TextView mGattUUIDDesc;
- @InjectView(R.id.data_as_string) TextView mDataAsString;
- @InjectView(R.id.data_as_array) TextView mDataAsArray;
-
- private boolean mConnected = false;
- private String mExportString;
- private BluetoothLeDevice mDevice;
-
- // Code to manage Service lifecycle.
- private final ServiceConnection mServiceConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName componentName, IBinder service) {
- mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
- if (!mBluetoothLeService.initialize()) {
- Log.e(TAG, "Unable to initialize Bluetooth");
- finish();
- }
- // Automatically connects to the device upon successful start-up initialization.
- mBluetoothLeService.connect(mDeviceAddress);
- }
-
- @Override
- public void onServiceDisconnected(ComponentName componentName) {
- mBluetoothLeService = null;
- }
- };
-
- // Handles various events fired by the Service.
- // ACTION_GATT_CONNECTED: connected to a GATT server.
- // ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
- // ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
- // ACTION_DATA_AVAILABLE: received data from the device.
- // this can be a result of read or notification operations.
- private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
- mConnected = true;
- updateConnectionState(R.string.connected);
- invalidateOptionsMenu();
- } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
- mConnected = false;
- updateConnectionState(R.string.disconnected);
- invalidateOptionsMenu();
- clearUI();
- } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
- // Show all the supported services and characteristics on the user interface.
- displayGattServices(mBluetoothLeService.getSupportedGattServices());
- } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
- final String noData = getString(R.string.no_data);
- final String uuid = intent.getStringExtra(BluetoothLeService.EXTRA_UUID_CHAR);
- final byte[] dataArr = intent.getByteArrayExtra(BluetoothLeService.EXTRA_DATA_RAW);
-
- mGattUUID.setText(tryString(uuid, noData));
- mGattUUIDDesc.setText(GattAttributeResolver.getAttributeName(uuid, getString(R.string.unknown)));
- mDataAsArray.setText(ByteUtils.byteArrayToHexString(dataArr));
- mDataAsString.setText(new String(dataArr));
- }
- }
- };
-
- // If a given GATT characteristic is selected, check for supported features. This sample
- // demonstrates 'Read' and 'Notify' features. See
- // http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
- // list of supported characteristic features.
- private final ExpandableListView.OnChildClickListener servicesListClickListner = new ExpandableListView.OnChildClickListener() {
- @Override
- public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
- if (mGattCharacteristics != null) {
- final BluetoothGattCharacteristic characteristic = mGattCharacteristics.get(groupPosition).get(childPosition);
- final int charaProp = characteristic.getProperties();
- if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
- // If there is an active notification on a characteristic, clear
- // it first so it doesn't update the data field on the user interface.
- if (mNotifyCharacteristic != null) {
- mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
- mNotifyCharacteristic = null;
- }
- mBluetoothLeService.readCharacteristic(characteristic);
- }
- if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
- mNotifyCharacteristic = characteristic;
- mBluetoothLeService.setCharacteristicNotification(characteristic, true);
- }
- return true;
- }
- return false;
- }
- };
-
- private void clearUI() {
- mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
- mGattUUID.setText(R.string.no_data);
- mGattUUIDDesc.setText(R.string.no_data);
- mDataAsArray.setText(R.string.no_data);
- mDataAsString.setText(R.string.no_data);
- }
-
- private void generateExportString(List gattServices){
- final String unknownServiceString = getResources().getString(R.string.unknown_service);
- final String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
- final StringBuilder exportBuilder = new StringBuilder();
-
- exportBuilder.append("Device Name: ");
- exportBuilder.append(mDeviceName);
- exportBuilder.append('\n');
- exportBuilder.append("Device Address: ");
- exportBuilder.append(mDeviceAddress);
- exportBuilder.append('\n');
- exportBuilder.append('\n');
-
- exportBuilder.append("Services:");
- exportBuilder.append("--------------------------");
- exportBuilder.append('\n');
-
- String uuid = null;
- for (BluetoothGattService gattService : gattServices) {
- uuid = gattService.getUuid().toString();
-
- exportBuilder.append(GattAttributeResolver.getAttributeName(uuid, unknownServiceString));
- exportBuilder.append(" (");
- exportBuilder.append(uuid);
- exportBuilder.append(')');
- exportBuilder.append('\n');
-
- final List gattCharacteristics = gattService.getCharacteristics();
- for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
- uuid = gattCharacteristic.getUuid().toString();
-
- exportBuilder.append('\t');
- exportBuilder.append(GattAttributeResolver.getAttributeName(uuid, unknownCharaString));
- exportBuilder.append(" (");
- exportBuilder.append(uuid);
- exportBuilder.append(')');
- exportBuilder.append('\n');
- }
-
- exportBuilder.append('\n');
- exportBuilder.append('\n');
- }
-
- exportBuilder.append("--------------------------");
- exportBuilder.append('\n');
-
- mExportString = exportBuilder.toString();
- }
-
- // Demonstrates how to iterate through the supported GATT Services/Characteristics.
- // In this sample, we populate the data structure that is bound to the ExpandableListView
- // on the UI.
- private void displayGattServices(List gattServices) {
- if (gattServices == null) return;
- generateExportString(gattServices);
-
- String uuid = null;
- final String unknownServiceString = getResources().getString(R.string.unknown_service);
- final String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
- final List> gattServiceData = new ArrayList>();
- final List>> gattCharacteristicData = new ArrayList>>();
- mGattCharacteristics = new ArrayList>();
-
- // Loops through available GATT Services.
- for (BluetoothGattService gattService : gattServices) {
- final Map currentServiceData = new HashMap();
- uuid = gattService.getUuid().toString();
- currentServiceData.put(LIST_NAME, GattAttributeResolver.getAttributeName(uuid, unknownServiceString));
- currentServiceData.put(LIST_UUID, uuid);
- gattServiceData.add(currentServiceData);
-
- final List> gattCharacteristicGroupData = new ArrayList>();
- final List gattCharacteristics = gattService.getCharacteristics();
- final List charas = new ArrayList();
-
- // Loops through available Characteristics.
- for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
- charas.add(gattCharacteristic);
- final Map currentCharaData = new HashMap();
- uuid = gattCharacteristic.getUuid().toString();
- currentCharaData.put(LIST_NAME, GattAttributeResolver.getAttributeName(uuid, unknownCharaString));
- currentCharaData.put(LIST_UUID, uuid);
- gattCharacteristicGroupData.add(currentCharaData);
- }
-
- mGattCharacteristics.add(charas);
- gattCharacteristicData.add(gattCharacteristicGroupData);
- }
-
- final SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
- this,
- gattServiceData,
- android.R.layout.simple_expandable_list_item_2,
- new String[] {LIST_NAME, LIST_UUID},
- new int[] { android.R.id.text1, android.R.id.text2 },
- gattCharacteristicData,
- android.R.layout.simple_expandable_list_item_2,
- new String[] {LIST_NAME, LIST_UUID},
- new int[] { android.R.id.text1, android.R.id.text2 }
- );
-
- mGattServicesList.setAdapter(gattServiceAdapter);
- invalidateOptionsMenu();
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_gatt_services);
-
- final Intent intent = getIntent();
- mDevice = intent.getParcelableExtra(EXTRA_DEVICE);
- mDeviceName = mDevice.getName();
- mDeviceAddress = mDevice.getAddress();
-
- ButterKnife.inject(this);
-
- // Sets up UI references.
- ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
- mGattServicesList.setOnChildClickListener(servicesListClickListner);
-
- getActionBar().setTitle(mDeviceName);
- getActionBar().setDisplayHomeAsUpEnabled(true);
-
- final Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
- bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.gatt_services, menu);
- if (mConnected) {
- menu.findItem(R.id.menu_connect).setVisible(false);
- menu.findItem(R.id.menu_disconnect).setVisible(true);
- } else {
- menu.findItem(R.id.menu_connect).setVisible(true);
- menu.findItem(R.id.menu_disconnect).setVisible(false);
- }
-
- if(mExportString == null){
- menu.findItem(R.id.menu_share).setVisible(false);
- } else {
- menu.findItem(R.id.menu_share).setVisible(true);
- }
-
- return true;
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unbindService(mServiceConnection);
- mBluetoothLeService = null;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch(item.getItemId()) {
- case R.id.menu_connect:
- mBluetoothLeService.connect(mDeviceAddress);
- return true;
- case R.id.menu_disconnect:
- mBluetoothLeService.disconnect();
- return true;
- case android.R.id.home:
- onBackPressed();
- return true;
- case R.id.menu_share:
- final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
- final String subject = getString(R.string.exporter_email_device_services_subject, mDeviceName, mDeviceAddress);
-
- intent.setType("text/plain");
- intent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
- intent.putExtra(android.content.Intent.EXTRA_TEXT, mExportString);
-
- startActivity(Intent.createChooser(
- intent,
- getString(R.string.exporter_email_device_list_picker_text)));
-
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- unregisterReceiver(mGattUpdateReceiver);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
- if (mBluetoothLeService != null) {
- final boolean result = mBluetoothLeService.connect(mDeviceAddress);
- Log.d(TAG, "Connect request result=" + result);
- }
- }
-
- private void updateConnectionState(final int resourceId) {
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- final int colourId;
-
- switch(resourceId){
- case R.string.connected:
- colourId = android.R.color.holo_green_dark;
- break;
- case R.string.disconnected:
- colourId = android.R.color.holo_red_dark;
- break;
- default:
- colourId = android.R.color.black;
- break;
- }
-
- mConnectionState.setText(resourceId);
- mConnectionState.setTextColor(getResources().getColor(colourId));
- }
- });
- }
-
- private static IntentFilter makeGattUpdateIntentFilter() {
- final IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
- intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
- intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
- intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
- return intentFilter;
- }
-
- private static String tryString(String string, String fallback){
- if(string == null){
- return fallback;
- } else{
- return string;
- }
- }
-}
\ No newline at end of file
diff --git a/sample_app/src/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java b/sample_app/src/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java
deleted file mode 100644
index 6f0870b..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/activities/DeviceDetailsActivity.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package uk.co.alt236.btlescan.activities;
-
-import java.util.Collection;
-import java.util.Locale;
-
-import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
-import uk.co.alt236.bluetoothlelib.device.adrecord.AdRecord;
-import uk.co.alt236.bluetoothlelib.device.mfdata.IBeaconManufacturerData;
-import uk.co.alt236.bluetoothlelib.resolvers.CompanyIdentifierResolver;
-import uk.co.alt236.bluetoothlelib.util.AdRecordUtils;
-import uk.co.alt236.bluetoothlelib.util.ByteUtils;
-import uk.co.alt236.bluetoothlelib.util.IBeaconUtils;
-import uk.co.alt236.btlescan.R;
-import uk.co.alt236.btlescan.util.TimeFormatter;
-import android.app.ListActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-import butterknife.ButterKnife;
-
-import com.commonsware.cwac.merge.MergeAdapter;
-
-public class DeviceDetailsActivity extends ListActivity{
- public static final String EXTRA_DEVICE = "extra_device";
-
- private BluetoothLeDevice mDevice;
-
- private void appendAdRecordView(MergeAdapter adapter, String title, AdRecord record){
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_adrecord, null);
- final TextView tvString = (TextView) lt.findViewById(R.id.data_as_string);
- final TextView tvArray = (TextView) lt.findViewById(R.id.data_as_array);
- final TextView tvTitle = (TextView) lt.findViewById(R.id.title);
-
- tvTitle.setText(title );
- tvString.setText("'" + AdRecordUtils.getRecordDataAsString(record) + "'");
- tvArray.setText("'" + ByteUtils.byteArrayToHexString(record.getData()) + "'");
-
- adapter.addView(lt);
- }
-
- private void appendDeviceInfo(MergeAdapter adapter, BluetoothLeDevice device){
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_device_info, null);
- final TextView tvName = (TextView) lt.findViewById(R.id.deviceName);
- final TextView tvAddress = (TextView) lt.findViewById(R.id.deviceAddress);
- final TextView tvClass = (TextView) lt.findViewById(R.id.deviceClass);
- final TextView tvBondingState = (TextView) lt.findViewById(R.id.deviceBondingState);
-
- tvName.setText(device.getName());
- tvAddress.setText(device.getAddress());
- tvClass.setText(device.getBluetoothDeviceClassName());
- tvBondingState.setText(device.getBluetoothDeviceBondState());
-
- adapter.addView(lt);
- }
-
- private void appendHeader(MergeAdapter adapter, String title){
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_header, null);
- final TextView tvTitle = (TextView) lt.findViewById(R.id.title);
- tvTitle.setText(title);
-
- adapter.addView(lt);
- }
-
- private void appendIBeaconInfo(MergeAdapter adapter, IBeaconManufacturerData iBeaconData){
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_ibeacon_details, null);
- final TextView tvCompanyId = (TextView) lt.findViewById(R.id.companyId);
- final TextView tvAdvert = (TextView) lt.findViewById(R.id.advertisement);
- final TextView tvUUID = (TextView) lt.findViewById(R.id.uuid);
- final TextView tvMajor = (TextView) lt.findViewById(R.id.major);
- final TextView tvMinor = (TextView) lt.findViewById(R.id.minor);
- final TextView tvTxPower = (TextView) lt.findViewById(R.id.txpower);
-
- tvCompanyId.setText(
- CompanyIdentifierResolver.getCompanyName(iBeaconData.getCompanyIdentifier(), getString(R.string.unknown))
- + " (" + hexEncode(iBeaconData.getCompanyIdentifier()) + ")");
- tvAdvert.setText(iBeaconData.getIBeaconAdvertisement() + " (" + hexEncode( iBeaconData.getIBeaconAdvertisement() ) + ")");
- tvUUID.setText(iBeaconData.getUUID().toString());
- tvMajor.setText(iBeaconData.getMajor() + " (" + hexEncode( iBeaconData.getMajor() ) + ")");
- tvMinor.setText(iBeaconData.getMinor() + " (" + hexEncode( iBeaconData.getMinor() ) + ")");
- tvTxPower.setText(iBeaconData.getCalibratedTxPower() + " (" + hexEncode( iBeaconData.getCalibratedTxPower() ) + ")");
-
- adapter.addView(lt);
- }
-
- private void appendRssiInfo(MergeAdapter adapter, BluetoothLeDevice device){
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_rssi_info, null);
- final TextView tvFirstTimestamp = (TextView) lt.findViewById(R.id.firstTimestamp);
- final TextView tvFirstRssi = (TextView) lt.findViewById(R.id.firstRssi);
- final TextView tvLastTimestamp = (TextView) lt.findViewById(R.id.lastTimestamp);
- final TextView tvLastRssi = (TextView) lt.findViewById(R.id.lastRssi);
- final TextView tvRunningAverageRssi = (TextView) lt.findViewById(R.id.runningAverageRssi);
-
- tvFirstTimestamp.setText(formatTime(device.getFirstTimestamp()));
- tvFirstRssi.setText(formatRssi(device.getFirstRssi()));
- tvLastTimestamp.setText(formatTime(device.getTimestamp()));
- tvLastRssi.setText(formatRssi(device.getRssi()));
- tvRunningAverageRssi.setText(formatRssi(device.getRunningAverageRssi()));
-
- adapter.addView(lt);
- }
-
- private void appendSimpleText(MergeAdapter adapter, byte data[]){
- appendSimpleText(adapter, ByteUtils.byteArrayToHexString(data));
- }
-
- private void appendSimpleText(MergeAdapter adapter, String data){
- final LinearLayout lt = (LinearLayout) getLayoutInflater().inflate(R.layout.list_item_view_textview, null);
- final TextView tvData = (TextView) lt.findViewById(R.id.data);
-
- tvData.setText(data);
-
- adapter.addView(lt);
- }
-
-
- private String formatRssi(double rssi){
- return getString(R.string.formatter_db, String.valueOf(rssi));
- }
-
- private String formatRssi(int rssi){
- return getString(R.string.formatter_db, String.valueOf(rssi));
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_details);
- ButterKnife.inject(this);
-
- mDevice = getIntent().getParcelableExtra(EXTRA_DEVICE);
-
- pupulateDetails(mDevice);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.details, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_connect:
-
- final Intent intent = new Intent(this, DeviceControlActivity.class);
- intent.putExtra(DeviceControlActivity.EXTRA_DEVICE, mDevice);
-
- startActivity(intent);
-
- break;
- }
- return true;
- }
-
- private void pupulateDetails(BluetoothLeDevice device) {
- final MergeAdapter adapter = new MergeAdapter();
-
- if(device == null){
- appendHeader(adapter, getString(R.string.header_device_info));
- appendSimpleText(adapter, getString(R.string.invalid_device_data));
- } else {
- appendHeader(adapter, getString(R.string.header_device_info));
- appendDeviceInfo(adapter, device);
-
- appendHeader(adapter, getString(R.string.header_rssi_info));
- appendRssiInfo(adapter, device);
-
- appendHeader(adapter, getString(R.string.header_scan_record));
- appendSimpleText(adapter, device.getScanRecord());
-
- final Collection adRecords = device.getAdRecordStore().getRecordsAsCollection();
- if(adRecords.size() > 0){
- appendHeader(adapter, getString(R.string.header_raw_ad_records));
-
- for(final AdRecord record : adRecords){
-
- appendAdRecordView(
- adapter,
- "#" + record.getType() + " " + record.getHumanReadableType(),
- record);
- }
- }
-
- final boolean isIBeacon = IBeaconUtils.isThisAnIBeacon(device);
- if(isIBeacon){
- final IBeaconManufacturerData iBeaconData = new IBeaconManufacturerData(device);
- appendHeader(adapter, getString(R.string.header_ibeacon_data));
- appendIBeaconInfo(adapter, iBeaconData);
- }
-
- }
- getListView().setAdapter(adapter);
- }
-
- private static String formatTime(long time){
- return TimeFormatter.getIsoDateTime(time);
- }
-
- private static String hexEncode(int integer){
- return "0x" + Integer.toHexString(integer).toUpperCase(Locale.US);
- }
-}
diff --git a/sample_app/src/uk/co/alt236/btlescan/activities/MainActivity.java b/sample_app/src/uk/co/alt236/btlescan/activities/MainActivity.java
deleted file mode 100644
index eb3a5cd..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/activities/MainActivity.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package uk.co.alt236.btlescan.activities;
-
-import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
-import uk.co.alt236.btlescan.R;
-import uk.co.alt236.btlescan.adapters.LeDeviceListAdapter;
-import uk.co.alt236.btlescan.containers.BluetoothLeDeviceStore;
-import uk.co.alt236.btlescan.util.BluetoothLeScanner;
-import uk.co.alt236.btlescan.util.BluetoothUtils;
-import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
-import android.app.AlertDialog;
-import android.app.ListActivity;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.Bundle;
-import android.text.SpannableString;
-import android.text.method.LinkMovementMethod;
-import android.text.util.Linkify;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ListView;
-import android.widget.TextView;
-import butterknife.ButterKnife;
-import butterknife.InjectView;
-
-public class MainActivity extends ListActivity {
- @InjectView(R.id.tvBluetoothLe) TextView mTvBluetoothLeStatus;
- @InjectView(R.id.tvBluetoothStatus) TextView mTvBluetoothStatus;
- @InjectView(R.id.tvItemCount) TextView mTvItemCount;
-
- private BluetoothUtils mBluetoothUtils;
- private BluetoothLeScanner mScanner;
- private LeDeviceListAdapter mLeDeviceListAdapter;
- private BluetoothLeDeviceStore mDeviceStore;
-
- 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());
- mDeviceStore.addDevice(deviceLe);
- final EasyObjectCursor c = mDeviceStore.getDeviceCursor();
-
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mLeDeviceListAdapter.swapCursor(c);
- updateItemCount(mLeDeviceListAdapter.getCount());
- }
- });
- }
- };
-
- private void updateItemCount(int count){
- mTvItemCount.setText(
- getString(
- R.string.formatter_item_count,
- String.valueOf(count)));
- }
-
- private void displayAboutDialog(){
- // REALLY REALLY LAZY LINKIFIED DIALOG
- final int paddingSizeDp = 5;
- final float scale = getResources().getDisplayMetrics().density;
- final int dpAsPixels = (int) (paddingSizeDp * scale + 0.5f);
-
- final TextView textView=new TextView(this);
- final SpannableString text = new SpannableString(getString(R.string.about_dialog_text));
-
- textView.setText(text);
- textView.setAutoLinkMask(RESULT_OK);
- textView.setMovementMethod(LinkMovementMethod.getInstance());
- textView.setPadding(dpAsPixels, dpAsPixels, dpAsPixels, dpAsPixels);
-
- Linkify.addLinks(text, Linkify.ALL);
- new AlertDialog.Builder(this)
- .setTitle(R.string.menu_about)
- .setCancelable(false)
- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {}
- })
- .setView(textView)
- .show();
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- ButterKnife.inject(this);
-
- mDeviceStore = new BluetoothLeDeviceStore();
- mBluetoothUtils = new BluetoothUtils(this);
- mScanner = new BluetoothLeScanner(mLeScanCallback, mBluetoothUtils);
- updateItemCount(0);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.main, menu);
- if (!mScanner.isScanning()) {
- menu.findItem(R.id.menu_stop).setVisible(false);
- menu.findItem(R.id.menu_scan).setVisible(true);
- menu.findItem(R.id.menu_refresh).setActionView(null);
- } else {
- menu.findItem(R.id.menu_stop).setVisible(true);
- menu.findItem(R.id.menu_scan).setVisible(false);
- menu.findItem(R.id.menu_refresh).setActionView(R.layout.actionbar_progress_indeterminate);
- }
-
- if(getListView().getCount() > 0){
- menu.findItem(R.id.menu_share).setVisible(true);
- } else {
- menu.findItem(R.id.menu_share).setVisible(false);
- }
-
- return true;
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- final BluetoothLeDevice device = (BluetoothLeDevice) mLeDeviceListAdapter.getItem(position);
- if (device == null) return;
-
-
- final Intent intent = new Intent(this, DeviceDetailsActivity.class);
- intent.putExtra(DeviceDetailsActivity.EXTRA_DEVICE, device);
-
- startActivity(intent);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_scan:
- startScan();
- break;
- case R.id.menu_stop:
- mScanner.scanLeDevice(-1, false);
- invalidateOptionsMenu();
- break;
- case R.id.menu_about:
- displayAboutDialog();
- break;
- case R.id.menu_share:
- mDeviceStore.shareDataAsEmail(this);
- }
- return true;
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- mScanner.scanLeDevice(-1, false);
- }
-
- @Override
- public void onResume(){
- super.onResume();
- final boolean mIsBluetoothOn = mBluetoothUtils.isBluetoothOn();
- final boolean mIsBluetoothLePresent = mBluetoothUtils.isBluetoothLeSupported();
-
- if(mIsBluetoothOn){
- mTvBluetoothStatus.setText(R.string.on);
- } else {
- mTvBluetoothStatus.setText(R.string.off);
- }
-
- if(mIsBluetoothLePresent){
- mTvBluetoothLeStatus.setText(R.string.supported);
- } else {
- mTvBluetoothLeStatus.setText(R.string.not_supported);
- }
-
- invalidateOptionsMenu();
- }
-
- private void startScan(){
- final boolean mIsBluetoothOn = mBluetoothUtils.isBluetoothOn();
- final boolean mIsBluetoothLePresent = mBluetoothUtils.isBluetoothLeSupported();
- mDeviceStore.clear();
- updateItemCount(0);
-
- mLeDeviceListAdapter = new LeDeviceListAdapter(this, mDeviceStore.getDeviceCursor());
- setListAdapter(mLeDeviceListAdapter);
-
- mBluetoothUtils.askUserToEnableBluetoothIfNeeded();
- if(mIsBluetoothOn && mIsBluetoothLePresent){
- mScanner.scanLeDevice(-1, true);
- invalidateOptionsMenu();
- }
- }
-
-}
diff --git a/sample_app/src/uk/co/alt236/btlescan/adapters/LeDeviceListAdapter.java b/sample_app/src/uk/co/alt236/btlescan/adapters/LeDeviceListAdapter.java
deleted file mode 100644
index 38d3892..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/adapters/LeDeviceListAdapter.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package uk.co.alt236.btlescan.adapters;
-
-import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
-import uk.co.alt236.bluetoothlelib.device.IBeaconDevice;
-import uk.co.alt236.bluetoothlelib.util.IBeaconUtils;
-import uk.co.alt236.btlescan.R;
-import uk.co.alt236.btlescan.util.Constants;
-import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
-import android.app.Activity;
-import android.support.v4.widget.SimpleCursorAdapter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-// Adapter for holding devices found through scanning.
-public class LeDeviceListAdapter extends SimpleCursorAdapter {
- private final LayoutInflater mInflator;
- private final Activity mActivity;
-
- public LeDeviceListAdapter(Activity activity, EasyObjectCursor cursor) {
- super(activity, R.layout.list_item_device, cursor, new String[0], new int[0], 0);
- mInflator = activity.getLayoutInflater();
- mActivity = activity;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public EasyObjectCursor getCursor(){
- return ((EasyObjectCursor) super.getCursor());
- }
-
- @Override
- public BluetoothLeDevice getItem(int i){
- return getCursor().getItem(i);
- }
-
- @Override
- public long getItemId(int i) {
- return i;
- }
-
- @Override
- public View getView(int i, View view, ViewGroup viewGroup) {
- ViewHolder viewHolder;
- // General ListView optimization code.
- if (view == null) {
- view = mInflator.inflate(R.layout.list_item_device, null);
- viewHolder = new ViewHolder();
- viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
- viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
- viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi);
- viewHolder.deviceIcon = (ImageView) view.findViewById(R.id.device_icon);
- viewHolder.deviceLastUpdated = (TextView) view.findViewById(R.id.device_last_update);
- viewHolder.ibeaconMajor = (TextView) view.findViewById(R.id.ibeacon_major);
- viewHolder.ibeaconMinor = (TextView) view.findViewById(R.id.ibeacon_minor);
- viewHolder.ibeaconDistance = (TextView) view.findViewById(R.id.ibeacon_distance);
- viewHolder.ibeaconUUID = (TextView) view.findViewById(R.id.ibeacon_uuid);
- viewHolder.ibeaconTxPower = (TextView) view.findViewById(R.id.ibeacon_tx_power);
- viewHolder.ibeaconSection = (View) view.findViewById(R.id.ibeacon_section);
- viewHolder.ibeaconDistanceDescriptor = (TextView) view.findViewById(R.id.ibeacon_distance_descriptor);
- view.setTag(viewHolder);
- } else {
- viewHolder = (ViewHolder) view.getTag();
- }
-
- final BluetoothLeDevice device = getCursor().getItem(i);
- final String deviceName = device.getName();
- final double rssi = device.getRssi();
-
- if (deviceName != null && deviceName.length() > 0){
- viewHolder.deviceName.setText(deviceName);
- } else{
- viewHolder.deviceName.setText(R.string.unknown_device);
- }
-
- if (IBeaconUtils.isThisAnIBeacon(device)){
- final IBeaconDevice iBeacon = new IBeaconDevice(device);
- final String accuracy = Constants.DOUBLE_TWO_DIGIT_ACCURACY.format(iBeacon.getAccuracy());
-
- viewHolder.deviceIcon.setImageResource(R.drawable.ic_device_ibeacon);
- viewHolder.ibeaconSection.setVisibility(View.VISIBLE);
- viewHolder.ibeaconMajor.setText(String.valueOf(iBeacon.getMajor()));
- viewHolder.ibeaconMinor.setText(String.valueOf(iBeacon.getMinor()));
- viewHolder.ibeaconTxPower.setText(String.valueOf(iBeacon.getCalibratedTxPower()));
- viewHolder.ibeaconUUID.setText(iBeacon.getUUID());
- viewHolder.ibeaconDistance.setText(
- mActivity.getString(R.string.formatter_meters, accuracy));
- viewHolder.ibeaconDistanceDescriptor.setText(iBeacon.getDistanceDescriptor().toString());
- } else {
- viewHolder.deviceIcon.setImageResource(R.drawable.ic_bluetooth);
- viewHolder.ibeaconSection.setVisibility(View.GONE);
- }
-
- final String rssiString =
- mActivity.getString(R.string.formatter_db, String.valueOf(rssi));
- final String runningAverageRssiString =
- mActivity.getString(R.string.formatter_db, String.valueOf(device.getRunningAverageRssi()));
-
- viewHolder.deviceLastUpdated.setText(
- android.text.format.DateFormat.format(
- Constants.TIME_FORMAT, new java.util.Date(device.getTimestamp())));
- viewHolder.deviceAddress.setText(device.getAddress());
- viewHolder.deviceRssi.setText(rssiString + " / " + runningAverageRssiString);
- return view;
- }
-
- static class ViewHolder {
- TextView deviceName;
- TextView deviceAddress;
- TextView deviceRssi;
- TextView ibeaconUUID;
- TextView ibeaconMajor;
- TextView ibeaconMinor;
- TextView ibeaconTxPower;
- TextView ibeaconDistance;
- TextView ibeaconDistanceDescriptor;
- TextView deviceLastUpdated;
- View ibeaconSection;
- ImageView deviceIcon;
- }
-
-}
\ No newline at end of file
diff --git a/sample_app/src/uk/co/alt236/btlescan/containers/BluetoothLeDeviceStore.java b/sample_app/src/uk/co/alt236/btlescan/containers/BluetoothLeDeviceStore.java
deleted file mode 100644
index 147ca27..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/containers/BluetoothLeDeviceStore.java
+++ /dev/null
@@ -1,182 +0,0 @@
-package uk.co.alt236.btlescan.containers;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
-import uk.co.alt236.bluetoothlelib.device.IBeaconDevice;
-import uk.co.alt236.bluetoothlelib.util.ByteUtils;
-import uk.co.alt236.bluetoothlelib.util.IBeaconUtils;
-import uk.co.alt236.btlescan.R;
-import uk.co.alt236.btlescan.util.CsvWriterHelper;
-import uk.co.alt236.btlescan.util.TimeFormatter;
-import uk.co.alt236.easycursor.objectcursor.EasyObjectCursor;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-
-public class BluetoothLeDeviceStore {
- private final Map mDeviceMap;
-
-
- public BluetoothLeDeviceStore(){
- mDeviceMap = new HashMap();
- }
-
- public void addDevice(BluetoothLeDevice device){
- if(mDeviceMap.containsKey(device.getAddress())){
- mDeviceMap.get(device.getAddress()).updateRssiReading(device.getTimestamp(), device.getRssi());
- } else {
- mDeviceMap.put(device.getAddress(), device);
- }
- }
-
- public void clear(){
- mDeviceMap.clear();
- }
-
-
- private FileWriter generateFile(File file, String contents){
- FileWriter writer = null;
- try {
- writer = new FileWriter(file);
- writer.append(contents);
- writer.flush();
-
- } catch (IOException e) {
- e.printStackTrace();
- }finally{
- try {
- writer.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return writer;
- }
-
- public EasyObjectCursor getDeviceCursor(){
- return new EasyObjectCursor(
- BluetoothLeDevice.class,
- getDeviceList(),
- "address");
- }
-
- public List getDeviceList(){
- final List methodResult = new ArrayList(mDeviceMap.values());
-
- Collections.sort(methodResult, new Comparator() {
-
- @Override
- public int compare(BluetoothLeDevice arg0, BluetoothLeDevice arg1) {
- return arg0.getAddress().compareToIgnoreCase(arg1.getAddress());
- }
- });
-
- return methodResult;
- }
-
-
- private String getListAsCsv(){
- final List list = getDeviceList();
- final StringBuilder sb = new StringBuilder();
- sb.append(CsvWriterHelper.addStuff("mac"));
- sb.append(CsvWriterHelper.addStuff("name"));
- sb.append(CsvWriterHelper.addStuff("firstTimestamp"));
- sb.append(CsvWriterHelper.addStuff("firstRssi"));
- sb.append(CsvWriterHelper.addStuff("currentTimestamp"));
- sb.append(CsvWriterHelper.addStuff("currentRssi"));
- sb.append(CsvWriterHelper.addStuff("adRecord"));
- sb.append(CsvWriterHelper.addStuff("iBeacon"));
- sb.append(CsvWriterHelper.addStuff("uuid"));
- sb.append(CsvWriterHelper.addStuff("major"));
- sb.append(CsvWriterHelper.addStuff("minor"));
- sb.append(CsvWriterHelper.addStuff("txPower"));
- sb.append(CsvWriterHelper.addStuff("distance"));
- sb.append(CsvWriterHelper.addStuff("accuracy"));
- sb.append('\n');
-
- for(BluetoothLeDevice device : list){
- sb.append(CsvWriterHelper.addStuff(device.getAddress()));
- sb.append(CsvWriterHelper.addStuff(device.getName()));
- sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getFirstTimestamp())));
- sb.append(CsvWriterHelper.addStuff(device.getFirstRssi()));
- sb.append(CsvWriterHelper.addStuff(TimeFormatter.getIsoDateTime(device.getTimestamp())));
- sb.append(CsvWriterHelper.addStuff(device.getRssi()));
- sb.append(CsvWriterHelper.addStuff(ByteUtils.byteArrayToHexString(device.getScanRecord())));
- final boolean isIBeacon = IBeaconUtils.isThisAnIBeacon(device);
- final String uuid;
- final String minor;
- final String major;
- final String txPower;
- final String distance;
- final String accuracy;
-
- if(isIBeacon){
- final IBeaconDevice beacon = new IBeaconDevice(device);
- uuid = String.valueOf(beacon.getUUID());
- minor = String.valueOf(beacon.getMinor());
- major = String.valueOf(beacon.getMajor());
- txPower = String.valueOf(beacon.getCalibratedTxPower());
- distance = beacon.getDistanceDescriptor().toString().toLowerCase(Locale.US);
- accuracy = String.valueOf(beacon.getAccuracy());
- } else {
- uuid = "";
- minor = "";
- major = "";
- txPower = "";
- distance = "";
- accuracy = "";
- }
-
- sb.append(CsvWriterHelper.addStuff(isIBeacon));
- sb.append(CsvWriterHelper.addStuff(uuid));
- sb.append(CsvWriterHelper.addStuff(minor));
- sb.append(CsvWriterHelper.addStuff(major));
- sb.append(CsvWriterHelper.addStuff(txPower));
- sb.append(CsvWriterHelper.addStuff(distance));
- sb.append(CsvWriterHelper.addStuff(accuracy));
-
- sb.append('\n');
- }
-
- return sb.toString();
- }
-
-
- public void shareDataAsEmail(Context context){
- final long timeInMillis = System.currentTimeMillis();
-
- final String to = null;
- final String subject = context.getString(
- R.string.exporter_email_device_list_subject,
- TimeFormatter.getIsoDateTime(timeInMillis));
-
- final String message = context.getString(R.string.exporter_email_device_list_body);
-
- final Intent i = new Intent(Intent.ACTION_SEND);
- i.setType("plain/text");
- try {
- final File outputDir = context.getCacheDir();
- final File outputFile = File.createTempFile("bluetooth_le_" + timeInMillis, ".csv", outputDir);
- outputFile.setReadable(true, false);
- generateFile(outputFile, getListAsCsv());
- i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(outputFile));
- i.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
- i.putExtra(Intent.EXTRA_SUBJECT, subject);
- i.putExtra(Intent.EXTRA_TEXT, message);
- context.startActivity(Intent.createChooser(i, context.getString(R.string.exporter_email_device_list_picker_text)));
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-}
diff --git a/sample_app/src/uk/co/alt236/btlescan/services/BluetoothLeService.java b/sample_app/src/uk/co/alt236/btlescan/services/BluetoothLeService.java
deleted file mode 100644
index 03f7539..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/services/BluetoothLeService.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package uk.co.alt236.btlescan.services;
-
-import java.util.List;
-
-import android.app.Service;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCallback;
-import android.bluetooth.BluetoothGattCharacteristic;
-import android.bluetooth.BluetoothGattService;
-import android.bluetooth.BluetoothManager;
-import android.bluetooth.BluetoothProfile;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-import android.util.Log;
-
-/**
- * Service for managing connection and data communication with a GATT server hosted on a
- * given Bluetooth LE device.
- */
-public class BluetoothLeService extends Service {
- private final static String TAG = BluetoothLeService.class.getSimpleName();
-
- private BluetoothManager mBluetoothManager;
- private BluetoothAdapter mBluetoothAdapter;
- private String mBluetoothDeviceAddress;
- private BluetoothGatt mBluetoothGatt;
- private int mConnectionState = STATE_DISCONNECTED;
-
- private static final int STATE_DISCONNECTED = 0;
- private static final int STATE_CONNECTING = 1;
- private static final int STATE_CONNECTED = 2;
-
- public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
- public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
- public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
- public final static String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
- public final static String EXTRA_DATA_RAW = "com.example.bluetooth.le.EXTRA_DATA_RAW";
- public final static String EXTRA_UUID_CHAR = "com.example.bluetooth.le.EXTRA_UUID_CHAR";
-
- // Implements callback methods for GATT events that the app cares about. For example,
- // connection change and services discovered.
- private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
- @Override
- public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
- String intentAction;
- if (newState == BluetoothProfile.STATE_CONNECTED) {
- intentAction = ACTION_GATT_CONNECTED;
- mConnectionState = STATE_CONNECTED;
- broadcastUpdate(intentAction);
- Log.i(TAG, "Connected to GATT server.");
- // Attempts to discover services after successful connection.
- Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
-
- } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
- intentAction = ACTION_GATT_DISCONNECTED;
- mConnectionState = STATE_DISCONNECTED;
- Log.i(TAG, "Disconnected from GATT server.");
- broadcastUpdate(intentAction);
- }
- }
-
- @Override
- public void onServicesDiscovered(BluetoothGatt gatt, int status) {
- if (status == BluetoothGatt.GATT_SUCCESS) {
- broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
- } else {
- Log.w(TAG, "onServicesDiscovered received: " + status);
- }
- }
-
- @Override
- public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
- if (status == BluetoothGatt.GATT_SUCCESS) {
- broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
- }
- }
-
- @Override
- public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
- }
- };
-
- private void broadcastUpdate(final String action) {
- final Intent intent = new Intent(action);
- sendBroadcast(intent);
- }
-
- private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
- final Intent intent = new Intent(action);
- intent.putExtra(EXTRA_UUID_CHAR, characteristic.getUuid().toString());
-
- // Always try to add the RAW value
- final byte[] data = characteristic.getValue();
- if (data != null && data.length > 0) {
- intent.putExtra(EXTRA_DATA_RAW, data);
- }
-
- sendBroadcast(intent);
- }
-
- public class LocalBinder extends Binder {
- public BluetoothLeService getService() {
- return BluetoothLeService.this;
- }
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- @Override
- public boolean onUnbind(Intent intent) {
- // After using a given device, you should make sure that BluetoothGatt.close() is called
- // such that resources are cleaned up properly. In this particular example, close() is
- // invoked when the UI is disconnected from the Service.
- close();
- return super.onUnbind(intent);
- }
-
- private final IBinder mBinder = new LocalBinder();
-
- /**
- * Initializes a reference to the local Bluetooth adapter.
- *
- * @return Return true if the initialization is successful.
- */
- public boolean initialize() {
- // For API level 18 and above, get a reference to BluetoothAdapter through
- // BluetoothManager.
- if (mBluetoothManager == null) {
- mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
- if (mBluetoothManager == null) {
- Log.e(TAG, "Unable to initialize BluetoothManager.");
- return false;
- }
- }
-
- mBluetoothAdapter = mBluetoothManager.getAdapter();
- if (mBluetoothAdapter == null) {
- Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
- return false;
- }
-
- return true;
- }
-
- /**
- * Connects to the GATT server hosted on the Bluetooth LE device.
- *
- * @param address The device address of the destination device.
- *
- * @return Return true if the connection is initiated successfully. The connection result
- * is reported asynchronously through the
- * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
- * callback.
- */
- public boolean connect(final String address) {
- if (mBluetoothAdapter == null || address == null) {
- Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
- return false;
- }
-
- // Previously connected device. Try to reconnect.
- if (mBluetoothDeviceAddress != null
- && address.equals(mBluetoothDeviceAddress)
- && mBluetoothGatt != null) {
-
- Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
- if (mBluetoothGatt.connect()) {
- mConnectionState = STATE_CONNECTING;
- return true;
- } else {
- return false;
- }
- }
-
- final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
- if (device == null) {
- Log.w(TAG, "Device not found. Unable to connect.");
- return false;
- }
- // We want to directly connect to the device, so we are setting the autoConnect
- // parameter to false.
- mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
- Log.d(TAG, "Trying to create a new connection.");
- mBluetoothDeviceAddress = address;
- mConnectionState = STATE_CONNECTING;
- return true;
- }
-
- /**
- * Disconnects an existing connection or cancel a pending connection. The disconnection result
- * is reported asynchronously through the
- * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
- * callback.
- */
- public void disconnect() {
- if (mBluetoothAdapter == null || mBluetoothGatt == null) {
- Log.w(TAG, "BluetoothAdapter not initialized");
- return;
- }
- mBluetoothGatt.disconnect();
- }
-
- /**
- * After using a given BLE device, the app must call this method to ensure resources are
- * released properly.
- */
- public void close() {
- if (mBluetoothGatt == null) {
- return;
- }
- mBluetoothGatt.close();
- mBluetoothGatt = null;
- }
-
- /**
- * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
- * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
- * callback.
- *
- * @param characteristic The characteristic to read from.
- */
- public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
- if (mBluetoothAdapter == null || mBluetoothGatt == null) {
- Log.w(TAG, "BluetoothAdapter not initialized");
- return;
- }
- mBluetoothGatt.readCharacteristic(characteristic);
- }
-
- /**
- * Enables or disables notification on a give characteristic.
- *
- * @param characteristic Characteristic to act on.
- * @param enabled If true, enable notification. False otherwise.
- */
- public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
- if (mBluetoothAdapter == null || mBluetoothGatt == null) {
- Log.w(TAG, "BluetoothAdapter not initialized");
- return;
- }
- mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
- }
-
- /**
- * Retrieves a list of supported GATT services on the connected device. This should be
- * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
- *
- * @return A {@code List} of supported services.
- */
- public List getSupportedGattServices() {
- if (mBluetoothGatt == null) return null;
-
- return mBluetoothGatt.getServices();
- }
-}
\ No newline at end of file
diff --git a/sample_app/src/uk/co/alt236/btlescan/util/BluetoothLeScanner.java b/sample_app/src/uk/co/alt236/btlescan/util/BluetoothLeScanner.java
deleted file mode 100644
index 38d1f79..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/util/BluetoothLeScanner.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package uk.co.alt236.btlescan.util;
-
-import android.bluetooth.BluetoothAdapter;
-import android.os.Handler;
-import android.util.Log;
-
-public class BluetoothLeScanner {
- private final Handler mHandler;
- private final BluetoothAdapter.LeScanCallback mLeScanCallback;
- private final BluetoothUtils mBluetoothUtils;
- private boolean mScanning;
-
- public BluetoothLeScanner(BluetoothAdapter.LeScanCallback leScanCallback, BluetoothUtils bluetoothUtils){
- mHandler = new Handler();
- mLeScanCallback = leScanCallback;
- mBluetoothUtils = bluetoothUtils;
- }
-
- public boolean isScanning() {
- return mScanning;
- }
-
- public void scanLeDevice(final int duration, final boolean enable) {
- if (enable) {
- if(mScanning){return;}
- Log.d("TAG", "~ Starting Scan");
- // Stops scanning after a pre-defined scan period.
- if(duration > 0){
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- Log.d("TAG", "~ Stopping Scan (timeout)");
- mScanning = false;
- mBluetoothUtils.getBluetoothAdapter().stopLeScan(mLeScanCallback);
- }
- }, duration);
- }
- mScanning = true;
- mBluetoothUtils.getBluetoothAdapter().startLeScan(mLeScanCallback);
- } else {
- Log.d("TAG", "~ Stopping Scan");
- mScanning = false;
- mBluetoothUtils.getBluetoothAdapter().stopLeScan(mLeScanCallback);
- }
- }
-}
diff --git a/sample_app/src/uk/co/alt236/btlescan/util/BluetoothUtils.java b/sample_app/src/uk/co/alt236/btlescan/util/BluetoothUtils.java
deleted file mode 100644
index 3bf7dd6..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/util/BluetoothUtils.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package uk.co.alt236.btlescan.util;
-
-import android.app.Activity;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-
-public final class BluetoothUtils {
- private final Activity mActivity;
- private final BluetoothAdapter mBluetoothAdapter;
- private final BluetoothManager mBluetoothManager;
-
- public final static int REQUEST_ENABLE_BT = 2001;
-
- public BluetoothUtils(Activity activity){
- mActivity = activity;
- mBluetoothManager = (BluetoothManager) mActivity.getSystemService(Context.BLUETOOTH_SERVICE);
- mBluetoothAdapter = mBluetoothManager.getAdapter();
- }
-
- public void askUserToEnableBluetoothIfNeeded(){
- if (isBluetoothLeSupported() && (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled())) {
- final Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- mActivity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
- }
- }
-
- public BluetoothAdapter getBluetoothAdapter(){
- return mBluetoothAdapter;
- }
-
- public boolean isBluetoothLeSupported(){
- return mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
- }
-
- public boolean isBluetoothOn(){
- if (mBluetoothAdapter == null) {
- return false;
- } else {
- return mBluetoothAdapter.isEnabled();
- }
- }
-}
diff --git a/sample_app/src/uk/co/alt236/btlescan/util/Constants.java b/sample_app/src/uk/co/alt236/btlescan/util/Constants.java
deleted file mode 100644
index 87376a8..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/util/Constants.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package uk.co.alt236.btlescan.util;
-
-import java.text.DecimalFormat;
-
-public class Constants {
- public static final DecimalFormat DOUBLE_TWO_DIGIT_ACCURACY = new DecimalFormat("#.##");
- public static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
-}
diff --git a/sample_app/src/uk/co/alt236/btlescan/util/CsvWriterHelper.java b/sample_app/src/uk/co/alt236/btlescan/util/CsvWriterHelper.java
deleted file mode 100644
index b827126..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/util/CsvWriterHelper.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package uk.co.alt236.btlescan.util;
-
-public class CsvWriterHelper {
- private static final String QUOTE = "\"";
- public static String addStuff(Integer text){
- return QUOTE + text + QUOTE + ",";
- }
-
- public static String addStuff(Long text){
- return QUOTE + text + QUOTE + ",";
- }
-
- public static String addStuff(boolean value){
- return QUOTE + value + QUOTE + ",";
- }
-
- public static String addStuff(String text){
- if(text == null){text = "";}
- text = text.replace(QUOTE, "'");
-
- return QUOTE + text.trim() + QUOTE + ",";
- }
-}
diff --git a/sample_app/src/uk/co/alt236/btlescan/util/TimeFormatter.java b/sample_app/src/uk/co/alt236/btlescan/util/TimeFormatter.java
deleted file mode 100644
index 8c7f925..0000000
--- a/sample_app/src/uk/co/alt236/btlescan/util/TimeFormatter.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package uk.co.alt236.btlescan.util;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-public class TimeFormatter {
- private final static String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS zzz";
- private final static SimpleDateFormat ISO_FORMATTER = new UtcDateFormatter(ISO_FORMAT, Locale.US);
-
- public static String getIsoDateTime(Date date){
- return ISO_FORMATTER.format(date);
- }
-
- public static String getIsoDateTime(long millis){
- return getIsoDateTime(new Date(millis));
- }
-}
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..ca218b5
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+include ':library'
+include ':sample_app'