[
  {
    "path": ".gitignore",
    "content": "# Built application files\n*.apk\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\n\n# Gradle files\n.gradle/\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n"
  },
  {
    "path": "BleLibrary/.classpath",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<classpath>\n\t<classpathentry kind=\"src\" path=\"src\"/>\n\t<classpathentry kind=\"src\" path=\"gen\"/>\n\t<classpathentry kind=\"con\" path=\"com.android.ide.eclipse.adt.ANDROID_FRAMEWORK\"/>\n\t<classpathentry exported=\"true\" kind=\"con\" path=\"com.android.ide.eclipse.adt.LIBRARIES\"/>\n\t<classpathentry exported=\"true\" kind=\"con\" path=\"com.android.ide.eclipse.adt.DEPENDENCIES\"/>\n\t<classpathentry kind=\"output\" path=\"bin/classes\"/>\n</classpath>\n"
  },
  {
    "path": "BleLibrary/.project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>BleLibrary</name>\n\t<comment></comment>\n\t<projects>\n\t</projects>\n\t<buildSpec>\n\t\t<buildCommand>\n\t\t\t<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t\t<buildCommand>\n\t\t\t<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t\t<buildCommand>\n\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t\t<buildCommand>\n\t\t\t<name>com.android.ide.eclipse.adt.ApkBuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t</buildSpec>\n\t<natures>\n\t\t<nature>com.android.ide.eclipse.adt.AndroidNature</nature>\n\t\t<nature>org.eclipse.jdt.core.javanature</nature>\n\t</natures>\n</projectDescription>\n"
  },
  {
    "path": "BleLibrary/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.xtremeprog.sdk.ble\"\n    android:versionCode=\"1\"\n    android:versionName=\"1.0\" >\n\n    <uses-sdk\n        android:minSdkVersion=\"17\"\n        android:targetSdkVersion=\"18\" />\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@drawable/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\" >\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "BleLibrary/proguard-project.txt",
    "content": "# To enable ProGuard in your project, edit project.properties\n# to define the proguard.config property as described in that file.\n#\n# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in ${sdk.dir}/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the ProGuard\n# include property in project.properties.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "BleLibrary/proguard.pro",
    "content": "-injars bin/blelibrary.jar\n-outjars bin/blelibrary-0.1.jar\n\n-libraryjars /Users/teamx/bin/adt-bundle-mac-x86_64-20130917/sdk/platforms/android-18/android.jar\n-libraryjars libs/com.broadcom.bt.jar\n-libraryjars libs/commons-codec-1.8.jar\n-libraryjars libs/samsung_ble_sdk_200.jar\n\n-target 1.6\n-useuniqueclassmembernames\n-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod\n-renamesourcefileattribute SourceFile\n-adaptresourcefilenames **.properties\n-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF\n-verbose\n\n\n# Keep - Library. Keep all public and protected classes, fields, and methods.\n-keep public class * {\n    public protected <fields>;\n    public protected <methods>;\n}\n\n# Also keep - Enumerations. Keep the special static methods that are required in\n# enumeration classes.\n-keepclassmembers enum  * {\n    public static **[] values();\n    public static ** valueOf(java.lang.String);\n}\n\n# Keep names - Native method names. Keep all native class/method names.\n-keepclasseswithmembers,allowshrinking class * {\n    native <methods>;\n}\n"
  },
  {
    "path": "BleLibrary/project.properties",
    "content": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# This file must be checked in Version Control Systems.\n#\n# To customize properties used by the Ant build system edit\n# \"ant.properties\", and override values to adapt the script to your\n# project structure.\n#\n# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):\n#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt\n\n# Project target.\ntarget=android-19\nandroid.library=true\n"
  },
  {
    "path": "BleLibrary/res/values/strings.xml",
    "content": "<resources>\n\n    <string name=\"app_name\">BleLibrary</string>\n\n</resources>\n"
  },
  {
    "path": "BleLibrary/res/values/styles.xml",
    "content": "<resources>\n\n    <!--\n        Base application theme, dependent on API level. This theme is replaced\n        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.\n    -->\n    <style name=\"AppBaseTheme\" parent=\"android:Theme.Light\">\n        <!--\n            Theme customizations available in newer API levels can go in\n            res/values-vXX/styles.xml, while customizations related to\n            backward-compatibility can go here.\n        -->\n    </style>\n\n    <!-- Application theme. -->\n    <style name=\"AppTheme\" parent=\"AppBaseTheme\">\n        <!-- All customizations that are NOT specific to a particular API-level can go here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "BleLibrary/res/values-v11/styles.xml",
    "content": "<resources>\n\n    <!--\n        Base application theme for API 11+. This theme completely replaces\n        AppBaseTheme from res/values/styles.xml on API 11+ devices.\n    -->\n    <style name=\"AppBaseTheme\" parent=\"android:Theme.Holo.Light\">\n        <!-- API 11 theme customizations can go here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "BleLibrary/res/values-v14/styles.xml",
    "content": "<resources>\n\n    <!--\n        Base application theme for API 14+. This theme completely replaces\n        AppBaseTheme from BOTH res/values/styles.xml and\n        res/values-v11/styles.xml on API 14+ devices.\n    -->\n    <style name=\"AppBaseTheme\" parent=\"android:Theme.Holo.Light.DarkActionBar\">\n        <!-- API 14 theme customizations can go here. -->\n    </style>\n\n</resources>\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/AndroidBle.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.UUID;\n\nimport org.apache.commons.codec.binary.Hex;\n\nimport android.annotation.SuppressLint;\nimport android.bluetooth.BluetoothAdapter;\nimport android.bluetooth.BluetoothDevice;\nimport android.bluetooth.BluetoothGatt;\nimport android.bluetooth.BluetoothGattCallback;\nimport android.bluetooth.BluetoothGattCharacteristic;\nimport android.bluetooth.BluetoothGattDescriptor;\nimport android.bluetooth.BluetoothGattService;\nimport android.bluetooth.BluetoothManager;\nimport android.bluetooth.BluetoothProfile;\nimport android.content.Context;\nimport android.content.pm.PackageManager;\nimport android.util.Log;\n\nimport com.xtremeprog.sdk.ble.BleRequest.RequestType;\n\n@SuppressLint(\"NewApi\")\npublic class AndroidBle implements IBle, IBleRequestHandler {\n\n\tprotected static final String TAG = \"blelib\";\n\n\tprivate BleService mService;\n\tprivate BluetoothAdapter mBtAdapter;\n\tprivate Map<String, BluetoothGatt> mBluetoothGatts;\n\t// private BTQuery btQuery;\n\n\tprivate BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {\n\t\t@Override\n\t\tpublic void onLeScan(final BluetoothDevice device, int rssi,\n\t\t\t\tbyte[] scanRecord) {\n\t\t\tmService.bleDeviceFound(device, rssi, scanRecord,\n\t\t\t\t\tBleService.DEVICE_SOURCE_SCAN);\n\t\t}\n\t};\n\n\tprivate BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {\n\t\t@Override\n\t\tpublic void onConnectionStateChange(BluetoothGatt gatt, int status,\n\t\t\t\tint newState) {\n\t\t\tString address = gatt.getDevice().getAddress();\n\t\t\tLog.d(TAG, \"onConnectionStateChange \" + address + \" status \"\n\t\t\t\t\t+ status + \" newState \" + newState);\n\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tdisconnect(address);\n\t\t\t\tmService.bleGattDisConnected(address);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (newState == BluetoothProfile.STATE_CONNECTED) {\n\t\t\t\tmService.bleGattConnected(gatt.getDevice());\n\t\t\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\t\t\tRequestType.DISCOVER_SERVICE, address));\n\t\t\t} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {\n\t\t\t\tmService.bleGattDisConnected(address);\n\t\t\t\tdisconnect(address);\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void onServicesDiscovered(BluetoothGatt gatt, int status) {\n\t\t\tString address = gatt.getDevice().getAddress();\n\t\t\tLog.d(TAG, \"onServicesDiscovered \" + address + \" status \" + status);\n\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tmService.requestProcessed(address,\n\t\t\t\t\t\tRequestType.DISCOVER_SERVICE, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmService.bleServiceDiscovered(gatt.getDevice().getAddress());\n\t\t}\n\n\t\t@Override\n\t\tpublic void onCharacteristicRead(BluetoothGatt gatt,\n\t\t\t\tBluetoothGattCharacteristic characteristic, int status) {\n\t\t\tString address = gatt.getDevice().getAddress();\n\t\t\tLog.d(TAG, \"onCharacteristicRead \" + address + \" status \" + status);\n\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tmService.requestProcessed(address,\n\t\t\t\t\t\tRequestType.READ_CHARACTERISTIC, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Log.d(TAG, \"data \" + characteristic.getStringValue(0));\n\t\t\tmService.bleCharacteristicRead(gatt.getDevice().getAddress(),\n\t\t\t\t\tcharacteristic.getUuid().toString(), status,\n\t\t\t\t\tcharacteristic.getValue());\n\t\t}\n\n\t\t@Override\n\t\tpublic void onCharacteristicChanged(BluetoothGatt gatt,\n\t\t\t\tBluetoothGattCharacteristic characteristic) {\n\t\t\tString address = gatt.getDevice().getAddress();\n\t\t\tLog.d(TAG, \"onCharacteristicChanged \" + address);\n\t\t\tLog.d(TAG, new String(Hex.encodeHex(characteristic.getValue())));\n\t\t\tmService.bleCharacteristicChanged(address, characteristic.getUuid()\n\t\t\t\t\t.toString(), characteristic.getValue());\n\t\t}\n\n\t\tpublic void onCharacteristicWrite(BluetoothGatt gatt,\n\t\t\t\tBluetoothGattCharacteristic characteristic, int status) {\n\t\t\tString address = gatt.getDevice().getAddress();\n\t\t\tLog.d(TAG, \"onCharacteristicWrite \" + address + \" status \" + status);\n\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tmService.requestProcessed(address,\n\t\t\t\t\t\tRequestType.WRITE_CHARACTERISTIC, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmService.bleCharacteristicWrite(gatt.getDevice().getAddress(),\n\t\t\t\t\tcharacteristic.getUuid().toString(), status);\n\t\t};\n\n\t\tpublic void onDescriptorWrite(BluetoothGatt gatt,\n\t\t\t\tBluetoothGattDescriptor descriptor, int status) {\n\t\t\tString address = gatt.getDevice().getAddress();\n\t\t\tLog.d(TAG, \"onDescriptorWrite \" + address + \" status \" + status);\n\t\t\tBleRequest request = mService.getCurrentRequest();\n\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION\n\t\t\t\t\t|| request.type == RequestType.CHARACTERISTIC_INDICATION\n\t\t\t\t\t|| request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {\n\t\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\t\tmService.requestProcessed(address,\n\t\t\t\t\t\t\tRequestType.CHARACTERISTIC_NOTIFICATION, false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), true,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {\n\t\t\t\t\tmService.bleCharacteristicIndication(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), status);\n\t\t\t\t} else {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), false,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t};\n\t};\n\n\tpublic AndroidBle(BleService service) {\n\t\tmService = service;\n\t\t// btQuery = BTQuery.getInstance();\n\t\tif (!mService.getPackageManager().hasSystemFeature(\n\t\t\t\tPackageManager.FEATURE_BLUETOOTH_LE)) {\n\t\t\tmService.bleNotSupported();\n\t\t\treturn;\n\t\t}\n\n\t\tfinal BluetoothManager bluetoothManager = (BluetoothManager) mService\n\t\t\t\t.getSystemService(Context.BLUETOOTH_SERVICE);\n\n\t\tmBtAdapter = bluetoothManager.getAdapter();\n\t\tif (mBtAdapter == null) {\n\t\t\tmService.bleNoBtAdapter();\n\t\t}\n\t\tmBluetoothGatts = new HashMap<String, BluetoothGatt>();\n\t}\n\n\t@Override\n\tpublic void startScan() {\n\t\tmBtAdapter.startLeScan(mLeScanCallback);\n\t}\n\n\t@Override\n\tpublic void stopScan() {\n\t\tmBtAdapter.stopLeScan(mLeScanCallback);\n\t}\n\n\t@Override\n\tpublic boolean adapterEnabled() {\n\t\tif (mBtAdapter != null) {\n\t\t\treturn mBtAdapter.isEnabled();\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean connect(String address) {\n\t\tBluetoothDevice device = mBtAdapter.getRemoteDevice(address);\n\t\tBluetoothGatt gatt = device.connectGatt(mService, false, mGattCallback);\n\t\tif (gatt == null) {\n\t\t\tmBluetoothGatts.remove(address);\n\t\t\treturn false;\n\t\t} else {\n\t\t\t// TODO: if state is 141, it can be connected again after about 15\n\t\t\t// seconds\n\t\t\tmBluetoothGatts.put(address, gatt);\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void disconnect(String address) {\n\t\tif (mBluetoothGatts.containsKey(address)) {\n\t\t\tBluetoothGatt gatt = mBluetoothGatts.remove(address);\n\t\t\tif (gatt != null) {\n\t\t\t\tgatt.disconnect();\n\t\t\t\tgatt.close();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic ArrayList<BleGattService> getServices(String address) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tArrayList<BleGattService> list = new ArrayList<BleGattService>();\n\t\tList<BluetoothGattService> services = gatt.getServices();\n\t\tfor (BluetoothGattService s : services) {\n\t\t\tBleGattService service = new BleGattService(s);\n\t\t\t// service.setInfo(btQuery.getGattServiceInfo(s.getUuid()));\n\t\t\tlist.add(service);\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic boolean requestReadCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null || characteristic == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tmService.addBleRequest(new BleRequest(RequestType.READ_CHARACTERISTIC,\n\t\t\t\tgatt.getDevice().getAddress(), characteristic));\n\t\treturn true;\n\t}\n\n\tpublic boolean readCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn gatt.readCharacteristic(characteristic.getGattCharacteristicA());\n\t}\n\n\t@Override\n\tpublic boolean discoverServices(String address) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tboolean ret = gatt.discoverServices();\n\t\tif (!ret) {\n\t\t\tdisconnect(address);\n\t\t}\n\t\treturn ret;\n\t}\n\n\t@Override\n\tpublic BleGattService getService(String address, UUID uuid) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\tBluetoothGattService service = gatt.getService(uuid);\n\t\tif (service == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn new BleGattService(service);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean requestCharacteristicNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null || characteristic == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_NOTIFICATION, gatt.getDevice()\n\t\t\t\t\t\t.getAddress(), characteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean characteristicNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBleRequest request = mService.getCurrentRequest();\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null || characteristic == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tboolean enable = true;\n\t\tif (request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {\n\t\t\tenable = false;\n\t\t}\n\t\tBluetoothGattCharacteristic c = characteristic.getGattCharacteristicA();\n\t\tif (!gatt.setCharacteristicNotification(c, enable)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tBluetoothGattDescriptor descriptor = c\n\t\t\t\t.getDescriptor(BleService.DESC_CCC);\n\t\tif (descriptor == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tbyte[] val_set = null;\n\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {\n\t\t\tval_set = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;\n\t\t} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {\n\t\t\tval_set = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;\n\t\t} else {\n\t\t\tval_set = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;\n\t\t}\n\t\tif (!descriptor.setValue(val_set)) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn gatt.writeDescriptor(descriptor);\n\t}\n\n\t@Override\n\tpublic boolean requestWriteCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic, String remark) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null || characteristic == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tmService.addBleRequest(new BleRequest(RequestType.WRITE_CHARACTERISTIC,\n\t\t\t\tgatt.getDevice().getAddress(), characteristic, remark));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean writeCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tLog.d(\"blelib\", new String(Hex.encodeHex(characteristic.getGattCharacteristicA().getValue())));\n\t\treturn gatt\n\t\t\t\t.writeCharacteristic(characteristic.getGattCharacteristicA());\n\t}\n\n\t@Override\n\tpublic boolean requestConnect(String address) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt != null && gatt.getServices().size() == 0) {\n\t\t\treturn false;\n\t\t}\n\n\t\tmService.addBleRequest(new BleRequest(RequestType.CONNECT_GATT, address));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getBTAdapterMacAddr() {\n\t\tif (mBtAdapter != null) {\n\t\t\treturn mBtAdapter.getAddress();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean requestIndication(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null || characteristic == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_INDICATION, gatt.getDevice()\n\t\t\t\t\t\t.getAddress(), characteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean requestStopNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBluetoothGatt gatt = mBluetoothGatts.get(address);\n\t\tif (gatt == null || characteristic == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_NOTIFICATION, gatt.getDevice()\n\t\t\t\t\t\t.getAddress(), characteristic));\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BleGattCharacteristic.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\nimport java.util.UUID;\n\nimport android.annotation.SuppressLint;\n\nimport com.xtremeprog.sdk.ble.BleService.BLESDK;\n\n@SuppressLint(\"NewApi\")\npublic class BleGattCharacteristic {\n\n\tpublic static final int PROPERTY_READ = 2;\n\tpublic static final int PROPERTY_WRITE = 8;\n\tpublic static final int PROPERTY_NOTIFY = 16;\n\tpublic static final int PROPERTY_INDICATE = 32;\n\n\t/**\n\t * Characteristic value format type uint8\n\t */\n\tpublic static final int FORMAT_UINT8 = 0x11;\n\n\t/**\n\t * Characteristic value format type uint16\n\t */\n\tpublic static final int FORMAT_UINT16 = 0x12;\n\n\t/**\n\t * Characteristic value format type uint24 Note: this is not a standard data\n\t * type!\n\t */\n\tpublic static final int FORMAT_UINT24 = 0x13;\n\n\t/**\n\t * Characteristic value format type uint32\n\t */\n\tpublic static final int FORMAT_UINT32 = 0x14;\n\n\t/**\n\t * Characteristic value format type sint8\n\t */\n\tpublic static final int FORMAT_SINT8 = 0x21;\n\n\t/**\n\t * Characteristic value format type sint16\n\t */\n\tpublic static final int FORMAT_SINT16 = 0x22;\n\n\t/**\n\t * Characteristic value format type sint32\n\t */\n\tpublic static final int FORMAT_SINT32 = 0x24;\n\n\t/**\n\t * Characteristic value format type sfloat (16-bit float)\n\t */\n\tpublic static final int FORMAT_SFLOAT = 0x32;\n\n\t/**\n\t * Characteristic value format type float (32-bit float)\n\t */\n\tpublic static final int FORMAT_FLOAT = 0x34;\n\n\tprivate android.bluetooth.BluetoothGattCharacteristic mGattCharacteristicA;\n\tprivate com.broadcom.bt.gatt.BluetoothGattCharacteristic mGattCharacteristicB;\n\tprivate com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic mGattCharacteristicS;\n\tprivate BLESDK mBleSDK;\n\tprivate String name;\n\n\tpublic BleGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic c) {\n\t\tmBleSDK = BLESDK.ANDROID;\n\t\tsetGattCharacteristicA(c);\n\t\tinitInfo();\n\t}\n\n\tpublic BleGattCharacteristic(\n\t\t\tcom.broadcom.bt.gatt.BluetoothGattCharacteristic c) {\n\t\tmBleSDK = BLESDK.BROADCOM;\n\t\tsetGattCharacteristicB(c);\n\t}\n\n\tpublic BleGattCharacteristic(\n\t\t\tcom.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic c) {\n\t\tmBleSDK = BLESDK.SAMSUNG;\n\t\tsetGattCharacteristicS(c);\n\t}\n\n\tprivate void initInfo() {\n\t\tname = \"Unknown characteristic\";\n\t}\n\n\tpublic UUID getUuid() {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn getGattCharacteristicA().getUuid();\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn getGattCharacteristicB().getUuid();\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn getGattCharacteristicS().getUuid();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprotected android.bluetooth.BluetoothGattCharacteristic getGattCharacteristicA() {\n\t\treturn mGattCharacteristicA;\n\t}\n\n\tpublic int getProperties() {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn getGattCharacteristicA().getProperties();\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn getGattCharacteristicB().getProperties();\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn getGattCharacteristicS().getProperties();\n\t\t}\n\n\t\treturn 0;\n\t}\n\n\tprotected com.broadcom.bt.gatt.BluetoothGattCharacteristic getGattCharacteristicB() {\n\t\treturn mGattCharacteristicB;\n\t}\n\n\tprotected void setGattCharacteristicB(\n\t\t\tcom.broadcom.bt.gatt.BluetoothGattCharacteristic mBCGattCharacteristic) {\n\t\tthis.mGattCharacteristicB = mBCGattCharacteristic;\n\t}\n\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\n\tpublic boolean setValue(byte[] val) {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn getGattCharacteristicA().setValue(val);\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn mGattCharacteristicS.setValue(val);\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn mGattCharacteristicB.setValue(val);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic byte[] getValue() {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn getGattCharacteristicA().getValue();\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn mGattCharacteristicS.getValue();\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn mGattCharacteristicB.getValue();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic boolean setValue(int value, int formatType, int offset) {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn getGattCharacteristicA().setValue(value, formatType, offset);\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn mGattCharacteristicS.setValue(value, formatType, offset);\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn mGattCharacteristicB.setValue(value, formatType, offset);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic boolean setValue(int mantissa, int exponent, int formatType,\n\t\t\tint offset) {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn getGattCharacteristicA().setValue(mantissa, exponent,\n\t\t\t\t\tformatType, offset);\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn mGattCharacteristicS.setValue(mantissa, exponent,\n\t\t\t\t\tformatType, offset);\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn mGattCharacteristicB.setValue(mantissa, exponent,\n\t\t\t\t\tformatType, offset);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic boolean setValue(String value) {\n\t\treturn setValue(value.getBytes());\n\t}\n\n\tpublic String getStringValue(int offset) {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn getGattCharacteristicA().getStringValue(offset);\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn mGattCharacteristicS.getStringValue(offset);\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn mGattCharacteristicB.getStringValue(offset);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic Float getFloatValue(int formatType, int offset) {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn getGattCharacteristicA().getFloatValue(formatType, offset);\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn mGattCharacteristicS.getFloatValue(formatType, offset);\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn mGattCharacteristicB.getFloatValue(formatType, offset);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic Integer getIntValue(int formatType, int offset) {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\tif (formatType == FORMAT_UINT24) {\n\t\t\t\tbyte[] value = getGattCharacteristicA().getValue();\n\t\t\t\treturn byte2uint24(offset, value);\n\t\t\t} else {\n\t\t\t\treturn getGattCharacteristicA().getIntValue(formatType, offset);\n\t\t\t}\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\tif (formatType == FORMAT_UINT24) {\n\t\t\t\tbyte[] value = mGattCharacteristicS.getValue();\n\t\t\t\treturn byte2uint24(offset, value);\n\t\t\t} else {\n\t\t\t\treturn mGattCharacteristicS.getIntValue(formatType, offset);\n\t\t\t}\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\tif (formatType == FORMAT_UINT24) {\n\t\t\t\tbyte[] value = mGattCharacteristicB.getValue();\n\t\t\t\treturn byte2uint24(offset, value);\n\t\t\t} else {\n\t\t\t\treturn mGattCharacteristicB.getIntValue(formatType, offset);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tprivate Integer byte2uint24(int offset, byte[] value) {\n\t\tif ((offset + 3) > value.length)\n\t\t\treturn null;\n\t\treturn Integer.valueOf((value[offset] & 0xFF)\n\t\t\t\t| (value[offset + 1] & 0xFF) << 8\n\t\t\t\t| (value[offset + 2] & 0xFF) << 16);\n\t}\n\n\tprotected com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic getGattCharacteristicS() {\n\t\treturn mGattCharacteristicS;\n\t}\n\n\tprotected void setGattCharacteristicS(\n\t\t\tcom.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic mSSGattCharacteristic) {\n\t\tthis.mGattCharacteristicS = mSSGattCharacteristic;\n\t}\n\n\tprotected void setGattCharacteristicA(\n\t\t\tandroid.bluetooth.BluetoothGattCharacteristic mGattCharacteristicA) {\n\t\tthis.mGattCharacteristicA = mGattCharacteristicA;\n\t}\n}\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BleGattService.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.UUID;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport android.annotation.SuppressLint;\nimport android.bluetooth.BluetoothGattCharacteristic;\n\nimport com.xtremeprog.sdk.ble.BleService.BLESDK;\n\n@SuppressLint(\"NewApi\")\npublic class BleGattService {\n\n\tprivate BLESDK mBleSDK;\n\tprivate com.samsung.android.sdk.bt.gatt.BluetoothGattService mGattServiceS;\n\tprivate com.broadcom.bt.gatt.BluetoothGattService mGattServiceB;\n\tprivate android.bluetooth.BluetoothGattService mGattServiceA;\n\tprivate String mName;\n\n\tpublic BleGattService(com.samsung.android.sdk.bt.gatt.BluetoothGattService s) {\n\t\tmBleSDK = BLESDK.SAMSUNG;\n\t\tmGattServiceS = s;\n\t\tinitInfo();\n\t}\n\n\tpublic BleGattService(com.broadcom.bt.gatt.BluetoothGattService s) {\n\t\tmBleSDK = BLESDK.BROADCOM;\n\t\tmGattServiceB = s;\n\t\tinitInfo();\n\t}\n\n\tpublic BleGattService(android.bluetooth.BluetoothGattService s) {\n\t\tmBleSDK = BLESDK.ANDROID;\n\t\tmGattServiceA = s;\n\t\tinitInfo();\n\t}\n\n\tprivate void initInfo() {\n\t\tmName = \"Unknown Service\";\n\t}\n\n\tpublic UUID getUuid() {\n\t\tif (mBleSDK == BLESDK.BROADCOM) {\n\t\t\treturn mGattServiceB.getUuid();\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\treturn mGattServiceS.getUuid();\n\t\t} else if (mBleSDK == BLESDK.ANDROID) {\n\t\t\treturn mGattServiceA.getUuid();\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic List<BleGattCharacteristic> getCharacteristics() {\n\t\tArrayList<BleGattCharacteristic> list = new ArrayList<BleGattCharacteristic>();\n\t\tif (mBleSDK == BLESDK.BROADCOM) {\n\t\t\tfor (com.broadcom.bt.gatt.BluetoothGattCharacteristic c : mGattServiceB\n\t\t\t\t\t.getCharacteristics()) {\n\t\t\t\tlist.add(new BleGattCharacteristic(c));\n\t\t\t}\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\tfor (Object o : mGattServiceS.getCharacteristics()) {\n\t\t\t\tcom.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic c = (com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic) o;\n\t\t\t\tlist.add(new BleGattCharacteristic(c));\n\t\t\t}\n\t\t} else if (mBleSDK == BLESDK.ANDROID) {\n\t\t\tfor (android.bluetooth.BluetoothGattCharacteristic c : mGattServiceA\n\t\t\t\t\t.getCharacteristics()) {\n\t\t\t\tlist.add(new BleGattCharacteristic(c));\n\t\t\t}\n\t\t}\n\n\t\treturn list;\n\t}\n\n\tpublic BleGattCharacteristic getCharacteristic(UUID uuid) {\n\t\tif (mBleSDK == BLESDK.ANDROID) {\n\t\t\tBluetoothGattCharacteristic c = mGattServiceA\n\t\t\t\t\t.getCharacteristic(uuid);\n\t\t\tif (c != null) {\n\t\t\t\treturn new BleGattCharacteristic(c);\n\t\t\t}\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\tcom.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic c = mGattServiceS\n\t\t\t\t\t.getCharacteristic(uuid);\n\t\t\tif (c != null) {\n\t\t\t\treturn new BleGattCharacteristic(c);\n\t\t\t}\n\t\t} else if (mBleSDK == BLESDK.BROADCOM) {\n\t\t\tcom.broadcom.bt.gatt.BluetoothGattCharacteristic c = mGattServiceB\n\t\t\t\t\t.getCharacteristic(uuid);\n\t\t\tif (c != null) {\n\t\t\t\treturn new BleGattCharacteristic(c);\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tpublic void setInfo(JSONObject info) {\n\t\tif (info == null) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tsetName(info.getString(\"name\"));\n\t\t} catch (JSONException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\tpublic String getName() {\n\t\treturn mName;\n\t}\n\n\tpublic void setName(String mName) {\n\t\tthis.mName = mName;\n\t}\n}\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BleRequest.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\npublic class BleRequest {\n\tpublic enum RequestType {\n\t\tCONNECT_GATT, DISCOVER_SERVICE, CHARACTERISTIC_NOTIFICATION, CHARACTERISTIC_INDICATION, READ_CHARACTERISTIC, READ_DESCRIPTOR, READ_RSSI, WRITE_CHARACTERISTIC, WRITE_DESCRIPTOR, CHARACTERISTIC_STOP_NOTIFICATION\n\t};\n\n\tpublic enum FailReason {\n\t\tSTART_FAILED, TIMEOUT, RESULT_FAILED\n\t}\n\n\tpublic RequestType type;\n\tpublic String address;\n\tpublic BleGattCharacteristic characteristic;\n\tpublic String remark;\n\n\tpublic BleRequest(RequestType type, String address) {\n\t\tthis.type = type;\n\t\tthis.address = address;\n\t}\n\n\tpublic BleRequest(RequestType type, String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tthis.type = type;\n\t\tthis.address = address;\n\t\tthis.characteristic = characteristic;\n\t}\n\n\tpublic BleRequest(RequestType type, String address,\n\t\t\tBleGattCharacteristic characteristic, String remark) {\n\t\tthis.type = type;\n\t\tthis.address = address;\n\t\tthis.characteristic = characteristic;\n\t\tthis.remark = remark;\n\t}\n\n\t@Override\n\tpublic boolean equals(Object o) {\n\t\tif (!(o instanceof BleRequest)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tBleRequest br = (BleRequest) o;\n\t\treturn (this.type == br.type && this.address.equals(br.address));\n\t}\n}\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BleService.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.LinkedList;\nimport java.util.Queue;\nimport java.util.UUID;\n\nimport android.app.Service;\nimport android.bluetooth.BluetoothDevice;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.content.pm.PackageManager;\nimport android.os.Binder;\nimport android.os.IBinder;\nimport android.util.Log;\n\nimport com.xtremeprog.sdk.ble.BleRequest.FailReason;\nimport com.xtremeprog.sdk.ble.BleRequest.RequestType;\n\npublic class BleService extends Service {\n\tprivate static final String TAG = \"blelib\";\n\n\t/** Intent for broadcast */\n\tpublic static final String BLE_NOT_SUPPORTED = \"com.xtremeprog.sdk.ble.not_supported\";\n\tpublic static final String BLE_NO_BT_ADAPTER = \"com.xtremeprog.sdk.ble.no_bt_adapter\";\n\tpublic static final String BLE_STATUS_ABNORMAL = \"com.xtremeprog.sdk.ble.status_abnormal\";\n\t/**\n\t * @see BleService#bleRequestFailed\n\t */\n\tpublic static final String BLE_REQUEST_FAILED = \"com.xtremeprog.sdk.ble.request_failed\";\n\t/**\n\t * @see BleService#bleDeviceFound\n\t */\n\tpublic static final String BLE_DEVICE_FOUND = \"com.xtremeprog.sdk.ble.device_found\";\n\t/**\n\t * @see BleService#bleGattConnected\n\t */\n\tpublic static final String BLE_GATT_CONNECTED = \"com.xtremeprog.sdk.ble.gatt_connected\";\n\t/**\n\t * @see BleService#bleGattDisConnected\n\t */\n\tpublic static final String BLE_GATT_DISCONNECTED = \"com.xtremeprog.sdk.ble.gatt_disconnected\";\n\t/**\n\t * @see BleService#bleServiceDiscovered\n\t */\n\tpublic static final String BLE_SERVICE_DISCOVERED = \"com.xtremeprog.sdk.ble.service_discovered\";\n\t/**\n\t * @see BleService#bleCharacteristicRead\n\t */\n\tpublic static final String BLE_CHARACTERISTIC_READ = \"com.xtremeprog.sdk.ble.characteristic_read\";\n\t/**\n\t * @see BleService#bleCharacteristicNotification\n\t */\n\tpublic static final String BLE_CHARACTERISTIC_NOTIFICATION = \"com.xtremeprog.sdk.ble.characteristic_notification\";\n\t/**\n\t * @see BleService#bleCharacteristicIndication\n\t */\n\tpublic static final String BLE_CHARACTERISTIC_INDICATION = \"com.xtremeprog.sdk.ble.characteristic_indication\";\n\t/**\n\t * @see BleService#bleCharacteristicWrite\n\t */\n\tpublic static final String BLE_CHARACTERISTIC_WRITE = \"com.xtremeprog.sdk.ble.characteristic_write\";\n\t/**\n\t * @see BleService#bleCharacteristicChanged\n\t */\n\tpublic static final String BLE_CHARACTERISTIC_CHANGED = \"com.xtremeprog.sdk.ble.characteristic_changed\";\n\n\t/** Intent extras */\n\tpublic static final String EXTRA_DEVICE = \"DEVICE\";\n\tpublic static final String EXTRA_RSSI = \"RSSI\";\n\tpublic static final String EXTRA_SCAN_RECORD = \"SCAN_RECORD\";\n\tpublic static final String EXTRA_SOURCE = \"SOURCE\";\n\tpublic static final String EXTRA_ADDR = \"ADDRESS\";\n\tpublic static final String EXTRA_CONNECTED = \"CONNECTED\";\n\tpublic static final String EXTRA_STATUS = \"STATUS\";\n\tpublic static final String EXTRA_UUID = \"UUID\";\n\tpublic static final String EXTRA_VALUE = \"VALUE\";\n\tpublic static final String EXTRA_REQUEST = \"REQUEST\";\n\tpublic static final String EXTRA_REASON = \"REASON\";\n\n\t/** Source of device entries in the device list */\n\tpublic static final int DEVICE_SOURCE_SCAN = 0;\n\tpublic static final int DEVICE_SOURCE_BONDED = 1;\n\tpublic static final int DEVICE_SOURCE_CONNECTED = 2;\n\n\tpublic static final UUID DESC_CCC = UUID\n\t\t\t.fromString(\"00002902-0000-1000-8000-00805f9b34fb\");\n\n\tpublic enum BLESDK {\n\t\tNOT_SUPPORTED, ANDROID, SAMSUNG, BROADCOM\n\t}\n\n\tprivate final IBinder mBinder = new LocalBinder();\n\tprivate BLESDK mBleSDK;\n\tprivate IBle mBle;\n\tprivate Queue<BleRequest> mRequestQueue = new LinkedList<BleRequest>();\n\tprivate BleRequest mCurrentRequest = null;\n\tprivate static final int REQUEST_TIMEOUT = 10 * 10; // total timeout =\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// REQUEST_TIMEOUT *\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// 100ms\n\tprivate boolean mCheckTimeout = false;\n\tprivate int mElapsed = 0;\n\tprivate Thread mRequestTimeout;\n\tprivate String mNotificationAddress;\n\n\tprivate Runnable mTimeoutRunnable = new Runnable() {\n\t\t@Override\n\t\tpublic void run() {\n\t\t\tLog.d(TAG, \"monitoring thread start\");\n\t\t\tmElapsed = 0;\n\t\t\ttry {\n\t\t\t\twhile (mCheckTimeout) {\n\t\t\t\t\t// Log.d(TAG, \"monitoring timeout seconds: \" + mElapsed);\n\t\t\t\t\tThread.sleep(100);\n\t\t\t\t\tmElapsed++;\n\n\t\t\t\t\tif (mElapsed > REQUEST_TIMEOUT && mCurrentRequest != null) {\n\t\t\t\t\t\tLog.d(TAG, \"-processrequest type \"\n\t\t\t\t\t\t\t\t+ mCurrentRequest.type + \" address \"\n\t\t\t\t\t\t\t\t+ mCurrentRequest.address + \" [timeout]\");\n\t\t\t\t\t\tbleRequestFailed(mCurrentRequest.address,\n\t\t\t\t\t\t\t\tmCurrentRequest.type, FailReason.TIMEOUT);\n\t\t\t\t\t\tbleStatusAbnormal(\"-processrequest type \"\n\t\t\t\t\t\t\t\t+ mCurrentRequest.type + \" address \"\n\t\t\t\t\t\t\t\t+ mCurrentRequest.address + \" [timeout]\");\n\t\t\t\t\t\tif (mBle != null) {\n\t\t\t\t\t\t\tmBle.disconnect(mCurrentRequest.address);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnew Thread(new Runnable() {\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\t\t\tmCurrentRequest = null;\n\t\t\t\t\t\t\t\tprocessNextRequest();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, \"th-ble\").start();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t\tLog.d(TAG, \"monitoring thread exception\");\n\t\t\t}\n\t\t\tLog.d(TAG, \"monitoring thread stop\");\n\t\t}\n\t};\n\n\tpublic static IntentFilter getIntentFilter() {\n\t\tIntentFilter intentFilter = new IntentFilter();\n\t\tintentFilter.addAction(BLE_NOT_SUPPORTED);\n\t\tintentFilter.addAction(BLE_NO_BT_ADAPTER);\n\t\tintentFilter.addAction(BLE_STATUS_ABNORMAL);\n\t\tintentFilter.addAction(BLE_REQUEST_FAILED);\n\t\tintentFilter.addAction(BLE_DEVICE_FOUND);\n\t\tintentFilter.addAction(BLE_GATT_CONNECTED);\n\t\tintentFilter.addAction(BLE_GATT_DISCONNECTED);\n\t\tintentFilter.addAction(BLE_SERVICE_DISCOVERED);\n\t\tintentFilter.addAction(BLE_CHARACTERISTIC_READ);\n\t\tintentFilter.addAction(BLE_CHARACTERISTIC_NOTIFICATION);\n\t\tintentFilter.addAction(BLE_CHARACTERISTIC_WRITE);\n\t\tintentFilter.addAction(BLE_CHARACTERISTIC_CHANGED);\n\t\treturn intentFilter;\n\t}\n\n\t@Override\n\tpublic IBinder onBind(Intent intent) {\n\t\treturn mBinder;\n\t}\n\n\tpublic class LocalBinder extends Binder {\n\t\tpublic BleService getService() {\n\t\t\treturn BleService.this;\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onCreate() {\n\t\tmBleSDK = getBleSDK();\n\t\tif (mBleSDK == BLESDK.NOT_SUPPORTED) {\n\t\t\treturn;\n\t\t}\n\n\t\tLog.d(TAG, \" \" + mBleSDK);\n\t\tif (mBleSDK == BLESDK.BROADCOM) {\n\t\t\tmBle = new BroadcomBle(this);\n\t\t} else if (mBleSDK == BLESDK.ANDROID) {\n\t\t\tmBle = new AndroidBle(this);\n\t\t} else if (mBleSDK == BLESDK.SAMSUNG) {\n\t\t\tmBle = new SamsungBle(this);\n\t\t}\n\t}\n\n\tprotected void bleNotSupported() {\n\t\tIntent intent = new Intent(BleService.BLE_NOT_SUPPORTED);\n\t\tsendBroadcast(intent);\n\t}\n\n\tprotected void bleNoBtAdapter() {\n\t\tIntent intent = new Intent(BleService.BLE_NO_BT_ADAPTER);\n\t\tsendBroadcast(intent);\n\t}\n\n\tprivate BLESDK getBleSDK() {\n\t\tif (getPackageManager().hasSystemFeature(\n\t\t\t\tPackageManager.FEATURE_BLUETOOTH_LE)) {\n\t\t\t// android 4.3\n\t\t\treturn BLESDK.ANDROID;\n\t\t}\n\n\t\tArrayList<String> libraries = new ArrayList<String>();\n\t\tfor (String i : getPackageManager().getSystemSharedLibraryNames()) {\n\t\t\tlibraries.add(i);\n\t\t}\n\n\t\tif (android.os.Build.VERSION.SDK_INT >= 17) {\n\t\t\t// android 4.2.2\n\t\t\tif (libraries.contains(\"com.samsung.android.sdk.bt\")) {\n\t\t\t\treturn BLESDK.SAMSUNG;\n\t\t\t} else if (libraries.contains(\"com.broadcom.bt\")) {\n\t\t\t\treturn BLESDK.BROADCOM;\n\t\t\t}\n\t\t}\n\n\t\tbleNotSupported();\n\t\treturn BLESDK.NOT_SUPPORTED;\n\t}\n\n\tpublic IBle getBle() {\n\t\treturn mBle;\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_DEVICE_FOUND} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_DEVICE} device {@link BluetoothDevice} <br>\n\t * {@link BleService#EXTRA_RSSI} rssi int<br>\n\t * {@link BleService#EXTRA_SCAN_RECORD} scan record byte[] <br>\n\t * {@link BleService#EXTRA_SOURCE} source int, not used now <br>\n\t */\n\tprotected void bleDeviceFound(BluetoothDevice device, int rssi,\n\t\t\tbyte[] scanRecord, int source) {\n\t\tLog.d(\"blelib\", \"[\" + new Date().toLocaleString() + \"] device found \"\n\t\t\t\t+ device.getAddress());\n\t\tIntent intent = new Intent(BleService.BLE_DEVICE_FOUND);\n\t\tintent.putExtra(BleService.EXTRA_DEVICE, device);\n\t\tintent.putExtra(BleService.EXTRA_RSSI, rssi);\n\t\tintent.putExtra(BleService.EXTRA_SCAN_RECORD, scanRecord);\n\t\tintent.putExtra(BleService.EXTRA_SOURCE, source);\n\t\tsendBroadcast(intent);\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_GATT_CONNECTED} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_DEVICE} device {@link BluetoothDevice} <br>\n\t */\n\tprotected void bleGattConnected(BluetoothDevice device) {\n\t\tIntent intent = new Intent(BLE_GATT_CONNECTED);\n\t\tintent.putExtra(EXTRA_DEVICE, device);\n\t\tintent.putExtra(EXTRA_ADDR, device.getAddress());\n\t\tsendBroadcast(intent);\n\t\trequestProcessed(device.getAddress(), RequestType.CONNECT_GATT, true);\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_GATT_DISCONNECTED} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_ADDR} device address {@link String} <br>\n\t * \n\t * @param address\n\t */\n\tprotected void bleGattDisConnected(String address) {\n\t\tIntent intent = new Intent(BLE_GATT_DISCONNECTED);\n\t\tintent.putExtra(EXTRA_ADDR, address);\n\t\tsendBroadcast(intent);\n\t\trequestProcessed(address, RequestType.CONNECT_GATT, false);\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_SERVICE_DISCOVERED} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_ADDR} device address {@link String} <br>\n\t * \n\t * @param address\n\t */\n\tprotected void bleServiceDiscovered(String address) {\n\t\tIntent intent = new Intent(BLE_SERVICE_DISCOVERED);\n\t\tintent.putExtra(EXTRA_ADDR, address);\n\t\tsendBroadcast(intent);\n\t\trequestProcessed(address, RequestType.DISCOVER_SERVICE, true);\n\t}\n\n\tprotected void requestProcessed(String address, RequestType requestType,\n\t\t\tboolean success) {\n\t\tif (mCurrentRequest != null && mCurrentRequest.type == requestType) {\n\t\t\tclearTimeoutThread();\n\t\t\tLog.d(TAG, \"-processrequest type \" + requestType + \" address \"\n\t\t\t\t\t+ address + \" [success: \" + success + \"]\");\n\t\t\tif (!success) {\n\t\t\t\tbleRequestFailed(mCurrentRequest.address, mCurrentRequest.type,\n\t\t\t\t\t\tFailReason.RESULT_FAILED);\n\t\t\t}\n\t\t\tnew Thread(new Runnable() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tmCurrentRequest = null;\n\t\t\t\t\tprocessNextRequest();\n\t\t\t\t}\n\t\t\t}, \"th-ble\").start();\n\t\t}\n\t}\n\n\tprivate void clearTimeoutThread() {\n\t\tif (mRequestTimeout.isAlive()) {\n\t\t\ttry {\n\t\t\t\tmCheckTimeout = false;\n\t\t\t\tmRequestTimeout.join();\n\t\t\t\tmRequestTimeout = null;\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_CHARACTERISTIC_READ} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_ADDR} device address {@link String} <br>\n\t * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>\n\t * {@link BleService#EXTRA_STATUS} read status {@link Integer} Not used now <br>\n\t * {@link BleService#EXTRA_VALUE} data byte[] <br>\n\t * \n\t * @param address\n\t * @param uuid\n\t * @param status\n\t * @param value\n\t */\n\tprotected void bleCharacteristicRead(String address, String uuid,\n\t\t\tint status, byte[] value) {\n\t\tIntent intent = new Intent(BLE_CHARACTERISTIC_READ);\n\t\tintent.putExtra(EXTRA_ADDR, address);\n\t\tintent.putExtra(EXTRA_UUID, uuid);\n\t\tintent.putExtra(EXTRA_STATUS, status);\n\t\tintent.putExtra(EXTRA_VALUE, value);\n\t\tsendBroadcast(intent);\n\t\trequestProcessed(address, RequestType.READ_CHARACTERISTIC, true);\n\t}\n\n\tprotected void addBleRequest(BleRequest request) {\n\t\tsynchronized (mRequestQueue) {\n\t\t\tmRequestQueue.add(request);\n\t\t\tprocessNextRequest();\n\t\t}\n\t}\n\n\tprivate synchronized void processNextRequest() {\n\t\tif (mCurrentRequest != null) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (mRequestQueue.isEmpty()) {\n\t\t\treturn;\n\t\t}\n\t\tmCurrentRequest = mRequestQueue.remove();\n\t\tLog.d(TAG, \"+processrequest type \" + mCurrentRequest.type + \" address \"\n\t\t\t\t+ mCurrentRequest.address + \" remark \" + mCurrentRequest.remark);\n\t\tstartTimeoutThread();\n\t\tboolean ret = false;\n\t\tswitch (mCurrentRequest.type) {\n\t\tcase CONNECT_GATT:\n\t\t\tret = ((IBleRequestHandler) mBle).connect(mCurrentRequest.address);\n\t\t\tbreak;\n\t\tcase DISCOVER_SERVICE:\n\t\t\tret = mBle.discoverServices(mCurrentRequest.address);\n\t\t\tbreak;\n\t\tcase CHARACTERISTIC_NOTIFICATION:\n\t\tcase CHARACTERISTIC_INDICATION:\n\t\tcase CHARACTERISTIC_STOP_NOTIFICATION:\n\t\t\tret = ((IBleRequestHandler) mBle).characteristicNotification(\n\t\t\t\t\tmCurrentRequest.address, mCurrentRequest.characteristic);\n\t\t\tbreak;\n\t\tcase READ_CHARACTERISTIC:\n\t\t\tret = ((IBleRequestHandler) mBle).readCharacteristic(\n\t\t\t\t\tmCurrentRequest.address, mCurrentRequest.characteristic);\n\t\t\tbreak;\n\t\tcase WRITE_CHARACTERISTIC:\n\t\t\tret = ((IBleRequestHandler) mBle).writeCharacteristic(\n\t\t\t\t\tmCurrentRequest.address, mCurrentRequest.characteristic);\n\t\t\tbreak;\n\t\tcase READ_DESCRIPTOR:\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\n\t\tif (!ret) {\n\t\t\tclearTimeoutThread();\n\t\t\tLog.d(TAG, \"-processrequest type \" + mCurrentRequest.type\n\t\t\t\t\t+ \" address \" + mCurrentRequest.address + \" [fail start]\");\n\t\t\tbleRequestFailed(mCurrentRequest.address, mCurrentRequest.type,\n\t\t\t\t\tFailReason.START_FAILED);\n\t\t\tnew Thread(new Runnable() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tmCurrentRequest = null;\n\t\t\t\t\tprocessNextRequest();\n\t\t\t\t}\n\t\t\t}, \"th-ble\").start();\n\t\t}\n\t}\n\n\tprivate void startTimeoutThread() {\n\t\tmCheckTimeout = true;\n\t\tmRequestTimeout = new Thread(mTimeoutRunnable);\n\t\tmRequestTimeout.start();\n\t}\n\n\tprotected BleRequest getCurrentRequest() {\n\t\treturn mCurrentRequest;\n\t}\n\n\tprotected void setCurrentRequest(BleRequest mCurrentRequest) {\n\t\tthis.mCurrentRequest = mCurrentRequest;\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_CHARACTERISTIC_NOTIFICATION} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_ADDR} device address {@link String} <br>\n\t * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>\n\t * {@link BleService#EXTRA_STATUS} read status {@link Integer} Not used now <br>\n\t * \n\t * @param address\n\t * @param uuid\n\t * @param status\n\t */\n\tprotected void bleCharacteristicNotification(String address, String uuid,\n\t\t\tboolean isEnabled, int status) {\n\t\tIntent intent = new Intent(BLE_CHARACTERISTIC_NOTIFICATION);\n\t\tintent.putExtra(EXTRA_ADDR, address);\n\t\tintent.putExtra(EXTRA_UUID, uuid);\n\t\tintent.putExtra(EXTRA_VALUE, isEnabled);\n\t\tintent.putExtra(EXTRA_STATUS, status);\n\t\tsendBroadcast(intent);\n\t\tif (isEnabled) {\n\t\t\trequestProcessed(address, RequestType.CHARACTERISTIC_NOTIFICATION,\n\t\t\t\t\ttrue);\n\t\t} else {\n\t\t\trequestProcessed(address,\n\t\t\t\t\tRequestType.CHARACTERISTIC_STOP_NOTIFICATION, true);\n\t\t}\n\t\tsetNotificationAddress(address);\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_CHARACTERISTIC_INDICATION} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_ADDR} device address {@link String} <br>\n\t * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>\n\t * {@link BleService#EXTRA_STATUS} read status {@link Integer} Not used now <br>\n\t * \n\t * @param address\n\t * @param uuid\n\t * @param status\n\t */\n\tprotected void bleCharacteristicIndication(String address, String uuid,\n\t\t\tint status) {\n\t\tIntent intent = new Intent(BLE_CHARACTERISTIC_INDICATION);\n\t\tintent.putExtra(EXTRA_ADDR, address);\n\t\tintent.putExtra(EXTRA_UUID, uuid);\n\t\tintent.putExtra(EXTRA_STATUS, status);\n\t\tsendBroadcast(intent);\n\t\trequestProcessed(address, RequestType.CHARACTERISTIC_INDICATION, true);\n\t\tsetNotificationAddress(address);\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_CHARACTERISTIC_WRITE} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_ADDR} device address {@link String} <br>\n\t * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>\n\t * {@link BleService#EXTRA_STATUS} read status {@link Integer} Not used now <br>\n\t * \n\t * @param address\n\t * @param uuid\n\t * @param status\n\t */\n\tprotected void bleCharacteristicWrite(String address, String uuid,\n\t\t\tint status) {\n\t\tIntent intent = new Intent(BLE_CHARACTERISTIC_WRITE);\n\t\tintent.putExtra(EXTRA_ADDR, address);\n\t\tintent.putExtra(EXTRA_UUID, uuid);\n\t\tintent.putExtra(EXTRA_STATUS, status);\n\t\tsendBroadcast(intent);\n\t\trequestProcessed(address, RequestType.WRITE_CHARACTERISTIC, true);\n\t}\n\n\t/**\n\t * Send {@link BleService#BLE_CHARACTERISTIC_CHANGED} broadcast. <br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_ADDR} device address {@link String} <br>\n\t * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>\n\t * {@link BleService#EXTRA_VALUE} data byte[] <br>\n\t * \n\t * @param address\n\t * @param uuid\n\t * @param value\n\t */\n\tprotected void bleCharacteristicChanged(String address, String uuid,\n\t\t\tbyte[] value) {\n\t\tIntent intent = new Intent(BLE_CHARACTERISTIC_CHANGED);\n\t\tintent.putExtra(EXTRA_ADDR, address);\n\t\tintent.putExtra(EXTRA_UUID, uuid);\n\t\tintent.putExtra(EXTRA_VALUE, value);\n\t\tsendBroadcast(intent);\n\t}\n\n\t/**\n\t * @param reason\n\t */\n\tprotected void bleStatusAbnormal(String reason) {\n\t\tIntent intent = new Intent(BLE_STATUS_ABNORMAL);\n\t\tintent.putExtra(EXTRA_VALUE, reason);\n\t\tsendBroadcast(intent);\n\t}\n\n\t/**\n\t * Sent when BLE request failed.<br>\n\t * <br>\n\t * Data in the broadcast intent: <br>\n\t * {@link BleService#EXTRA_ADDR} device address {@link String} <br>\n\t * {@link BleService#EXTRA_REQUEST} request type\n\t * {@link BleRequest.RequestType} <br>\n\t * {@link BleService#EXTRA_REASON} fail reason {@link BleRequest.FailReason} <br>\n\t */\n\tprotected void bleRequestFailed(String address, RequestType type,\n\t\t\tFailReason reason) {\n\t\tIntent intent = new Intent(BLE_REQUEST_FAILED);\n\t\tintent.putExtra(EXTRA_ADDR, address);\n\t\tintent.putExtra(EXTRA_REQUEST, type);\n\t\tintent.putExtra(EXTRA_REASON, reason.ordinal());\n\t\tsendBroadcast(intent);\n\t}\n\n\tprotected String getNotificationAddress() {\n\t\treturn mNotificationAddress;\n\t}\n\n\tprotected void setNotificationAddress(String mNotificationAddress) {\n\t\tthis.mNotificationAddress = mNotificationAddress;\n\t}\n}\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BroadcomBle.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.UUID;\n\nimport android.bluetooth.BluetoothAdapter;\nimport android.bluetooth.BluetoothDevice;\nimport android.bluetooth.BluetoothProfile;\n\nimport com.broadcom.bt.gatt.BluetoothGatt;\nimport com.broadcom.bt.gatt.BluetoothGattAdapter;\nimport com.broadcom.bt.gatt.BluetoothGattCallback;\nimport com.broadcom.bt.gatt.BluetoothGattCharacteristic;\nimport com.broadcom.bt.gatt.BluetoothGattDescriptor;\nimport com.broadcom.bt.gatt.BluetoothGattService;\nimport com.xtremeprog.sdk.ble.BleRequest.RequestType;\n\npublic class BroadcomBle implements IBle, IBleRequestHandler {\n\tprivate BluetoothAdapter mBtAdapter;\n\tprivate BleService mService;\n\tprivate BluetoothGatt mBluetoothGatt;\n\tprivate boolean mScanning;\n\tprivate String mAddress;\n\n\tprivate final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() {\n\t\t@Override\n\t\tpublic void onAppRegistered(int status) {\n\t\t}\n\n\t\t@Override\n\t\tpublic void onScanResult(BluetoothDevice device, int rssi,\n\t\t\t\tbyte[] scanRecord) {\n\t\t\tmService.bleDeviceFound(device, rssi, scanRecord,\n\t\t\t\t\tBleService.DEVICE_SOURCE_SCAN);\n\t\t}\n\n\t\t@Override\n\t\tpublic void onConnectionStateChange(BluetoothDevice device, int status,\n\t\t\t\tint newState) {\n\t\t\tif (mBluetoothGatt == null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (newState == BluetoothProfile.STATE_CONNECTED) {\n\t\t\t\tmService.bleGattConnected(device);\n\t\t\t\tmBluetoothGatt.discoverServices(device);\n\t\t\t\tmAddress = device.getAddress();\n\t\t\t} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {\n\t\t\t\tmService.bleGattDisConnected(device.getAddress());\n\t\t\t\tmAddress = null;\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void onServicesDiscovered(BluetoothDevice device, int status) {\n\t\t\tmService.bleServiceDiscovered(device.getAddress());\n\t\t}\n\n\t\t@Override\n\t\tpublic void onCharacteristicRead(\n\t\t\t\tBluetoothGattCharacteristic characteristic, int status) {\n\t\t\tif (status == BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tmService.bleCharacteristicRead(mAddress, characteristic\n\t\t\t\t\t\t.getUuid().toString(), status, characteristic\n\t\t\t\t\t\t.getValue());\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void onCharacteristicChanged(\n\t\t\t\tBluetoothGattCharacteristic characteristic) {\n\t\t\tString address = mService.getNotificationAddress();\n\t\t\tmService.bleCharacteristicChanged(address, characteristic.getUuid()\n\t\t\t\t\t.toString(), characteristic.getValue());\n\t\t}\n\n\t\t@Override\n\t\tpublic void onDescriptorRead(BluetoothGattDescriptor descriptor,\n\t\t\t\tint status) {\n\t\t\tBleRequest request = mService.getCurrentRequest();\n\t\t\tString address = request.address;\n\t\t\tbyte[] value = descriptor.getValue();\n\t\t\tbyte[] val_set = null;\n\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {\n\t\t\t\tval_set = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;\n\t\t\t} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {\n\t\t\t\tval_set = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;\n\t\t\t} else {\n\t\t\t\tval_set = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;\n\t\t\t}\n\n\t\t\tif (Arrays.equals(value, val_set)) {\n\t\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), true,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {\n\t\t\t\t\tmService.bleCharacteristicIndication(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), status);\n\t\t\t\t} else {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), false,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!descriptor.setValue(val_set)) {\n\t\t\t\tmService.requestProcessed(address, request.type, false);\n\t\t\t}\n\n\t\t\tmBluetoothGatt.writeDescriptor(descriptor);\n\t\t};\n\n\t\t@Override\n\t\tpublic void onDescriptorWrite(BluetoothGattDescriptor descriptor,\n\t\t\t\tint status) {\n\t\t\tBleRequest request = mService.getCurrentRequest();\n\t\t\tString address = request.address;\n\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION\n\t\t\t\t\t|| request.type == RequestType.CHARACTERISTIC_INDICATION\n\t\t\t\t\t|| request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {\n\t\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\t\tmService.requestProcessed(address, request.type, false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), true,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {\n\t\t\t\t\tmService.bleCharacteristicIndication(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), status);\n\t\t\t\t} else {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), false,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t};\n\t};\n\n\tprivate final BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() {\n\t\t@Override\n\t\tpublic void onServiceConnected(int profile, BluetoothProfile proxy) {\n\t\t\tmBluetoothGatt = (BluetoothGatt) proxy;\n\t\t\tmBluetoothGatt.registerApp(mGattCallbacks);\n\t\t}\n\n\t\t@Override\n\t\tpublic void onServiceDisconnected(int profile) {\n\t\t\tfor ( BluetoothDevice d : mBluetoothGatt.getConnectedDevices() ) {\n\t\t\t\tmBluetoothGatt.cancelConnection(d);\n\t\t\t}\n\t\t\tmBluetoothGatt = null;\n\t\t}\n\t};\n\n\tpublic BroadcomBle(BleService service) {\n\t\tmService = service;\n\t\tmBtAdapter = BluetoothAdapter.getDefaultAdapter();\n\t\tif (mBtAdapter == null) {\n\t\t\tmService.bleNoBtAdapter();\n\t\t\treturn;\n\t\t}\n\t\tBluetoothGattAdapter.getProfileProxy(mService, mProfileServiceListener,\n\t\t\t\tBluetoothGattAdapter.GATT);\n\t}\n\n\t@Override\n\tpublic void startScan() {\n\t\tif (mScanning) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (mBluetoothGatt == null) {\n\t\t\tmScanning = false;\n\t\t\treturn;\n\t\t}\n\n\t\tmScanning = true;\n\t\tmBluetoothGatt.startScan();\n\t}\n\n\t@Override\n\tpublic void stopScan() {\n\t\tif (!mScanning || mBluetoothGatt == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tmScanning = false;\n\t\tmBluetoothGatt.stopScan();\n\t}\n\n\t@Override\n\tpublic boolean adapterEnabled() {\n\t\tif (mBtAdapter != null) {\n\t\t\treturn mBtAdapter.isEnabled();\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean connect(String address) {\n\t\tBluetoothDevice device = mBtAdapter.getRemoteDevice(address);\n\t\treturn mBluetoothGatt.connect(device, false);\n\t}\n\n\t@Override\n\tpublic void disconnect(String address) {\n\t\tBluetoothDevice device = mBtAdapter.getRemoteDevice(address);\n\t\tmBluetoothGatt.cancelConnection(device);\n\t}\n\n\t@Override\n\tpublic ArrayList<BleGattService> getServices(String address) {\n\t\tArrayList<BleGattService> list = new ArrayList<BleGattService>();\n\t\tBluetoothDevice device = mBtAdapter.getRemoteDevice(address);\n\t\tList<BluetoothGattService> services = mBluetoothGatt\n\t\t\t\t.getServices(device);\n\t\tfor (BluetoothGattService s : services) {\n\t\t\tlist.add(new BleGattService(s));\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic boolean requestReadCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tmService.addBleRequest(new BleRequest(RequestType.READ_CHARACTERISTIC,\n\t\t\t\taddress, characteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean discoverServices(String address) {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean readCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tif (characteristic.getGattCharacteristicB() != null) {\n\t\t\treturn mBluetoothGatt.readCharacteristic(characteristic\n\t\t\t\t\t.getGattCharacteristicB());\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic BleGattService getService(String address, UUID uuid) {\n\t\tBluetoothGattService service = mBluetoothGatt.getService(\n\t\t\t\tmBtAdapter.getRemoteDevice(address), uuid);\n\t\tif (service == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn new BleGattService(service);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean requestCharacteristicNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_NOTIFICATION, address,\n\t\t\t\tcharacteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean characteristicNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBleRequest request = mService.getCurrentRequest();\n\t\tBluetoothGattCharacteristic b = characteristic.getGattCharacteristicB();\n\n\t\tboolean enable = true;\n\t\tif (request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {\n\t\t\tenable = false;\n\t\t}\n\t\tif (!mBluetoothGatt.setCharacteristicNotification(b, enable)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tBluetoothGattDescriptor descriptor = b\n\t\t\t\t.getDescriptor(BleService.DESC_CCC);\n\t\tif (descriptor == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn mBluetoothGatt.readDescriptor(descriptor);\n\t}\n\n\t@Override\n\tpublic boolean requestWriteCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic, String remark) {\n\t\tmService.addBleRequest(new BleRequest(RequestType.WRITE_CHARACTERISTIC,\n\t\t\t\taddress, characteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean writeCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\treturn mBluetoothGatt.writeCharacteristic(characteristic\n\t\t\t\t.getGattCharacteristicB());\n\t}\n\n\t@Override\n\tpublic boolean requestConnect(String address) {\n\t\tif (mAddress != null) {\n\t\t\treturn false;\n\t\t}\n\t\tmService.addBleRequest(new BleRequest(RequestType.CONNECT_GATT, address));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getBTAdapterMacAddr() {\n\t\tif (mBtAdapter != null) {\n\t\t\treturn mBtAdapter.getAddress();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean requestIndication(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_INDICATION, address, characteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean requestStopNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_STOP_NOTIFICATION, address,\n\t\t\t\tcharacteristic));\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/IBle.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\nimport java.util.ArrayList;\nimport java.util.UUID;\n\npublic interface IBle {\n\n\tpublic String getBTAdapterMacAddr();\n\n\t/**\n\t * Will receive broadcast {@link BleService#BLE_DEVICE_FOUND} if device\n\t * found.\n\t */\n\tpublic void startScan();\n\n\t/**\n\t * Stop BLE scan.\n\t */\n\tpublic void stopScan();\n\n\t/**\n\t * Check if bluetooth adapter is enabled.\n\t * \n\t * @return enabled\n\t */\n\tpublic boolean adapterEnabled();\n\n\t/**\n\t * Disconnect BLE device. Will receive\n\t * {@link BleService#BLE_GATT_DISCONNECTED} broadcast if device\n\t * disconnected.\n\t * \n\t * @param address\n\t *            BLE device address.\n\t */\n\tpublic void disconnect(String address);\n\n\t/**\n\t * Discover BLE services. Will receive\n\t * {@link BleService#BLE_SERVICE_DISCOVERED} broadcast if device service\n\t * discovered.\n\t * \n\t * @param address\n\t * @return\n\t */\n\tpublic boolean discoverServices(String address);\n\n\t/**\n\t * Get discovered services for BLE device. Call this function after\n\t * {@link BleService#BLE_SERVICE_DISCOVERED} broadcast is received.\n\t * \n\t * @param address\n\t * @return List of {@link BleGattService}\n\t */\n\tpublic ArrayList<BleGattService> getServices(String address);\n\n\t/**\n\t * Get discovered service by uuid. Call this function after\n\t * {@link BleService#BLE_SERVICE_DISCOVERED} broadcast is received.\n\t * \n\t * @param address\n\t * @param uuid\n\t * @return {@link BleGattService}\n\t */\n\tpublic BleGattService getService(String address, UUID uuid);\n\n\t/**\n\t * Request to connect a BLE device by address. Will receive\n\t * {@link BleService#BLE_GATT_CONNECTED} broadcast if device connected.\n\t * \n\t * @param address\n\t * @return if request be inserted into queue successfully.\n\t */\n\tpublic boolean requestConnect(String address);\n\n\t/**\n\t * Request to read characteristic. Will receive\n\t * {@link BleService#BLE_CHARACTERISTIC_READ} broadcast if characteristic\n\t * read.\n\t * \n\t * @param address\n\t * @param characteristic\n\t *            Get characteristic from {@link BleGattService}\n\t * @return if request be inserted into queue successfully.\n\t */\n\tpublic boolean requestReadCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic);\n\n\t/**\n\t * Request characteristic notification. Will receive\n\t * {@link BleService#BLE_CHARACTERISTIC_NOTIFICATION} broadcast if\n\t * notification set OK. When the characteristic's value changed,\n\t * {@link BleService#BLE_CHARACTERISTIC_CHANGED} broadcast will be received\n\t * also.\n\t * \n\t * @param address\n\t * @param characteristic\n\t *            Get characteristic from {@link BleGattService}\n\t * @return if request be inserted into queue successfully.\n\t */\n\tpublic boolean requestCharacteristicNotification(String address,\n\t\t\tBleGattCharacteristic characteristic);\n\n\tpublic boolean requestStopNotification(String address,\n\t\t\tBleGattCharacteristic characteristic);\n\n\t/**\n\t * Request characteristic indication. Will receive\n\t * {@link BleService#BLE_CHARACTERISTIC_INDICATION} broadcast if indication\n\t * set OK. When the characteristic's value changed,\n\t * {@link BleService#BLE_CHARACTERISTIC_CHANGED} broadcast will be received\n\t * also.\n\t * \n\t * @param address\n\t * @param characteristic\n\t *            Get characteristic from {@link BleGattService}\n\t * @return if request be inserted into queue successfully.\n\t */\n\tpublic boolean requestIndication(String address,\n\t\t\tBleGattCharacteristic characteristic);\n\n\t/**\n\t * Request write characteristic value. Will receive\n\t * {@link BleService#BLE_CHARACTERISTIC_WRITE} broadcast if characteristic\n\t * value be written.\n\t * \n\t * @param address\n\t * @param characteristic\n\t *            Get characteristic from {@link BleGattService}\n\t * @param remark\n\t *            For debug purpose.\n\t * @return if request be inserted into queue successfully.\n\t */\n\tpublic boolean requestWriteCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic, String remark);\n}\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/IBleRequestHandler.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\npublic interface IBleRequestHandler {\n\n\tpublic boolean connect(String address);\n\n\t/**\n\t * @param address\n\t * @param characteristic\n\t * @return\n\t */\n\tpublic boolean readCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic);\n\n\t/**\n\t * @param address\n\t * @param characteristic\n\t * @return\n\t */\n\tpublic boolean characteristicNotification(String address,\n\t\t\tBleGattCharacteristic characteristic);\n\n\t/**\n\t * @param address\n\t * @param characteristic\n\t * @return\n\t */\n\tpublic boolean writeCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic);\n}\n"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/SamsungBle.java",
    "content": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.xtremeprog.sdk.ble;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.UUID;\n\nimport android.bluetooth.BluetoothAdapter;\nimport android.bluetooth.BluetoothDevice;\nimport android.bluetooth.BluetoothProfile;\nimport android.util.Log;\n\nimport com.samsung.android.sdk.bt.gatt.BluetoothGatt;\nimport com.samsung.android.sdk.bt.gatt.BluetoothGattAdapter;\nimport com.samsung.android.sdk.bt.gatt.BluetoothGattCallback;\nimport com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic;\nimport com.samsung.android.sdk.bt.gatt.BluetoothGattDescriptor;\nimport com.samsung.android.sdk.bt.gatt.BluetoothGattService;\nimport com.xtremeprog.sdk.ble.BleRequest.RequestType;\n\npublic class SamsungBle implements IBle, IBleRequestHandler {\n\n\tprotected static final String TAG = \"blelib\";\n\n\tprivate BluetoothAdapter mBtAdapter;\n\tprivate BleService mService;\n\tprivate BluetoothGatt mBluetoothGatt;\n\tprivate boolean mScanning;\n\n\tprivate final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() {\n\t\t@Override\n\t\tpublic void onAppRegistered(int status) {\n\t\t}\n\n\t\t@Override\n\t\tpublic void onScanResult(BluetoothDevice device, int rssi,\n\t\t\t\tbyte[] scanRecord) {\n\t\t\tmService.bleDeviceFound(device, rssi, scanRecord,\n\t\t\t\t\tBleService.DEVICE_SOURCE_SCAN);\n\t\t}\n\n\t\t@Override\n\t\tpublic void onConnectionStateChange(BluetoothDevice device, int status,\n\t\t\t\tint newState) {\n\t\t\tif (mBluetoothGatt == null) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tdisconnect(device.getAddress());\n\t\t\t\tmService.bleGattDisConnected(device.getAddress());\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (newState == BluetoothProfile.STATE_CONNECTED) {\n\t\t\t\tmService.bleGattConnected(device);\n\t\t\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\t\t\tRequestType.DISCOVER_SERVICE, device.getAddress()));\n\t\t\t} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {\n\t\t\t\tmService.bleGattDisConnected(device.getAddress());\n\t\t\t\tdisconnect(device.getAddress());\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void onServicesDiscovered(BluetoothDevice device, int status) {\n\t\t\tString address = device.getAddress();\n\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tdisconnect(address);\n\t\t\t\tmService.bleGattDisConnected(address);\n\t\t\t\tmService.requestProcessed(address,\n\t\t\t\t\t\tRequestType.DISCOVER_SERVICE, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmService.bleServiceDiscovered(device.getAddress());\n\t\t}\n\n\t\t@Override\n\t\tpublic void onCharacteristicRead(\n\t\t\t\tBluetoothGattCharacteristic characteristic, int status) {\n\t\t\tBleRequest request = mService.getCurrentRequest();\n\t\t\tString address = request.address;\n\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tmService.requestProcessed(address,\n\t\t\t\t\t\tRequestType.READ_CHARACTERISTIC, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmService.bleCharacteristicRead(address, characteristic.getUuid()\n\t\t\t\t\t.toString(), status, characteristic.getValue());\n\t\t}\n\n\t\t@Override\n\t\tpublic void onCharacteristicChanged(\n\t\t\t\tBluetoothGattCharacteristic characteristic) {\n\t\t\tLog.d(TAG, \"onCharacteristicChanged\");\n\t\t\tString address = mService.getNotificationAddress();\n\t\t\tmService.bleCharacteristicChanged(address, characteristic.getUuid()\n\t\t\t\t\t.toString(), characteristic.getValue());\n\t\t}\n\n\t\t@Override\n\t\tpublic void onCharacteristicWrite(\n\t\t\t\tBluetoothGattCharacteristic characteristic, int status) {\n\t\t\tBleRequest request = mService.getCurrentRequest();\n\t\t\tString address = request.address;\n\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\tmService.requestProcessed(address,\n\t\t\t\t\t\tRequestType.WRITE_CHARACTERISTIC, false);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmService.bleCharacteristicWrite(address, characteristic.getUuid()\n\t\t\t\t\t.toString(), status);\n\t\t};\n\n\t\t@Override\n\t\tpublic void onDescriptorRead(BluetoothGattDescriptor descriptor,\n\t\t\t\tint status) {\n\t\t\tBleRequest request = mService.getCurrentRequest();\n\t\t\tString address = request.address;\n\t\t\tbyte[] value = descriptor.getValue();\n\t\t\tbyte[] val_set = null;\n\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {\n\t\t\t\tval_set = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;\n\t\t\t} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {\n\t\t\t\tval_set = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;\n\t\t\t} else {\n\t\t\t\tval_set = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;\n\t\t\t}\n\n\t\t\tif (Arrays.equals(value, val_set)) {\n\t\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), true,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {\n\t\t\t\t\tmService.bleCharacteristicIndication(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), status);\n\t\t\t\t} else {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), false,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!descriptor.setValue(val_set)) {\n\t\t\t\tmService.requestProcessed(address, request.type, false);\n\t\t\t}\n\n\t\t\tmBluetoothGatt.writeDescriptor(descriptor);\n\t\t};\n\n\t\t@Override\n\t\tpublic void onDescriptorWrite(BluetoothGattDescriptor descriptor,\n\t\t\t\tint status) {\n\t\t\tBleRequest request = mService.getCurrentRequest();\n\t\t\tString address = request.address;\n\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION\n\t\t\t\t\t|| request.type == RequestType.CHARACTERISTIC_INDICATION\n\t\t\t\t\t|| request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {\n\t\t\t\tif (status != BluetoothGatt.GATT_SUCCESS) {\n\t\t\t\t\tmService.requestProcessed(address, request.type, false);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), true,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {\n\t\t\t\t\tmService.bleCharacteristicIndication(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), status);\n\t\t\t\t} else {\n\t\t\t\t\tmService.bleCharacteristicNotification(address, descriptor\n\t\t\t\t\t\t\t.getCharacteristic().getUuid().toString(), false,\n\t\t\t\t\t\t\tstatus);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t};\n\t};\n\n\tprivate final BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() {\n\t\t@Override\n\t\tpublic void onServiceConnected(int profile, BluetoothProfile proxy) {\n\t\t\tmBluetoothGatt = (BluetoothGatt) proxy;\n\t\t\tmBluetoothGatt.registerApp(mGattCallbacks);\n\t\t}\n\n\t\t@Override\n\t\tpublic void onServiceDisconnected(int profile) {\n\t\t\tmBluetoothGatt = null;\n\t\t}\n\t};\n\n\tpublic SamsungBle(BleService service) {\n\t\tmService = service;\n\t\tmBtAdapter = BluetoothAdapter.getDefaultAdapter();\n\t\tif (mBtAdapter == null) {\n\t\t\tmService.bleNoBtAdapter();\n\t\t\treturn;\n\t\t}\n\t\tBluetoothGattAdapter.getProfileProxy(mService, mProfileServiceListener,\n\t\t\t\tBluetoothGattAdapter.GATT);\n\t}\n\n\t@Override\n\tpublic void startScan() {\n\t\tif (mScanning) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (mBluetoothGatt == null) {\n\t\t\tmScanning = false;\n\t\t\treturn;\n\t\t}\n\n\t\tmScanning = true;\n\t\tmBluetoothGatt.startScan();\n\t}\n\n\t@Override\n\tpublic void stopScan() {\n\t\tif (!mScanning || mBluetoothGatt == null) {\n\t\t\treturn;\n\t\t}\n\n\t\tmScanning = false;\n\t\tmBluetoothGatt.stopScan();\n\t}\n\n\t@Override\n\tpublic boolean adapterEnabled() {\n\t\tif (mBtAdapter != null) {\n\t\t\treturn mBtAdapter.isEnabled();\n\t\t}\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic boolean connect(String address) {\n\t\tBluetoothDevice device = mBtAdapter.getRemoteDevice(address);\n\t\treturn mBluetoothGatt.connect(device, false);\n\t}\n\n\t@Override\n\tpublic void disconnect(String address) {\n\t\tBluetoothDevice device = mBtAdapter.getRemoteDevice(address);\n\t\tmBluetoothGatt.cancelConnection(device);\n\t}\n\n\t@Override\n\tpublic ArrayList<BleGattService> getServices(String address) {\n\t\tArrayList<BleGattService> list = new ArrayList<BleGattService>();\n\t\tBluetoothDevice device = mBtAdapter.getRemoteDevice(address);\n\t\tList<BluetoothGattService> services = mBluetoothGatt\n\t\t\t\t.getServices(device);\n\t\tfor (BluetoothGattService s : services) {\n\t\t\tlist.add(new BleGattService(s));\n\t\t}\n\t\treturn list;\n\t}\n\n\t@Override\n\tpublic boolean requestReadCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tmService.addBleRequest(new BleRequest(RequestType.READ_CHARACTERISTIC,\n\t\t\t\taddress, characteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean discoverServices(String address) {\n\t\treturn mBluetoothGatt.discoverServices(mBtAdapter\n\t\t\t\t.getRemoteDevice(address));\n\t}\n\n\t@Override\n\tpublic boolean readCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\treturn mBluetoothGatt.readCharacteristic(characteristic\n\t\t\t\t.getGattCharacteristicS());\n\t}\n\n\t@Override\n\tpublic BleGattService getService(String address, UUID uuid) {\n\t\tBluetoothGattService service = mBluetoothGatt.getService(\n\t\t\t\tmBtAdapter.getRemoteDevice(address), uuid);\n\t\tif (service == null) {\n\t\t\treturn null;\n\t\t} else {\n\t\t\treturn new BleGattService(service);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean requestCharacteristicNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_NOTIFICATION, address,\n\t\t\t\tcharacteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean characteristicNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tBluetoothGattCharacteristic c = characteristic.getGattCharacteristicS();\n\n\t\tif (!mBluetoothGatt.setCharacteristicNotification(c, true)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tBluetoothGattDescriptor descriptor = c\n\t\t\t\t.getDescriptor(BleService.DESC_CCC);\n\t\tif (descriptor == null) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn mBluetoothGatt.readDescriptor(descriptor);\n\t}\n\n\t@Override\n\tpublic boolean requestWriteCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic, String remark) {\n\t\tmService.addBleRequest(new BleRequest(RequestType.WRITE_CHARACTERISTIC,\n\t\t\t\taddress, characteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean writeCharacteristic(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\treturn mBluetoothGatt.writeCharacteristic(characteristic\n\t\t\t\t.getGattCharacteristicS());\n\t}\n\n\t@Override\n\tpublic boolean requestConnect(String address) {\n\t\tmService.addBleRequest(new BleRequest(RequestType.CONNECT_GATT, address));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic String getBTAdapterMacAddr() {\n\t\tif (mBtAdapter != null) {\n\t\t\treturn mBtAdapter.getAddress();\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic boolean requestIndication(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_INDICATION, address, characteristic));\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean requestStopNotification(String address,\n\t\t\tBleGattCharacteristic characteristic) {\n\t\tmService.addBleRequest(new BleRequest(\n\t\t\t\tRequestType.CHARACTERISTIC_STOP_NOTIFICATION, address,\n\t\t\t\tcharacteristic));\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "BluetoothLeGatt/.classpath",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<classpath>\n\t<classpathentry kind=\"con\" path=\"com.android.ide.eclipse.adt.ANDROID_FRAMEWORK\"/>\n\t<classpathentry exported=\"true\" kind=\"con\" path=\"com.android.ide.eclipse.adt.LIBRARIES\"/>\n\t<classpathentry exported=\"true\" kind=\"con\" path=\"com.android.ide.eclipse.adt.DEPENDENCIES\"/>\n\t<classpathentry kind=\"src\" path=\"src\"/>\n\t<classpathentry kind=\"src\" path=\"gen\"/>\n\t<classpathentry kind=\"output\" path=\"bin/classes\"/>\n</classpath>\n"
  },
  {
    "path": "BluetoothLeGatt/.project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>DeviceScanActivity</name>\n\t<comment></comment>\n\t<projects>\n\t</projects>\n\t<buildSpec>\n\t\t<buildCommand>\n\t\t\t<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t\t<buildCommand>\n\t\t\t<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t\t<buildCommand>\n\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t\t<buildCommand>\n\t\t\t<name>com.android.ide.eclipse.adt.ApkBuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t</buildSpec>\n\t<natures>\n\t\t<nature>com.android.ide.eclipse.adt.AndroidNature</nature>\n\t\t<nature>org.eclipse.jdt.core.javanature</nature>\n\t</natures>\n</projectDescription>\n"
  },
  {
    "path": "BluetoothLeGatt/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\nCopyright (C) 2013 The Android Open Source Project\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n-->\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.example.bluetooth.le\"\n    android:versionCode=\"1\"\n    android:versionName=\"1.0\" >\n\n    <uses-sdk\n        android:minSdkVersion=\"17\"\n        android:targetSdkVersion=\"17\" />\n    <!--\n    Declare this required feature if you want to make the app available to BLE-capable\n    devices only.  If you want to make your app available to devices that don't support BLE,\n    you should omit this in the manifest.  Instead, determine BLE capability by using\n    PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE)\n    -->\n    <uses-feature\n        android:name=\"android.hardware.bluetooth_le\"\n        android:required=\"true\" />\n\n    <uses-permission android:name=\"android.permission.BLUETOOTH\" />\n    <uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\" />\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n\n    <application\n        android:name=\"com.example.bluetooth.le.BleApplication\"\n        android:icon=\"@drawable/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@android:style/Theme.Holo.Light\" >\n        <activity\n            android:name=\"com.example.bluetooth.le.DeviceScanActivity\"\n            android:label=\"@string/app_name\" >\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity android:name=\"com.example.bluetooth.le.DeviceControlActivity\" >\n        </activity>\n\n        <service\n            android:name=\"com.xtremeprog.sdk.ble.BleService\"\n            android:enabled=\"true\" />\n\n        <activity\n            android:name=\"com.example.bluetooth.le.CharacteristicActivity\"\n            android:label=\"@string/title_activity_characteristic\" >\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "BluetoothLeGatt/project.properties",
    "content": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# This file must be checked in Version Control Systems.\n#\n# To customize properties used by the Ant build system edit\n# \"ant.properties\", and override values to adapt the script to your\n# project structure.\n#\n# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):\n#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt\n\n# Project target.\ntarget=android-17\nandroid.library.reference.1=../BleLibrary\n"
  },
  {
    "path": "BluetoothLeGatt/res/layout/actionbar_indeterminate_progress.xml",
    "content": "<!--\n  Copyright 2013 Google Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n             android:layout_height=\"wrap_content\"\n             android:layout_width=\"56dp\"\n             android:minWidth=\"56dp\">\n    <ProgressBar android:layout_width=\"32dp\"\n                 android:layout_height=\"32dp\"\n                 android:layout_gravity=\"center\"/>\n</FrameLayout>\n"
  },
  {
    "path": "BluetoothLeGatt/res/layout/activity_characteristic.xml",
    "content": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    android:padding=\"10dp\"\n    tools:context=\"com.example.bluetooth.le.CharacteristicActivity\" >\n\n    <TextView\n        android:id=\"@+id/tv_name\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:textSize=\"18sp\" />\n\n    <TextView\n        android:id=\"@+id/tv_uuid\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:textSize=\"18sp\" />\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\" >\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"ASCII: \"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_ascii\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textSize=\"18sp\" />\n    </LinearLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\" >\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"HEX: \"\n            android:textSize=\"18sp\" />\n\n        <TextView\n            android:id=\"@+id/tv_hex\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:textSize=\"18sp\" />\n    </LinearLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\" >\n\n        <Button\n            android:id=\"@+id/btn_read\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Read\"\n            android:visibility=\"gone\" />\n\n        <Button\n            android:id=\"@+id/btn_notify\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Start Notify\"\n            android:visibility=\"gone\" />\n\n        <Button\n            android:id=\"@+id/btn_indicate\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Indicate\"\n            android:visibility=\"gone\" />\n    </LinearLayout>\n\n    <LinearLayout\n        android:id=\"@+id/ll_write\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\"\n        android:visibility=\"gone\" >\n\n        <Button\n            android:id=\"@+id/btn_write\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"Write\" />\n\n        <EditText\n            android:id=\"@+id/et_hex\"\n            android:layout_width=\"fill_parent\"\n            android:layout_height=\"wrap_content\"\n            android:hint=\"0x0A30BC\" />\n    </LinearLayout>\n\n</LinearLayout>"
  },
  {
    "path": "BluetoothLeGatt/res/layout/gatt_services_characteristics.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n     Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_margin=\"10dp\"\n    android:orientation=\"vertical\" >\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"10dp\"\n        android:orientation=\"horizontal\" >\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/label_device_address\"\n            android:textSize=\"18sp\" />\n\n        <Space\n            android:layout_width=\"5dp\"\n            android:layout_height=\"wrap_content\" />\n\n        <TextView\n            android:id=\"@+id/device_address\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:textSize=\"18sp\" />\n    </LinearLayout>\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"10dp\"\n        android:orientation=\"horizontal\" >\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/label_state\"\n            android:textSize=\"18sp\" />\n\n        <Space\n            android:layout_width=\"5dp\"\n            android:layout_height=\"wrap_content\" />\n\n        <TextView\n            android:id=\"@+id/connection_state\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/disconnected\"\n            android:textSize=\"18sp\" />\n    </LinearLayout>\n\n    <ExpandableListView\n        android:id=\"@+id/gatt_services_list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\" />\n\n</LinearLayout>"
  },
  {
    "path": "BluetoothLeGatt/res/layout/listitem_device.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n              android:orientation=\"vertical\"\n              android:layout_width=\"match_parent\"\n              android:layout_height=\"wrap_content\">\n    <TextView android:id=\"@+id/device_name\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:textSize=\"24dp\"/>\n    <TextView android:id=\"@+id/device_address\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:textSize=\"12dp\"/>\n</LinearLayout>"
  },
  {
    "path": "BluetoothLeGatt/res/menu/characteristic.xml",
    "content": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:context=\"com.example.bluetooth.le.CharacteristicActivity\" >\n\n    <item\n        android:id=\"@+id/action_settings\"\n        android:orderInCategory=\"100\"\n        android:showAsAction=\"never\"\n        android:title=\"@string/action_settings\"/>\n\n</menu>\n"
  },
  {
    "path": "BluetoothLeGatt/res/menu/gatt_services.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:id=\"@+id/menu_refresh\"\n          android:checkable=\"false\"\n          android:orderInCategory=\"1\"\n          android:showAsAction=\"ifRoom\"/>\n    <item android:id=\"@+id/menu_connect\"\n          android:title=\"@string/menu_connect\"\n          android:orderInCategory=\"100\"\n          android:showAsAction=\"ifRoom|withText\"/>\n    <item android:id=\"@+id/menu_disconnect\"\n          android:title=\"@string/menu_disconnect\"\n          android:orderInCategory=\"101\"\n          android:showAsAction=\"ifRoom|withText\"/>\n</menu>\n"
  },
  {
    "path": "BluetoothLeGatt/res/menu/main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:id=\"@+id/menu_refresh\"\n          android:checkable=\"false\"\n          android:orderInCategory=\"1\"\n          android:showAsAction=\"ifRoom\"/>\n    <item android:id=\"@+id/menu_scan\"\n          android:title=\"@string/menu_scan\"\n          android:orderInCategory=\"100\"\n          android:showAsAction=\"ifRoom|withText\"/>\n    <item android:id=\"@+id/menu_stop\"\n          android:title=\"@string/menu_stop\"\n          android:orderInCategory=\"101\"\n          android:showAsAction=\"ifRoom|withText\"/>\n</menu>\n"
  },
  {
    "path": "BluetoothLeGatt/res/values/dimens.xml",
    "content": "<resources>\n\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n\n</resources>\n"
  },
  {
    "path": "BluetoothLeGatt/res/values/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n     Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under the Apache License, Version 2.0 (the \"License\");\n     you may not use this file except in compliance with the License.\n     You may obtain a copy of the License at\n\n          http://www.apache.org/licenses/LICENSE-2.0\n\n     Unless required by applicable law or agreed to in writing, software\n     distributed under the License is distributed on an \"AS IS\" BASIS,\n     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n     See the License for the specific language governing permissions and\n     limitations under the License.\n-->\n<resources>\n\n    <string name=\"app_name\">BLE Sample</string>\n    <string name=\"ble_not_supported\">BLE is not supported</string>\n    <string name=\"label_data\">Data:</string>\n    <string name=\"label_device_address\">Device address:</string>\n    <string name=\"label_state\">State:</string>\n    <string name=\"no_data\">No data</string>\n    <string name=\"connected\">Connected</string>\n    <string name=\"disconnected\">Disconnected</string>\n    <string name=\"title_devices\">BLE Device Scan</string>\n    <string name=\"error_bluetooth_not_supported\">Bluetooth not supported.</string>\n    <string name=\"unknown_device\">Unknown device</string>\n    <string name=\"unknown_characteristic\">Unknown characteristic</string>\n    <string name=\"unknown_service\">Unknown service</string>\n\n    <!-- Menu items -->\n    <string name=\"menu_connect\">Connect</string>\n    <string name=\"menu_disconnect\">Disconnect</string>\n    <string name=\"menu_scan\">Scan</string>\n    <string name=\"menu_stop\">Stop</string>\n    <string name=\"title_activity_characteristic\">CharacteristicActivity</string>\n    <string name=\"hello_world\">Hello world!</string>\n    <string name=\"action_settings\">Settings</string>\n\n</resources>\n"
  },
  {
    "path": "BluetoothLeGatt/res/values-w820dp/dimens.xml",
    "content": "<resources>\n\n    <!--\n         Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively).\n    -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n\n</resources>\n"
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/BleApplication.java",
    "content": "package com.example.bluetooth.le;\n\nimport android.app.Application;\nimport android.content.ComponentName;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.ServiceConnection;\nimport android.os.IBinder;\n\nimport com.xtremeprog.sdk.ble.BleService;\nimport com.xtremeprog.sdk.ble.IBle;\n\npublic class BleApplication extends Application {\n\n\tprivate BleService mService;\n\tprivate IBle mBle;\n\n\tprivate final ServiceConnection mServiceConnection = new ServiceConnection() {\n\t\t@Override\n\t\tpublic void onServiceConnected(ComponentName className,\n\t\t\t\tIBinder rawBinder) {\n\t\t\tmService = ((BleService.LocalBinder) rawBinder).getService();\n\t\t\tmBle = mService.getBle();\n\t\t\tif (mBle != null && !mBle.adapterEnabled()) {\n\t\t\t\t// TODO: enalbe adapter\n\t\t\t}\n\t\t}\n\n\t\t@Override\n\t\tpublic void onServiceDisconnected(ComponentName classname) {\n\t\t\tmService = null;\n\t\t}\n\t};\n\n\t@Override\n\tpublic void onCreate() {\n\t\tsuper.onCreate();\n\n\t\tIntent bindIntent = new Intent(this, BleService.class);\n\t\tbindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);\n\t}\n\t\n\tpublic IBle getIBle() {\n\t\treturn mBle;\n\t}\n}\n"
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/CharacteristicActivity.java",
    "content": "package com.example.bluetooth.le;\n\nimport java.util.UUID;\n\nimport org.apache.commons.codec.DecoderException;\nimport org.apache.commons.codec.binary.Hex;\n\nimport android.app.Activity;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.Button;\nimport android.widget.EditText;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.xtremeprog.sdk.ble.BleGattCharacteristic;\nimport com.xtremeprog.sdk.ble.BleService;\nimport com.xtremeprog.sdk.ble.IBle;\n\npublic class CharacteristicActivity extends Activity {\n\n\tprivate String mDeviceAddress;\n\tprivate IBle mBle;\n\tprivate BleGattCharacteristic mCharacteristic;\n\n\tprivate View.OnClickListener onClickListener = new View.OnClickListener() {\n\n\t\t@Override\n\t\tpublic void onClick(View v) {\n\t\t\tif (v.getId() == R.id.btn_read) {\n\t\t\t\tmBle.requestReadCharacteristic(mDeviceAddress, mCharacteristic);\n\t\t\t} else if (v.getId() == R.id.btn_notify) {\n\t\t\t\tif (mNotifyStarted) {\n\t\t\t\t\tmBle.requestStopNotification(mDeviceAddress,\n\t\t\t\t\t\t\tmCharacteristic);\n\t\t\t\t} else {\n\t\t\t\t\tmBle.requestCharacteristicNotification(mDeviceAddress,\n\t\t\t\t\t\t\tmCharacteristic);\n\t\t\t\t}\n\t\t\t} else if (v.getId() == R.id.btn_indicate) {\n\t\t\t\tmBle.requestIndication(mDeviceAddress, mCharacteristic);\n\t\t\t} else if (v.getId() == R.id.btn_write) {\n\t\t\t\tString val = et_hex.getText().toString();\n\t\t\t\ttry {\n\t\t\t\t\tbyte[] data = Hex.decodeHex(val.toCharArray());\n\t\t\t\t\tmCharacteristic.setValue(data);\n\t\t\t\t\tmBle.requestWriteCharacteristic(mDeviceAddress,\n\t\t\t\t\t\t\tmCharacteristic, \"\");\n\t\t\t\t} catch (DecoderException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate final BroadcastReceiver mBleReceiver = new BroadcastReceiver() {\n\t\t@Override\n\t\tpublic void onReceive(Context context, Intent intent) {\n\t\t\tBundle extras = intent.getExtras();\n\t\t\tif (!mDeviceAddress.equals(extras.getString(BleService.EXTRA_ADDR))) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tString uuid = extras.getString(BleService.EXTRA_UUID);\n\t\t\tif (uuid != null\n\t\t\t\t\t&& !mCharacteristic.getUuid().toString().equals(uuid)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tString action = intent.getAction();\n\t\t\tif (BleService.BLE_GATT_DISCONNECTED.equals(action)) {\n\t\t\t\tToast.makeText(CharacteristicActivity.this,\n\t\t\t\t\t\t\"Device disconnected...\", Toast.LENGTH_SHORT).show();\n\t\t\t\tfinish();\n\t\t\t} else if (BleService.BLE_CHARACTERISTIC_READ.equals(action)\n\t\t\t\t\t|| BleService.BLE_CHARACTERISTIC_CHANGED.equals(action)) {\n\t\t\t\tbyte[] val = extras.getByteArray(BleService.EXTRA_VALUE);\n\t\t\t\ttv_ascii.setText(new String(val));\n\t\t\t\ttv_hex.setText(\"0x\" + new String(Hex.encodeHex(val)));\n\t\t\t} else if (BleService.BLE_CHARACTERISTIC_NOTIFICATION\n\t\t\t\t\t.equals(action)) {\n\t\t\t\tToast.makeText(CharacteristicActivity.this,\n\t\t\t\t\t\t\"Notification state changed!\", Toast.LENGTH_SHORT)\n\t\t\t\t\t\t.show();\n\t\t\t\tmNotifyStarted = extras.getBoolean(BleService.EXTRA_VALUE);\n\t\t\t\tif (mNotifyStarted) {\n\t\t\t\t\tbtn_notify.setText(\"Stop Notify\");\n\t\t\t\t} else {\n\t\t\t\t\tbtn_notify.setText(\"Start Notify\");\n\t\t\t\t}\n\t\t\t} else if (BleService.BLE_CHARACTERISTIC_INDICATION.equals(action)) {\n\t\t\t\tToast.makeText(CharacteristicActivity.this,\n\t\t\t\t\t\t\"Indication state changed!\", Toast.LENGTH_SHORT).show();\n\t\t\t} else if (BleService.BLE_CHARACTERISTIC_WRITE.equals(action)) {\n\t\t\t\tToast.makeText(CharacteristicActivity.this, \"Write success!\",\n\t\t\t\t\t\tToast.LENGTH_SHORT).show();\n\t\t\t}\n\t\t}\n\t};\n\tprivate TextView tv_ascii;\n\tprivate TextView tv_hex;\n\tprivate EditText et_hex;\n\tprivate boolean mNotifyStarted;\n\tprivate Button btn_notify;\n\n\t@Override\n\tprotected void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.activity_characteristic);\n\n\t\tmDeviceAddress = getIntent().getStringExtra(\"address\");\n\t\tString service = getIntent().getStringExtra(\"service\");\n\t\tString characteristic = getIntent().getStringExtra(\"characteristic\");\n\t\tBleApplication app = (BleApplication) getApplication();\n\t\tmBle = app.getIBle();\n\t\tmCharacteristic = mBle.getService(mDeviceAddress,\n\t\t\t\tUUID.fromString(service)).getCharacteristic(\n\t\t\t\tUUID.fromString(characteristic));\n\t\tmNotifyStarted = false;\n\n\t\tTextView tv_name = (TextView) findViewById(R.id.tv_name);\n\t\tTextView tv_uuid = (TextView) findViewById(R.id.tv_uuid);\n\t\ttv_ascii = (TextView) findViewById(R.id.tv_ascii);\n\t\ttv_hex = (TextView) findViewById(R.id.tv_hex);\n\n\t\ttv_name.setText(Utils.BLE_CHARACTERISTICS.containsKey(characteristic) ? Utils.BLE_CHARACTERISTICS\n\t\t\t\t.get(characteristic) : \"unknown characteristic\");\n\t\ttv_uuid.setText(mCharacteristic.getUuid().toString());\n\n\t\tView btn_read = findViewById(R.id.btn_read);\n\t\tbtn_notify = (Button) findViewById(R.id.btn_notify);\n\t\tView btn_indicate = findViewById(R.id.btn_indicate);\n\t\tView ll_write = findViewById(R.id.ll_write);\n\t\tView btn_write = findViewById(R.id.btn_write);\n\t\tet_hex = (EditText) findViewById(R.id.et_hex);\n\t\tbtn_read.setOnClickListener(onClickListener);\n\t\tbtn_notify.setOnClickListener(onClickListener);\n\t\tbtn_indicate.setOnClickListener(onClickListener);\n\t\tbtn_write.setOnClickListener(onClickListener);\n\n\t\tfinal int charaProp = mCharacteristic.getProperties();\n\t\tif ((charaProp & BleGattCharacteristic.PROPERTY_READ) > 0) {\n\t\t\tbtn_read.setVisibility(View.VISIBLE);\n\t\t}\n\t\tif ((charaProp & BleGattCharacteristic.PROPERTY_NOTIFY) > 0) {\n\t\t\tbtn_notify.setVisibility(View.VISIBLE);\n\t\t}\n\t\tif ((charaProp & BleGattCharacteristic.PROPERTY_INDICATE) > 0) {\n\t\t\tbtn_indicate.setVisibility(View.VISIBLE);\n\t\t}\n\t\tif ((charaProp & BleGattCharacteristic.PROPERTY_WRITE) > 0) {\n\t\t\tll_write.setVisibility(View.VISIBLE);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean onCreateOptionsMenu(Menu menu) {\n\n\t\t// Inflate the menu; this adds items to the action bar if it is present.\n\t\tgetMenuInflater().inflate(R.menu.characteristic, menu);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean onOptionsItemSelected(MenuItem item) {\n\t\t// Handle action bar item clicks here. The action bar will\n\t\t// automatically handle clicks on the Home/Up button, so long\n\t\t// as you specify a parent activity in AndroidManifest.xml.\n\t\tint id = item.getItemId();\n\t\tif (id == R.id.action_settings) {\n\t\t\treturn true;\n\t\t}\n\t\treturn super.onOptionsItemSelected(item);\n\t}\n\n\t@Override\n\tprotected void onResume() {\n\t\tsuper.onResume();\n\t\tregisterReceiver(mBleReceiver, BleService.getIntentFilter());\n\t}\n\n\t@Override\n\tpublic void onPanelClosed(int featureId, Menu menu) {\n\t\tsuper.onPanelClosed(featureId, menu);\n\t\tunregisterReceiver(mBleReceiver);\n\t}\n}\n"
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/DeviceControlActivity.java",
    "content": "/*\n * Copyright (C) 2013 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.example.bluetooth.le;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\n\nimport android.app.Activity;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.util.Log;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.ExpandableListView;\nimport android.widget.SimpleExpandableListAdapter;\nimport android.widget.TextView;\n\nimport com.xtremeprog.sdk.ble.BleGattCharacteristic;\nimport com.xtremeprog.sdk.ble.BleGattService;\nimport com.xtremeprog.sdk.ble.BleService;\nimport com.xtremeprog.sdk.ble.IBle;\n//import android.bluetooth.BluetoothGattCharacteristic;\n//import android.bluetooth.BluetoothGattService;\n\n/**\n * For a given BLE device, this Activity provides the user interface to connect,\n * display data, and display GATT services and characteristics supported by the\n * device. The Activity communicates with {@code BluetoothLeService}, which in\n * turn interacts with the Bluetooth LE API.\n */\npublic class DeviceControlActivity extends Activity {\n\tprivate final static String TAG = DeviceControlActivity.class\n\t\t\t.getSimpleName();\n\n\tpublic static final String EXTRAS_DEVICE_NAME = \"DEVICE_NAME\";\n\tpublic static final String EXTRAS_DEVICE_ADDRESS = \"DEVICE_ADDRESS\";\n\n\tprivate TextView mConnectionState;\n\tprivate String mDeviceName;\n\tprivate String mDeviceAddress;\n\tprivate ExpandableListView mGattServicesList;\n\tprivate ArrayList<ArrayList<BleGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BleGattCharacteristic>>();\n\tprivate boolean mConnected = false;\n\n\tprivate final String LIST_NAME = \"NAME\";\n\tprivate final String LIST_UUID = \"UUID\";\n\n\tprotected IBle mBle;\n\n\t// Handles various events fired by the Service.\n\t// ACTION_GATT_CONNECTED: connected to a GATT server.\n\t// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.\n\t// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.\n\t// ACTION_DATA_AVAILABLE: received data from the device. This can be a\n\t// result of read\n\t// or notification operations.\n\tprivate final BroadcastReceiver mBleReceiver = new BroadcastReceiver() {\n\t\t@Override\n\t\tpublic void onReceive(Context context, Intent intent) {\n\t\t\tBundle extras = intent.getExtras();\n\t\t\tif (!mDeviceAddress.equals(extras.getString(BleService.EXTRA_ADDR))) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tString action = intent.getAction();\n\t\t\tif (BleService.BLE_GATT_CONNECTED.equals(action)) {\n\t\t\t\tmConnected = true;\n\t\t\t\tupdateConnectionState(R.string.connected);\n\t\t\t\tinvalidateOptionsMenu();\n\t\t\t} else if (BleService.BLE_GATT_DISCONNECTED.equals(action)) {\n\t\t\t\tonDeviceDisconnected();\n\t\t\t} else if (BleService.BLE_SERVICE_DISCOVERED.equals(action)) {\n\t\t\t\tdisplayGattServices(mBle.getServices(mDeviceAddress));\n\t\t\t}\n\t\t}\n\t};\n\n\t// If a given GATT characteristic is selected, check for supported features.\n\t// This sample\n\t// demonstrates 'Read' and 'Notify' features. See\n\t// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for\n\t// the complete\n\t// list of supported characteristic features.\n\tprivate final ExpandableListView.OnChildClickListener servicesListClickListner = new ExpandableListView.OnChildClickListener() {\n\t\t@Override\n\t\tpublic boolean onChildClick(ExpandableListView parent, View v,\n\t\t\t\tint groupPosition, int childPosition, long id) {\n\t\t\tLog.d(TAG, \"onChildClick \" + groupPosition + \" \" + childPosition);\n\t\t\tif (mGattCharacteristics != null) {\n\t\t\t\tfinal BleGattCharacteristic characteristic = mGattCharacteristics\n\t\t\t\t\t\t.get(groupPosition).get(childPosition);\n\t\t\t\tIntent intent = new Intent(DeviceControlActivity.this,\n\t\t\t\t\t\tCharacteristicActivity.class);\n\t\t\t\tintent.putExtra(\"address\", mDeviceAddress);\n\t\t\t\tLog.d(TAG, \"service size \" + mBle.getServices(mDeviceAddress).size());\n\t\t\t\tintent.putExtra(\"service\", mBle.getServices(mDeviceAddress)\n\t\t\t\t\t\t.get(groupPosition).getUuid().toString());\n\t\t\t\tintent.putExtra(\"characteristic\", characteristic.getUuid()\n\t\t\t\t\t\t.toString().toUpperCase());\n\t\t\t\tstartActivity(intent);\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t};\n\n\tprivate void clearUI() {\n\t\tmGattServicesList.setAdapter((SimpleExpandableListAdapter) null);\n\t}\n\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tsetContentView(R.layout.gatt_services_characteristics);\n\n\t\tfinal Intent intent = getIntent();\n\t\tmDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);\n\t\tmDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);\n\n\t\t// Sets up UI references.\n\t\t((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);\n\t\tmGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);\n\t\tmGattServicesList.setOnChildClickListener(servicesListClickListner);\n\t\tmConnectionState = (TextView) findViewById(R.id.connection_state);\n\n\t\tgetActionBar().setTitle(mDeviceName);\n\t\tgetActionBar().setDisplayHomeAsUpEnabled(true);\n\t\tBleApplication app = (BleApplication) getApplication();\n\t\tmBle = app.getIBle();\n\t}\n\n\t@Override\n\tprotected void onResume() {\n\t\tsuper.onResume();\n\t\tregisterReceiver(mBleReceiver, BleService.getIntentFilter());\n\t\tArrayList<BleGattService> services = mBle.getServices(mDeviceAddress);\n\t\tif (services == null || services.size() == 0) {\n\t\t\tonDeviceDisconnected();\n\t\t}\n\t}\n\n\t@Override\n\tprotected void onPause() {\n\t\tsuper.onPause();\n\t\tunregisterReceiver(mBleReceiver);\n\t}\n\n\t@Override\n\tprotected void onDestroy() {\n\t\tsuper.onDestroy();\n\t\tif (mBle != null) {\n\t\t\tmBle.disconnect(mDeviceAddress);\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean onCreateOptionsMenu(Menu menu) {\n\t\tgetMenuInflater().inflate(R.menu.gatt_services, menu);\n\t\tif (mConnected) {\n\t\t\tmenu.findItem(R.id.menu_connect).setVisible(true);\n\t\t\tmenu.findItem(R.id.menu_disconnect).setVisible(true);\n\t\t} else {\n\t\t\tmenu.findItem(R.id.menu_connect).setVisible(true);\n\t\t\tmenu.findItem(R.id.menu_disconnect).setVisible(true);\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean onOptionsItemSelected(MenuItem item) {\n\t\tswitch (item.getItemId()) {\n\t\tcase R.id.menu_connect:\n\t\t\tmBle.requestConnect(mDeviceAddress);\n\t\t\treturn true;\n\t\tcase R.id.menu_disconnect:\n\t\t\tmBle.disconnect(mDeviceAddress);\n\t\t\tonDeviceDisconnected();\n\t\t\treturn true;\n\t\tcase android.R.id.home:\n\t\t\tonBackPressed();\n\t\t\treturn true;\n\t\t}\n\t\treturn super.onOptionsItemSelected(item);\n\t}\n\n\tprivate void updateConnectionState(final int resourceId) {\n\t\trunOnUiThread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmConnectionState.setText(resourceId);\n\t\t\t}\n\t\t});\n\t}\n\n\t// Demonstrates how to iterate through the supported GATT\n\t// Services/Characteristics.\n\t// In this sample, we populate the data structure that is bound to the\n\t// ExpandableListView\n\t// on the UI.\n\tprivate void displayGattServices(List<BleGattService> gattServices) {\n\t\tif (gattServices == null)\n\t\t\treturn;\n\t\tString uuid = null;\n\t\tString unknownServiceString = getResources().getString(\n\t\t\t\tR.string.unknown_service);\n\t\tString unknownCharaString = getResources().getString(\n\t\t\t\tR.string.unknown_characteristic);\n\t\tArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();\n\t\tArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();\n\t\tmGattCharacteristics = new ArrayList<ArrayList<BleGattCharacteristic>>();\n\n\t\t// Loops through available GATT Services.\n\t\tfor (BleGattService gattService : gattServices) {\n\t\t\tHashMap<String, String> currentServiceData = new HashMap<String, String>();\n\t\t\tuuid = gattService.getUuid().toString().toUpperCase();\n\n\t\t\tcurrentServiceData.put(LIST_NAME, Utils.BLE_SERVICES\n\t\t\t\t\t.containsKey(uuid) ? Utils.BLE_SERVICES.get(uuid)\n\t\t\t\t\t: unknownServiceString);\n\t\t\tcurrentServiceData.put(LIST_UUID, uuid);\n\t\t\tgattServiceData.add(currentServiceData);\n\n\t\t\tArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>();\n\t\t\tList<BleGattCharacteristic> gattCharacteristics = gattService\n\t\t\t\t\t.getCharacteristics();\n\t\t\tArrayList<BleGattCharacteristic> charas = new ArrayList<BleGattCharacteristic>();\n\n\t\t\t// Loops through available Characteristics.\n\t\t\tfor (BleGattCharacteristic gattCharacteristic : gattCharacteristics) {\n\t\t\t\tcharas.add(gattCharacteristic);\n\t\t\t\tHashMap<String, String> currentCharaData = new HashMap<String, String>();\n\t\t\t\tuuid = gattCharacteristic.getUuid().toString().toUpperCase();\n\t\t\t\tcurrentCharaData\n\t\t\t\t\t\t.put(LIST_NAME,\n\t\t\t\t\t\t\t\tUtils.BLE_CHARACTERISTICS.containsKey(uuid) ? Utils.BLE_CHARACTERISTICS\n\t\t\t\t\t\t\t\t\t\t.get(uuid) : unknownCharaString);\n\t\t\t\tcurrentCharaData.put(LIST_UUID, uuid);\n\t\t\t\tgattCharacteristicGroupData.add(currentCharaData);\n\t\t\t}\n\t\t\tmGattCharacteristics.add(charas);\n\t\t\tgattCharacteristicData.add(gattCharacteristicGroupData);\n\t\t}\n\n\t\tSimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(\n\t\t\t\tthis, gattServiceData,\n\t\t\t\tandroid.R.layout.simple_expandable_list_item_2, new String[] {\n\t\t\t\t\t\tLIST_NAME, LIST_UUID }, new int[] { android.R.id.text1,\n\t\t\t\t\t\tandroid.R.id.text2 }, gattCharacteristicData,\n\t\t\t\tandroid.R.layout.simple_expandable_list_item_2, new String[] {\n\t\t\t\t\t\tLIST_NAME, LIST_UUID }, new int[] { android.R.id.text1,\n\t\t\t\t\t\tandroid.R.id.text2 });\n\t\tmGattServicesList.setAdapter(gattServiceAdapter);\n\t}\n\n\tprivate void onDeviceDisconnected() {\n\t\tmConnected = false;\n\t\tupdateConnectionState(R.string.disconnected);\n\t\tinvalidateOptionsMenu();\n\t\tclearUI();\n\t}\n}\n"
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/DeviceScanActivity.java",
    "content": "/*\n * Copyright (C) 2013 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreement to the following terms, and your\n * use, installation, modification or redistribution of this XPG software\n * constitutes acceptance of these terms.� If you do not agree with these terms,\n * please do not use, install, modify or redistribute this XPG software.\n * \n * In consideration of your agreement to abide by the following terms, and\n * subject to these terms, XPG grants you a non-exclusive license, under XPG's\n * copyrights in this original XPG software (the \"XPG Software\"), to use and\n * redistribute the XPG Software, in source and/or binary forms; provided that\n * if you redistribute the XPG Software, with or without modifications, you must\n * retain this notice and the following text and disclaimers in all such\n * redistributions of the XPG Software. Neither the name, trademarks, service\n * marks or logos of XPG Inc. may be used to endorse or promote products derived\n * from the XPG Software without specific prior written permission from XPG.�\n * Except as expressly stated in this notice, no other rights or licenses,\n * express or implied, are granted by XPG herein, including but not limited to\n * any patent rights that may be infringed by your derivative works or by other\n * works in which the XPG Software may be incorporated.\n * \n * The XPG Software is provided by XPG on an \"AS IS\" basis.� XPG MAKES NO\n * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED\n * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN\n * COMBINATION WITH YOUR PRODUCTS.\n * \n * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION\n * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER\n * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR\n * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n * \n * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)\n * is a digital solutions company based in the United States and China. XPG\n * integrates cutting-edge hardware designs, mobile applications, and cloud\n * computing technologies to bring innovative products to the marketplace. XPG's\n * partners and customers include global leading corporations in semiconductor,\n * home appliances, health/wellness electronics, toys and games, and automotive\n * industries. Visit www.xtremeprog.com for more information.\n * \n * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.\n */\n\npackage com.example.bluetooth.le;\n\nimport java.util.ArrayList;\n\nimport android.app.Activity;\nimport android.app.ListActivity;\nimport android.bluetooth.BluetoothAdapter;\nimport android.bluetooth.BluetoothDevice;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Handler;\nimport android.view.LayoutInflater;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.BaseAdapter;\nimport android.widget.ListView;\nimport android.widget.TextView;\nimport android.widget.Toast;\n\nimport com.xtremeprog.sdk.ble.BleService;\nimport com.xtremeprog.sdk.ble.IBle;\n\n/**\n * Activity for scanning and displaying available Bluetooth LE devices.\n */\npublic class DeviceScanActivity extends ListActivity {\n\tprivate LeDeviceListAdapter mLeDeviceListAdapter;\n\tprivate boolean mScanning;\n\tprivate Handler mHandler;\n\tprivate IBle mBle;\n\n\tprivate static final int REQUEST_ENABLE_BT = 1;\n\t// Stops scanning after 10 seconds.\n\tprivate static final long SCAN_PERIOD = 10000;\n\n\tprivate final BroadcastReceiver mBleReceiver = new BroadcastReceiver() {\n\n\t\t@Override\n\t\tpublic void onReceive(Context context, Intent intent) {\n\t\t\tString action = intent.getAction();\n\t\t\tif (BleService.BLE_NOT_SUPPORTED.equals(action)) {\n\t\t\t\trunOnUiThread(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\tToast.makeText(DeviceScanActivity.this,\n\t\t\t\t\t\t\t\t\"Ble not support\", Toast.LENGTH_SHORT).show();\n\t\t\t\t\t\tfinish();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else if (BleService.BLE_DEVICE_FOUND.equals(action)) {\n\t\t\t\t// device found\n\t\t\t\tBundle extras = intent.getExtras();\n\t\t\t\tfinal BluetoothDevice device = extras\n\t\t\t\t\t\t.getParcelable(BleService.EXTRA_DEVICE);\n\t\t\t\trunOnUiThread(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\tmLeDeviceListAdapter.addDevice(device);\n\t\t\t\t\t\tmLeDeviceListAdapter.notifyDataSetChanged();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else if (BleService.BLE_NO_BT_ADAPTER.equals(action)) {\n\t\t\t\trunOnUiThread(new Runnable() {\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic void run() {\n\t\t\t\t\t\tToast.makeText(DeviceScanActivity.this,\n\t\t\t\t\t\t\t\t\"No bluetooth adapter\", Toast.LENGTH_SHORT)\n\t\t\t\t\t\t\t\t.show();\n\t\t\t\t\t\tfinish();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\n\t@Override\n\tpublic void onCreate(Bundle savedInstanceState) {\n\t\tsuper.onCreate(savedInstanceState);\n\t\tgetActionBar().setTitle(R.string.title_devices);\n\t\tmHandler = new Handler();\n\t}\n\n\t@Override\n\tpublic boolean onCreateOptionsMenu(Menu menu) {\n\t\tgetMenuInflater().inflate(R.menu.main, menu);\n\t\tif (!mScanning) {\n\t\t\tmenu.findItem(R.id.menu_stop).setVisible(false);\n\t\t\tmenu.findItem(R.id.menu_scan).setVisible(true);\n\t\t\tmenu.findItem(R.id.menu_refresh).setActionView(null);\n\t\t} else {\n\t\t\tmenu.findItem(R.id.menu_stop).setVisible(true);\n\t\t\tmenu.findItem(R.id.menu_scan).setVisible(false);\n\t\t\tmenu.findItem(R.id.menu_refresh).setActionView(\n\t\t\t\t\tR.layout.actionbar_indeterminate_progress);\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean onOptionsItemSelected(MenuItem item) {\n\t\tswitch (item.getItemId()) {\n\t\tcase R.id.menu_scan:\n\t\t\tmLeDeviceListAdapter.clear();\n\t\t\tscanLeDevice(true);\n\t\t\tbreak;\n\t\tcase R.id.menu_stop:\n\t\t\tscanLeDevice(false);\n\t\t\tbreak;\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tprotected void onResume() {\n\t\tsuper.onResume();\n\t\tregisterReceiver(mBleReceiver, BleService.getIntentFilter());\n\n\t\t// Ensures Bluetooth is enabled on the device. If Bluetooth is not\n\t\t// currently enabled,\n\t\t// fire an intent to display a dialog asking the user to grant\n\t\t// permission to enable it.\n\t\tif (mBle != null && !mBle.adapterEnabled()) {\n\t\t\tIntent enableBtIntent = new Intent(\n\t\t\t\t\tBluetoothAdapter.ACTION_REQUEST_ENABLE);\n\t\t\tstartActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);\n\t\t}\n\n\t\t// Initializes list view adapter.\n\t\tmLeDeviceListAdapter = new LeDeviceListAdapter();\n\t\tsetListAdapter(mLeDeviceListAdapter);\n\t\tscanLeDevice(true);\n\t}\n\n\t@Override\n\tprotected void onActivityResult(int requestCode, int resultCode, Intent data) {\n\t\t// User chose not to enable Bluetooth.\n\t\tif (requestCode == REQUEST_ENABLE_BT\n\t\t\t\t&& resultCode == Activity.RESULT_CANCELED) {\n\t\t\tfinish();\n\t\t\treturn;\n\t\t}\n\t\tsuper.onActivityResult(requestCode, resultCode, data);\n\t}\n\n\t@Override\n\tprotected void onPause() {\n\t\tsuper.onPause();\n\t\tunregisterReceiver(mBleReceiver);\n\t\tscanLeDevice(false);\n\t\tmLeDeviceListAdapter.clear();\n\t}\n\n\t@Override\n\tprotected void onListItemClick(ListView l, View v, int position, long id) {\n\t\tfinal BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);\n\t\tif (device == null)\n\t\t\treturn;\n\t\tfinal Intent intent = new Intent(this, DeviceControlActivity.class);\n\t\tintent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME,\n\t\t\t\tdevice.getName());\n\t\tintent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS,\n\t\t\t\tdevice.getAddress());\n\t\tif (mBle != null) {\n\t\t\tmBle.stopScan();\n\t\t}\n\t\tstartActivity(intent);\n\t}\n\n\tprivate void scanLeDevice(final boolean enable) {\n\t\tBleApplication app = (BleApplication) getApplication();\n\t\tmBle = app.getIBle();\n\t\tif (mBle == null) {\n\t\t\treturn;\n\t\t}\n\t\tif (enable) {\n\t\t\t// Stops scanning after a pre-defined scan period.\n\t\t\tmHandler.postDelayed(new Runnable() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tmScanning = false;\n\t\t\t\t\tif (mBle != null) {\n\t\t\t\t\t\tmBle.stopScan();\n\t\t\t\t\t}\n\t\t\t\t\tinvalidateOptionsMenu();\n\t\t\t\t}\n\t\t\t}, SCAN_PERIOD);\n\n\t\t\tmScanning = true;\n\t\t\tif (mBle != null) {\n\t\t\t\tmBle.startScan();\n\t\t\t}\n\t\t} else {\n\t\t\tmScanning = false;\n\t\t\tif (mBle != null) {\n\t\t\t\tmBle.stopScan();\n\t\t\t}\n\t\t}\n\t\tinvalidateOptionsMenu();\n\t}\n\n\t// Adapter for holding devices found through scanning.\n\tprivate class LeDeviceListAdapter extends BaseAdapter {\n\t\tprivate ArrayList<BluetoothDevice> mLeDevices;\n\t\tprivate LayoutInflater mInflator;\n\n\t\tpublic LeDeviceListAdapter() {\n\t\t\tsuper();\n\t\t\tmLeDevices = new ArrayList<BluetoothDevice>();\n\t\t\tmInflator = DeviceScanActivity.this.getLayoutInflater();\n\t\t}\n\n\t\tpublic void addDevice(BluetoothDevice device) {\n\t\t\tif (!mLeDevices.contains(device)) {\n\t\t\t\tmLeDevices.add(device);\n\t\t\t}\n\t\t}\n\n\t\tpublic BluetoothDevice getDevice(int position) {\n\t\t\treturn mLeDevices.get(position);\n\t\t}\n\n\t\tpublic void clear() {\n\t\t\tmLeDevices.clear();\n\t\t}\n\n\t\t@Override\n\t\tpublic int getCount() {\n\t\t\treturn mLeDevices.size();\n\t\t}\n\n\t\t@Override\n\t\tpublic Object getItem(int i) {\n\t\t\treturn mLeDevices.get(i);\n\t\t}\n\n\t\t@Override\n\t\tpublic long getItemId(int i) {\n\t\t\treturn i;\n\t\t}\n\n\t\t@Override\n\t\tpublic View getView(int i, View view, ViewGroup viewGroup) {\n\t\t\tViewHolder viewHolder;\n\t\t\t// General ListView optimization code.\n\t\t\tif (view == null) {\n\t\t\t\tview = mInflator.inflate(R.layout.listitem_device, null);\n\t\t\t\tviewHolder = new ViewHolder();\n\t\t\t\tviewHolder.deviceAddress = (TextView) view\n\t\t\t\t\t\t.findViewById(R.id.device_address);\n\t\t\t\tviewHolder.deviceName = (TextView) view\n\t\t\t\t\t\t.findViewById(R.id.device_name);\n\t\t\t\tview.setTag(viewHolder);\n\t\t\t} else {\n\t\t\t\tviewHolder = (ViewHolder) view.getTag();\n\t\t\t}\n\n\t\t\tBluetoothDevice device = mLeDevices.get(i);\n\t\t\tfinal String deviceName = device.getName();\n\t\t\tif (deviceName != null && deviceName.length() > 0)\n\t\t\t\tviewHolder.deviceName.setText(deviceName);\n\t\t\telse\n\t\t\t\tviewHolder.deviceName.setText(R.string.unknown_device);\n\t\t\tviewHolder.deviceAddress.setText(device.getAddress());\n\n\t\t\treturn view;\n\t\t}\n\t}\n\n\tstatic class ViewHolder {\n\t\tTextView deviceName;\n\t\tTextView deviceAddress;\n\t}\n}"
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/Utils.java",
    "content": "package com.example.bluetooth.le;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class Utils {\n\tpublic static Map<String, String> BLE_SERVICES = new HashMap<String, String>();\n\tpublic static Map<String, String> BLE_CHARACTERISTICS = new HashMap<String, String>();\n\t\n\tstatic {\n\t\tBLE_SERVICES.put(\"00001811-0000-1000-8000-00805F9B34FB\", \"Alert Notification Service\");\n\t\tBLE_SERVICES.put(\"0000180F-0000-1000-8000-00805F9B34FB\", \"Battery Service\");\n\t\tBLE_SERVICES.put(\"00001810-0000-1000-8000-00805F9B34FB\", \"Blood Pressure\");\n\t\tBLE_SERVICES.put(\"00001805-0000-1000-8000-00805F9B34FB\", \"Current Time Service\");\n\t\tBLE_SERVICES.put(\"00001818-0000-1000-8000-00805F9B34FB\", \"Cycling Power\");\n\t\tBLE_SERVICES.put(\"00001816-0000-1000-8000-00805F9B34FB\", \"Cycling Speed and Cadence\");\n\t\tBLE_SERVICES.put(\"0000180A-0000-1000-8000-00805F9B34FB\", \"Device Information\");\n\t\tBLE_SERVICES.put(\"00001800-0000-1000-8000-00805F9B34FB\", \"Generic Access\");\n\t\tBLE_SERVICES.put(\"00001801-0000-1000-8000-00805F9B34FB\", \"Generic Attribute\");\n\t\tBLE_SERVICES.put(\"00001808-0000-1000-8000-00805F9B34FB\", \"Glucose\");\n\t\tBLE_SERVICES.put(\"00001809-0000-1000-8000-00805F9B34FB\", \"Health Thermometer\");\n\t\tBLE_SERVICES.put(\"0000180D-0000-1000-8000-00805F9B34FB\", \"Heart Rate\");\n\t\tBLE_SERVICES.put(\"00001812-0000-1000-8000-00805F9B34FB\", \"Human Interface Device\");\n\t\tBLE_SERVICES.put(\"00001802-0000-1000-8000-00805F9B34FB\", \"Immediate Alert\");\n\t\tBLE_SERVICES.put(\"00001803-0000-1000-8000-00805F9B34FB\", \"Link Loss\");\n\t\tBLE_SERVICES.put(\"00001819-0000-1000-8000-00805F9B34FB\", \"Location and Navigation\");\n\t\tBLE_SERVICES.put(\"00001807-0000-1000-8000-00805F9B34FB\", \"Next DST Change Service\");\n\t\tBLE_SERVICES.put(\"0000180E-0000-1000-8000-00805F9B34FB\", \"Phone Alert Status Service\");\n\t\tBLE_SERVICES.put(\"00001806-0000-1000-8000-00805F9B34FB\", \"Reference Time Update Service\");\n\t\tBLE_SERVICES.put(\"00001814-0000-1000-8000-00805F9B34FB\", \"Running Speed and Cadence\");\n\t\tBLE_SERVICES.put(\"00001813-0000-1000-8000-00805F9B34FB\", \"Scan Parameters\");\n\t\tBLE_SERVICES.put(\"00001804-0000-1000-8000-00805F9B34FB\", \"Tx Power\");\n\t\t\n\t\tBLE_CHARACTERISTICS.put(\"00002A43-0000-1000-8000-00805F9B34FB\", \"Alert Category ID\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A42-0000-1000-8000-00805F9B34FB\", \"Alert Category ID Bit Mask\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A06-0000-1000-8000-00805F9B34FB\", \"Alert Level\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A44-0000-1000-8000-00805F9B34FB\", \"Alert Notification Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A3F-0000-1000-8000-00805F9B34FB\", \"Alert Status\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A01-0000-1000-8000-00805F9B34FB\", \"Appearance\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A19-0000-1000-8000-00805F9B34FB\", \"Battery Level\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A49-0000-1000-8000-00805F9B34FB\", \"Blood Pressure Feature\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A35-0000-1000-8000-00805F9B34FB\", \"Blood Pressure Measurement\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A38-0000-1000-8000-00805F9B34FB\", \"Body Sensor Location\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A22-0000-1000-8000-00805F9B34FB\", \"Boot Keyboard Input Report\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A32-0000-1000-8000-00805F9B34FB\", \"Boot Keyboard Output Report\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A33-0000-1000-8000-00805F9B34FB\", \"Boot Mouse Input Report\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A5C-0000-1000-8000-00805F9B34FB\", \"CSC Feature\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A5B-0000-1000-8000-00805F9B34FB\", \"CSC Measurement\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A2B-0000-1000-8000-00805F9B34FB\", \"Current Time\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A66-0000-1000-8000-00805F9B34FB\", \"Cycling Power Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A65-0000-1000-8000-00805F9B34FB\", \"Cycling Power Feature\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A63-0000-1000-8000-00805F9B34FB\", \"Cycling Power Measurement\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A64-0000-1000-8000-00805F9B34FB\", \"Cycling Power Vector\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A08-0000-1000-8000-00805F9B34FB\", \"Date Time\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A0A-0000-1000-8000-00805F9B34FB\", \"Day Date Time\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A09-0000-1000-8000-00805F9B34FB\", \"Day of Week\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A00-0000-1000-8000-00805F9B34FB\", \"Device Name\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A0D-0000-1000-8000-00805F9B34FB\", \"DST Offset\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A0C-0000-1000-8000-00805F9B34FB\", \"Exact Time 256\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A26-0000-1000-8000-00805F9B34FB\", \"Firmware Revision String\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A51-0000-1000-8000-00805F9B34FB\", \"Glucose Feature\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A18-0000-1000-8000-00805F9B34FB\", \"Glucose Measurement\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A34-0000-1000-8000-00805F9B34FB\", \"Glucose Measurement Context\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A27-0000-1000-8000-00805F9B34FB\", \"Hardware Revision String\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A39-0000-1000-8000-00805F9B34FB\", \"Heart Rate Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A37-0000-1000-8000-00805F9B34FB\", \"Heart Rate Measurement\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A4C-0000-1000-8000-00805F9B34FB\", \"HID Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A4A-0000-1000-8000-00805F9B34FB\", \"HID Information\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A2A-0000-1000-8000-00805F9B34FB\", \"IEEE 11073-20601 Regulatory Certification Data List\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A36-0000-1000-8000-00805F9B34FB\", \"Intermediate Cuff Pressure\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A1E-0000-1000-8000-00805F9B34FB\", \"Intermediate Temperature\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A6B-0000-1000-8000-00805F9B34FB\", \"LN Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A6A-0000-1000-8000-00805F9B34FB\", \"LN Feature\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A0F-0000-1000-8000-00805F9B34FB\", \"Local Time Information\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A67-0000-1000-8000-00805F9B34FB\", \"Location and Speed\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A29-0000-1000-8000-00805F9B34FB\", \"Manufacturer Name String\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A21-0000-1000-8000-00805F9B34FB\", \"Measurement Interval\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A24-0000-1000-8000-00805F9B34FB\", \"Model Number String\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A68-0000-1000-8000-00805F9B34FB\", \"Navigation\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A46-0000-1000-8000-00805F9B34FB\", \"New Alert\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A04-0000-1000-8000-00805F9B34FB\", \"Peripheral Preferred Connection Parameters\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A02-0000-1000-8000-00805F9B34FB\", \"Peripheral Privacy Flag\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A50-0000-1000-8000-00805F9B34FB\", \"PnP ID\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A69-0000-1000-8000-00805F9B34FB\", \"Position Quality\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A4E-0000-1000-8000-00805F9B34FB\", \"Protocol Mode\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A03-0000-1000-8000-00805F9B34FB\", \"Reconnection Address\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A52-0000-1000-8000-00805F9B34FB\", \"Record Access Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A14-0000-1000-8000-00805F9B34FB\", \"Reference Time Information\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A4D-0000-1000-8000-00805F9B34FB\", \"Report\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A4B-0000-1000-8000-00805F9B34FB\", \"Report Map\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A40-0000-1000-8000-00805F9B34FB\", \"Ringer Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A41-0000-1000-8000-00805F9B34FB\", \"Ringer Setting\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A54-0000-1000-8000-00805F9B34FB\", \"RSC Feature\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A53-0000-1000-8000-00805F9B34FB\", \"RSC Measurement\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A55-0000-1000-8000-00805F9B34FB\", \"SC Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A4F-0000-1000-8000-00805F9B34FB\", \"Scan Interval Window\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A31-0000-1000-8000-00805F9B34FB\", \"Scan Refresh\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A5D-0000-1000-8000-00805F9B34FB\", \"Sensor Location\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A25-0000-1000-8000-00805F9B34FB\", \"Serial Number String\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A05-0000-1000-8000-00805F9B34FB\", \"Service Changed\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A28-0000-1000-8000-00805F9B34FB\", \"Software Revision String\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A47-0000-1000-8000-00805F9B34FB\", \"Supported New Alert Category\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A48-0000-1000-8000-00805F9B34FB\", \"Supported Unread Alert Category\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A23-0000-1000-8000-00805F9B34FB\", \"System ID\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A1C-0000-1000-8000-00805F9B34FB\", \"Temperature Measurement\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A1D-0000-1000-8000-00805F9B34FB\", \"Temperature Type\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A12-0000-1000-8000-00805F9B34FB\", \"Time Accuracy\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A13-0000-1000-8000-00805F9B34FB\", \"Time Source\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A16-0000-1000-8000-00805F9B34FB\", \"Time Update Control Point\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A17-0000-1000-8000-00805F9B34FB\", \"Time Update State\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A11-0000-1000-8000-00805F9B34FB\", \"Time with DST\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A0E-0000-1000-8000-00805F9B34FB\", \"Time Zone\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A07-0000-1000-8000-00805F9B34FB\", \"Tx Power Level\");\n\t\tBLE_CHARACTERISTICS.put(\"00002A45-0000-1000-8000-00805F9B34FB\", \"Unread Alert Status\");\n\t}\n\t\n\tprivate static Utils INSTANCE;\n\t\n\tprivate Utils() {}\n\t\n\tpublic static Utils getInstance() {\n\t\tif (INSTANCE == null) {\n\t\t\tINSTANCE = new Utils();\n\t\t}\n\t\treturn INSTANCE;\n\t}\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "README.md",
    "content": "GizwitsBLE\n==========\n\nGizwitsBLE solves the compatibility and reliability issues that have troubled developers. First, many BLE-ready Android phones (e.g. Samsung S2 and Note2) have not been upgraded to Android 4.3. Therefore adding Android app-level BLE support requires developers to code against a number of vendor specific BLE SDK's. Second, the Android 4.3 native BLE support has a number of pitfalls that seriously affect user experience. Since android users rarely upgrade their Operating Systems, Android 4.2 and 4.3 will continue to dominate the Android smartphone market for the next few years. \n\nGizwitsBLE Android SDK was build to be a quick and reliable solution for developers to add robust BLE support for Android 4.2 and Android 4.3+ smartphones with a simple common interface. On Android 4.2 phones, GizwitsBLE automatically detects and adapts to the corresponding vendor specific SDK (e.g. those provided by Samsung and Broadcom), so that developers don't have to learn and code against the specifies of each implementation. \n\nOn Android 4.3 phones, BLE related calls tends to crash the app and even the Operating System for no apparent reasons. Through trial and error, the Gizwits team has found that BLE calls must be made serially to avoid system crashes, and therefore all  requests (connection, discovery service, read or write characteristics) are queued and executed sequentially. This has made BLE communications much more stable. \n\nGizwitsBLE has a simple interface that's easy to learn and is open sourced. It is also been heavily tested and is commercially ready. It powers dozens of BLE products. We encourage all developers frustrated by the fragmented and inconsistent BLE support on try it out.\n\n# Main Features\n* Support Android 4.2 (Broadcom, Sumsung SDK) and Android 4.3+ \n* Built in Service, just start the service and receive BLE events by broadcast\n* Built in BLE request queue\n\n# Components\n* BleLibrary: this is the library project you can reuse in your project.\n* BluetoothLeGatt: this is the demo app project that uses BleLibrary.\n\n# Compile & Run\n## Eclipse\nThese two projects are eclipse projects. If you use eclipse, you can import these projects directly and run BluetoothLeGatt.\n## Android Studio\nIf you use android studio, you should import these project.\n\nWhen it goes to Libraries step, it will show libs and libs1, just choose libs and ignore libs1.\n\nWhen it goes to select project SDK step, ensure you choose Android API > 17.\n\nThen you can run BluetoothLeGatt in android studio.\n"
  }
]