Full Code of xpg/GizwitsBLE for AI

master 82300009aff2 cached
47 files
167.2 KB
42.6k tokens
231 symbols
1 requests
Download .txt
Repository: xpg/GizwitsBLE
Branch: master
Commit: 82300009aff2
Files: 47
Total size: 167.2 KB

Directory structure:
gitextract_x58tzomf/

├── .gitignore
├── BleLibrary/
│   ├── .classpath
│   ├── .project
│   ├── AndroidManifest.xml
│   ├── libs/
│   │   ├── com.broadcom.bt.jar
│   │   ├── commons-codec-1.8.jar
│   │   └── samsung_ble_sdk_200.jar
│   ├── proguard-project.txt
│   ├── proguard.pro
│   ├── project.properties
│   ├── res/
│   │   ├── values/
│   │   │   ├── strings.xml
│   │   │   └── styles.xml
│   │   ├── values-v11/
│   │   │   └── styles.xml
│   │   └── values-v14/
│   │       └── styles.xml
│   └── src/
│       └── com/
│           └── xtremeprog/
│               └── sdk/
│                   └── ble/
│                       ├── AndroidBle.java
│                       ├── BleGattCharacteristic.java
│                       ├── BleGattService.java
│                       ├── BleRequest.java
│                       ├── BleService.java
│                       ├── BroadcomBle.java
│                       ├── IBle.java
│                       ├── IBleRequestHandler.java
│                       └── SamsungBle.java
├── BluetoothLeGatt/
│   ├── .classpath
│   ├── .project
│   ├── AndroidManifest.xml
│   ├── libs/
│   │   ├── com.broadcom.bt.jar
│   │   ├── commons-codec-1.8.jar
│   │   └── samsung_ble_sdk_200.jar
│   ├── project.properties
│   ├── res/
│   │   ├── layout/
│   │   │   ├── actionbar_indeterminate_progress.xml
│   │   │   ├── activity_characteristic.xml
│   │   │   ├── gatt_services_characteristics.xml
│   │   │   └── listitem_device.xml
│   │   ├── menu/
│   │   │   ├── characteristic.xml
│   │   │   ├── gatt_services.xml
│   │   │   └── main.xml
│   │   ├── values/
│   │   │   ├── dimens.xml
│   │   │   └── strings.xml
│   │   └── values-w820dp/
│   │       └── dimens.xml
│   └── src/
│       └── com/
│           └── example/
│               └── bluetooth/
│                   └── le/
│                       ├── BleApplication.java
│                       ├── CharacteristicActivity.java
│                       ├── DeviceControlActivity.java
│                       ├── DeviceScanActivity.java
│                       └── Utils.java
├── LICENSE
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Built application files
*.apk
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/


================================================
FILE: BleLibrary/.classpath
================================================
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="src" path="src"/>
	<classpathentry kind="src" path="gen"/>
	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
	<classpathentry kind="output" path="bin/classes"/>
</classpath>


================================================
FILE: BleLibrary/.project
================================================
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>BleLibrary</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.jdt.core.javabuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
	</buildSpec>
	<natures>
		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
		<nature>org.eclipse.jdt.core.javanature</nature>
	</natures>
</projectDescription>


================================================
FILE: BleLibrary/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xtremeprog.sdk.ble"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="17"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
    </application>

</manifest>


================================================
FILE: BleLibrary/proguard-project.txt
================================================
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: BleLibrary/proguard.pro
================================================
-injars bin/blelibrary.jar
-outjars bin/blelibrary-0.1.jar

-libraryjars /Users/teamx/bin/adt-bundle-mac-x86_64-20130917/sdk/platforms/android-18/android.jar
-libraryjars libs/com.broadcom.bt.jar
-libraryjars libs/commons-codec-1.8.jar
-libraryjars libs/samsung_ble_sdk_200.jar

-target 1.6
-useuniqueclassmembernames
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,LocalVariable*Table,*Annotation*,Synthetic,EnclosingMethod
-renamesourcefileattribute SourceFile
-adaptresourcefilenames **.properties
-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF
-verbose


# Keep - Library. Keep all public and protected classes, fields, and methods.
-keep public class * {
    public protected <fields>;
    public protected <methods>;
}

# Also keep - Enumerations. Keep the special static methods that are required in
# enumeration classes.
-keepclassmembers enum  * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# Keep names - Native method names. Keep all native class/method names.
-keepclasseswithmembers,allowshrinking class * {
    native <methods>;
}


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

# Project target.
target=android-19
android.library=true


================================================
FILE: BleLibrary/res/values/strings.xml
================================================
<resources>

    <string name="app_name">BleLibrary</string>

</resources>


================================================
FILE: BleLibrary/res/values/styles.xml
================================================
<resources>

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    </style>

</resources>


================================================
FILE: BleLibrary/res/values-v11/styles.xml
================================================
<resources>

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

</resources>


================================================
FILE: BleLibrary/res/values-v14/styles.xml
================================================
<resources>

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

</resources>


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/AndroidBle.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.codec.binary.Hex;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log;

import com.xtremeprog.sdk.ble.BleRequest.RequestType;

@SuppressLint("NewApi")
public class AndroidBle implements IBle, IBleRequestHandler {

	protected static final String TAG = "blelib";

	private BleService mService;
	private BluetoothAdapter mBtAdapter;
	private Map<String, BluetoothGatt> mBluetoothGatts;
	// private BTQuery btQuery;

	private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
		@Override
		public void onLeScan(final BluetoothDevice device, int rssi,
				byte[] scanRecord) {
			mService.bleDeviceFound(device, rssi, scanRecord,
					BleService.DEVICE_SOURCE_SCAN);
		}
	};

	private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
		@Override
		public void onConnectionStateChange(BluetoothGatt gatt, int status,
				int newState) {
			String address = gatt.getDevice().getAddress();
			Log.d(TAG, "onConnectionStateChange " + address + " status "
					+ status + " newState " + newState);
			if (status != BluetoothGatt.GATT_SUCCESS) {
				disconnect(address);
				mService.bleGattDisConnected(address);
				return;
			}

			if (newState == BluetoothProfile.STATE_CONNECTED) {
				mService.bleGattConnected(gatt.getDevice());
				mService.addBleRequest(new BleRequest(
						RequestType.DISCOVER_SERVICE, address));
			} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				mService.bleGattDisConnected(address);
				disconnect(address);
			}
		}

		@Override
		public void onServicesDiscovered(BluetoothGatt gatt, int status) {
			String address = gatt.getDevice().getAddress();
			Log.d(TAG, "onServicesDiscovered " + address + " status " + status);
			if (status != BluetoothGatt.GATT_SUCCESS) {
				mService.requestProcessed(address,
						RequestType.DISCOVER_SERVICE, false);
				return;
			}
			mService.bleServiceDiscovered(gatt.getDevice().getAddress());
		}

		@Override
		public void onCharacteristicRead(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic, int status) {
			String address = gatt.getDevice().getAddress();
			Log.d(TAG, "onCharacteristicRead " + address + " status " + status);
			if (status != BluetoothGatt.GATT_SUCCESS) {
				mService.requestProcessed(address,
						RequestType.READ_CHARACTERISTIC, false);
				return;
			}
			// Log.d(TAG, "data " + characteristic.getStringValue(0));
			mService.bleCharacteristicRead(gatt.getDevice().getAddress(),
					characteristic.getUuid().toString(), status,
					characteristic.getValue());
		}

		@Override
		public void onCharacteristicChanged(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic) {
			String address = gatt.getDevice().getAddress();
			Log.d(TAG, "onCharacteristicChanged " + address);
			Log.d(TAG, new String(Hex.encodeHex(characteristic.getValue())));
			mService.bleCharacteristicChanged(address, characteristic.getUuid()
					.toString(), characteristic.getValue());
		}

		public void onCharacteristicWrite(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic, int status) {
			String address = gatt.getDevice().getAddress();
			Log.d(TAG, "onCharacteristicWrite " + address + " status " + status);
			if (status != BluetoothGatt.GATT_SUCCESS) {
				mService.requestProcessed(address,
						RequestType.WRITE_CHARACTERISTIC, false);
				return;
			}
			mService.bleCharacteristicWrite(gatt.getDevice().getAddress(),
					characteristic.getUuid().toString(), status);
		};

		public void onDescriptorWrite(BluetoothGatt gatt,
				BluetoothGattDescriptor descriptor, int status) {
			String address = gatt.getDevice().getAddress();
			Log.d(TAG, "onDescriptorWrite " + address + " status " + status);
			BleRequest request = mService.getCurrentRequest();
			if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION
					|| request.type == RequestType.CHARACTERISTIC_INDICATION
					|| request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {
				if (status != BluetoothGatt.GATT_SUCCESS) {
					mService.requestProcessed(address,
							RequestType.CHARACTERISTIC_NOTIFICATION, false);
					return;
				}
				if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), true,
							status);
				} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {
					mService.bleCharacteristicIndication(address, descriptor
							.getCharacteristic().getUuid().toString(), status);
				} else {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), false,
							status);
				}
				return;
			}
		};
	};

	public AndroidBle(BleService service) {
		mService = service;
		// btQuery = BTQuery.getInstance();
		if (!mService.getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_BLUETOOTH_LE)) {
			mService.bleNotSupported();
			return;
		}

		final BluetoothManager bluetoothManager = (BluetoothManager) mService
				.getSystemService(Context.BLUETOOTH_SERVICE);

		mBtAdapter = bluetoothManager.getAdapter();
		if (mBtAdapter == null) {
			mService.bleNoBtAdapter();
		}
		mBluetoothGatts = new HashMap<String, BluetoothGatt>();
	}

	@Override
	public void startScan() {
		mBtAdapter.startLeScan(mLeScanCallback);
	}

	@Override
	public void stopScan() {
		mBtAdapter.stopLeScan(mLeScanCallback);
	}

	@Override
	public boolean adapterEnabled() {
		if (mBtAdapter != null) {
			return mBtAdapter.isEnabled();
		}
		return false;
	}

	@Override
	public boolean connect(String address) {
		BluetoothDevice device = mBtAdapter.getRemoteDevice(address);
		BluetoothGatt gatt = device.connectGatt(mService, false, mGattCallback);
		if (gatt == null) {
			mBluetoothGatts.remove(address);
			return false;
		} else {
			// TODO: if state is 141, it can be connected again after about 15
			// seconds
			mBluetoothGatts.put(address, gatt);
			return true;
		}
	}

	@Override
	public void disconnect(String address) {
		if (mBluetoothGatts.containsKey(address)) {
			BluetoothGatt gatt = mBluetoothGatts.remove(address);
			if (gatt != null) {
				gatt.disconnect();
				gatt.close();
			}
		}
	}

	@Override
	public ArrayList<BleGattService> getServices(String address) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null) {
			return null;
		}

		ArrayList<BleGattService> list = new ArrayList<BleGattService>();
		List<BluetoothGattService> services = gatt.getServices();
		for (BluetoothGattService s : services) {
			BleGattService service = new BleGattService(s);
			// service.setInfo(btQuery.getGattServiceInfo(s.getUuid()));
			list.add(service);
		}
		return list;
	}

	@Override
	public boolean requestReadCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null || characteristic == null) {
			return false;
		}

		mService.addBleRequest(new BleRequest(RequestType.READ_CHARACTERISTIC,
				gatt.getDevice().getAddress(), characteristic));
		return true;
	}

	public boolean readCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null) {
			return false;
		}

		return gatt.readCharacteristic(characteristic.getGattCharacteristicA());
	}

	@Override
	public boolean discoverServices(String address) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null) {
			return false;
		}

		boolean ret = gatt.discoverServices();
		if (!ret) {
			disconnect(address);
		}
		return ret;
	}

	@Override
	public BleGattService getService(String address, UUID uuid) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null) {
			return null;
		}

		BluetoothGattService service = gatt.getService(uuid);
		if (service == null) {
			return null;
		} else {
			return new BleGattService(service);
		}
	}

	@Override
	public boolean requestCharacteristicNotification(String address,
			BleGattCharacteristic characteristic) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null || characteristic == null) {
			return false;
		}

		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_NOTIFICATION, gatt.getDevice()
						.getAddress(), characteristic));
		return true;
	}

	@Override
	public boolean characteristicNotification(String address,
			BleGattCharacteristic characteristic) {
		BleRequest request = mService.getCurrentRequest();
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null || characteristic == null) {
			return false;
		}

		boolean enable = true;
		if (request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {
			enable = false;
		}
		BluetoothGattCharacteristic c = characteristic.getGattCharacteristicA();
		if (!gatt.setCharacteristicNotification(c, enable)) {
			return false;
		}

		BluetoothGattDescriptor descriptor = c
				.getDescriptor(BleService.DESC_CCC);
		if (descriptor == null) {
			return false;
		}

		byte[] val_set = null;
		if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {
			val_set = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
		} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {
			val_set = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;
		} else {
			val_set = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;
		}
		if (!descriptor.setValue(val_set)) {
			return false;
		}

		return gatt.writeDescriptor(descriptor);
	}

	@Override
	public boolean requestWriteCharacteristic(String address,
			BleGattCharacteristic characteristic, String remark) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null || characteristic == null) {
			return false;
		}

		mService.addBleRequest(new BleRequest(RequestType.WRITE_CHARACTERISTIC,
				gatt.getDevice().getAddress(), characteristic, remark));
		return true;
	}

	@Override
	public boolean writeCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null) {
			return false;
		}

		Log.d("blelib", new String(Hex.encodeHex(characteristic.getGattCharacteristicA().getValue())));
		return gatt
				.writeCharacteristic(characteristic.getGattCharacteristicA());
	}

	@Override
	public boolean requestConnect(String address) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt != null && gatt.getServices().size() == 0) {
			return false;
		}

		mService.addBleRequest(new BleRequest(RequestType.CONNECT_GATT, address));
		return true;
	}

	@Override
	public String getBTAdapterMacAddr() {
		if (mBtAdapter != null) {
			return mBtAdapter.getAddress();
		}
		return null;
	}

	@Override
	public boolean requestIndication(String address,
			BleGattCharacteristic characteristic) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null || characteristic == null) {
			return false;
		}

		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_INDICATION, gatt.getDevice()
						.getAddress(), characteristic));
		return true;
	}

	@Override
	public boolean requestStopNotification(String address,
			BleGattCharacteristic characteristic) {
		BluetoothGatt gatt = mBluetoothGatts.get(address);
		if (gatt == null || characteristic == null) {
			return false;
		}

		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_NOTIFICATION, gatt.getDevice()
						.getAddress(), characteristic));
		return true;
	}
}


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BleGattCharacteristic.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

import java.util.UUID;

import android.annotation.SuppressLint;

import com.xtremeprog.sdk.ble.BleService.BLESDK;

@SuppressLint("NewApi")
public class BleGattCharacteristic {

	public static final int PROPERTY_READ = 2;
	public static final int PROPERTY_WRITE = 8;
	public static final int PROPERTY_NOTIFY = 16;
	public static final int PROPERTY_INDICATE = 32;

	/**
	 * Characteristic value format type uint8
	 */
	public static final int FORMAT_UINT8 = 0x11;

	/**
	 * Characteristic value format type uint16
	 */
	public static final int FORMAT_UINT16 = 0x12;

	/**
	 * Characteristic value format type uint24 Note: this is not a standard data
	 * type!
	 */
	public static final int FORMAT_UINT24 = 0x13;

	/**
	 * Characteristic value format type uint32
	 */
	public static final int FORMAT_UINT32 = 0x14;

	/**
	 * Characteristic value format type sint8
	 */
	public static final int FORMAT_SINT8 = 0x21;

	/**
	 * Characteristic value format type sint16
	 */
	public static final int FORMAT_SINT16 = 0x22;

	/**
	 * Characteristic value format type sint32
	 */
	public static final int FORMAT_SINT32 = 0x24;

	/**
	 * Characteristic value format type sfloat (16-bit float)
	 */
	public static final int FORMAT_SFLOAT = 0x32;

	/**
	 * Characteristic value format type float (32-bit float)
	 */
	public static final int FORMAT_FLOAT = 0x34;

	private android.bluetooth.BluetoothGattCharacteristic mGattCharacteristicA;
	private com.broadcom.bt.gatt.BluetoothGattCharacteristic mGattCharacteristicB;
	private com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic mGattCharacteristicS;
	private BLESDK mBleSDK;
	private String name;

	public BleGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic c) {
		mBleSDK = BLESDK.ANDROID;
		setGattCharacteristicA(c);
		initInfo();
	}

	public BleGattCharacteristic(
			com.broadcom.bt.gatt.BluetoothGattCharacteristic c) {
		mBleSDK = BLESDK.BROADCOM;
		setGattCharacteristicB(c);
	}

	public BleGattCharacteristic(
			com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic c) {
		mBleSDK = BLESDK.SAMSUNG;
		setGattCharacteristicS(c);
	}

	private void initInfo() {
		name = "Unknown characteristic";
	}

	public UUID getUuid() {
		if (mBleSDK == BLESDK.ANDROID) {
			return getGattCharacteristicA().getUuid();
		} else if (mBleSDK == BLESDK.BROADCOM) {
			return getGattCharacteristicB().getUuid();
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return getGattCharacteristicS().getUuid();
		}

		return null;
	}

	protected android.bluetooth.BluetoothGattCharacteristic getGattCharacteristicA() {
		return mGattCharacteristicA;
	}

	public int getProperties() {
		if (mBleSDK == BLESDK.ANDROID) {
			return getGattCharacteristicA().getProperties();
		} else if (mBleSDK == BLESDK.BROADCOM) {
			return getGattCharacteristicB().getProperties();
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return getGattCharacteristicS().getProperties();
		}

		return 0;
	}

	protected com.broadcom.bt.gatt.BluetoothGattCharacteristic getGattCharacteristicB() {
		return mGattCharacteristicB;
	}

	protected void setGattCharacteristicB(
			com.broadcom.bt.gatt.BluetoothGattCharacteristic mBCGattCharacteristic) {
		this.mGattCharacteristicB = mBCGattCharacteristic;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean setValue(byte[] val) {
		if (mBleSDK == BLESDK.ANDROID) {
			return getGattCharacteristicA().setValue(val);
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return mGattCharacteristicS.setValue(val);
		} else if (mBleSDK == BLESDK.BROADCOM) {
			return mGattCharacteristicB.setValue(val);
		}

		return false;
	}

	public byte[] getValue() {
		if (mBleSDK == BLESDK.ANDROID) {
			return getGattCharacteristicA().getValue();
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return mGattCharacteristicS.getValue();
		} else if (mBleSDK == BLESDK.BROADCOM) {
			return mGattCharacteristicB.getValue();
		}

		return null;
	}

	public boolean setValue(int value, int formatType, int offset) {
		if (mBleSDK == BLESDK.ANDROID) {
			return getGattCharacteristicA().setValue(value, formatType, offset);
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return mGattCharacteristicS.setValue(value, formatType, offset);
		} else if (mBleSDK == BLESDK.BROADCOM) {
			return mGattCharacteristicB.setValue(value, formatType, offset);
		}

		return false;
	}

	public boolean setValue(int mantissa, int exponent, int formatType,
			int offset) {
		if (mBleSDK == BLESDK.ANDROID) {
			return getGattCharacteristicA().setValue(mantissa, exponent,
					formatType, offset);
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return mGattCharacteristicS.setValue(mantissa, exponent,
					formatType, offset);
		} else if (mBleSDK == BLESDK.BROADCOM) {
			return mGattCharacteristicB.setValue(mantissa, exponent,
					formatType, offset);
		}

		return false;
	}

	public boolean setValue(String value) {
		return setValue(value.getBytes());
	}

	public String getStringValue(int offset) {
		if (mBleSDK == BLESDK.ANDROID) {
			return getGattCharacteristicA().getStringValue(offset);
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return mGattCharacteristicS.getStringValue(offset);
		} else if (mBleSDK == BLESDK.BROADCOM) {
			return mGattCharacteristicB.getStringValue(offset);
		}

		return null;
	}

	public Float getFloatValue(int formatType, int offset) {
		if (mBleSDK == BLESDK.ANDROID) {
			return getGattCharacteristicA().getFloatValue(formatType, offset);
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return mGattCharacteristicS.getFloatValue(formatType, offset);
		} else if (mBleSDK == BLESDK.BROADCOM) {
			return mGattCharacteristicB.getFloatValue(formatType, offset);
		}

		return null;
	}

	public Integer getIntValue(int formatType, int offset) {
		if (mBleSDK == BLESDK.ANDROID) {
			if (formatType == FORMAT_UINT24) {
				byte[] value = getGattCharacteristicA().getValue();
				return byte2uint24(offset, value);
			} else {
				return getGattCharacteristicA().getIntValue(formatType, offset);
			}
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			if (formatType == FORMAT_UINT24) {
				byte[] value = mGattCharacteristicS.getValue();
				return byte2uint24(offset, value);
			} else {
				return mGattCharacteristicS.getIntValue(formatType, offset);
			}
		} else if (mBleSDK == BLESDK.BROADCOM) {
			if (formatType == FORMAT_UINT24) {
				byte[] value = mGattCharacteristicB.getValue();
				return byte2uint24(offset, value);
			} else {
				return mGattCharacteristicB.getIntValue(formatType, offset);
			}
		}

		return null;
	}

	private Integer byte2uint24(int offset, byte[] value) {
		if ((offset + 3) > value.length)
			return null;
		return Integer.valueOf((value[offset] & 0xFF)
				| (value[offset + 1] & 0xFF) << 8
				| (value[offset + 2] & 0xFF) << 16);
	}

	protected com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic getGattCharacteristicS() {
		return mGattCharacteristicS;
	}

	protected void setGattCharacteristicS(
			com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic mSSGattCharacteristic) {
		this.mGattCharacteristicS = mSSGattCharacteristic;
	}

	protected void setGattCharacteristicA(
			android.bluetooth.BluetoothGattCharacteristic mGattCharacteristicA) {
		this.mGattCharacteristicA = mGattCharacteristicA;
	}
}


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BleGattService.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothGattCharacteristic;

import com.xtremeprog.sdk.ble.BleService.BLESDK;

@SuppressLint("NewApi")
public class BleGattService {

	private BLESDK mBleSDK;
	private com.samsung.android.sdk.bt.gatt.BluetoothGattService mGattServiceS;
	private com.broadcom.bt.gatt.BluetoothGattService mGattServiceB;
	private android.bluetooth.BluetoothGattService mGattServiceA;
	private String mName;

	public BleGattService(com.samsung.android.sdk.bt.gatt.BluetoothGattService s) {
		mBleSDK = BLESDK.SAMSUNG;
		mGattServiceS = s;
		initInfo();
	}

	public BleGattService(com.broadcom.bt.gatt.BluetoothGattService s) {
		mBleSDK = BLESDK.BROADCOM;
		mGattServiceB = s;
		initInfo();
	}

	public BleGattService(android.bluetooth.BluetoothGattService s) {
		mBleSDK = BLESDK.ANDROID;
		mGattServiceA = s;
		initInfo();
	}

	private void initInfo() {
		mName = "Unknown Service";
	}

	public UUID getUuid() {
		if (mBleSDK == BLESDK.BROADCOM) {
			return mGattServiceB.getUuid();
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			return mGattServiceS.getUuid();
		} else if (mBleSDK == BLESDK.ANDROID) {
			return mGattServiceA.getUuid();
		}

		return null;
	}

	public List<BleGattCharacteristic> getCharacteristics() {
		ArrayList<BleGattCharacteristic> list = new ArrayList<BleGattCharacteristic>();
		if (mBleSDK == BLESDK.BROADCOM) {
			for (com.broadcom.bt.gatt.BluetoothGattCharacteristic c : mGattServiceB
					.getCharacteristics()) {
				list.add(new BleGattCharacteristic(c));
			}
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			for (Object o : mGattServiceS.getCharacteristics()) {
				com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic c = (com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic) o;
				list.add(new BleGattCharacteristic(c));
			}
		} else if (mBleSDK == BLESDK.ANDROID) {
			for (android.bluetooth.BluetoothGattCharacteristic c : mGattServiceA
					.getCharacteristics()) {
				list.add(new BleGattCharacteristic(c));
			}
		}

		return list;
	}

	public BleGattCharacteristic getCharacteristic(UUID uuid) {
		if (mBleSDK == BLESDK.ANDROID) {
			BluetoothGattCharacteristic c = mGattServiceA
					.getCharacteristic(uuid);
			if (c != null) {
				return new BleGattCharacteristic(c);
			}
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic c = mGattServiceS
					.getCharacteristic(uuid);
			if (c != null) {
				return new BleGattCharacteristic(c);
			}
		} else if (mBleSDK == BLESDK.BROADCOM) {
			com.broadcom.bt.gatt.BluetoothGattCharacteristic c = mGattServiceB
					.getCharacteristic(uuid);
			if (c != null) {
				return new BleGattCharacteristic(c);
			}
		}

		return null;
	}

	public void setInfo(JSONObject info) {
		if (info == null) {
			return;
		}

		try {
			setName(info.getString("name"));
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}

	public String getName() {
		return mName;
	}

	public void setName(String mName) {
		this.mName = mName;
	}
}


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BleRequest.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

public class BleRequest {
	public enum RequestType {
		CONNECT_GATT, DISCOVER_SERVICE, CHARACTERISTIC_NOTIFICATION, CHARACTERISTIC_INDICATION, READ_CHARACTERISTIC, READ_DESCRIPTOR, READ_RSSI, WRITE_CHARACTERISTIC, WRITE_DESCRIPTOR, CHARACTERISTIC_STOP_NOTIFICATION
	};

	public enum FailReason {
		START_FAILED, TIMEOUT, RESULT_FAILED
	}

	public RequestType type;
	public String address;
	public BleGattCharacteristic characteristic;
	public String remark;

	public BleRequest(RequestType type, String address) {
		this.type = type;
		this.address = address;
	}

	public BleRequest(RequestType type, String address,
			BleGattCharacteristic characteristic) {
		this.type = type;
		this.address = address;
		this.characteristic = characteristic;
	}

	public BleRequest(RequestType type, String address,
			BleGattCharacteristic characteristic, String remark) {
		this.type = type;
		this.address = address;
		this.characteristic = characteristic;
		this.remark = remark;
	}

	@Override
	public boolean equals(Object o) {
		if (!(o instanceof BleRequest)) {
			return false;
		}

		BleRequest br = (BleRequest) o;
		return (this.type == br.type && this.address.equals(br.address));
	}
}


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BleService.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;

import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import com.xtremeprog.sdk.ble.BleRequest.FailReason;
import com.xtremeprog.sdk.ble.BleRequest.RequestType;

public class BleService extends Service {
	private static final String TAG = "blelib";

	/** Intent for broadcast */
	public static final String BLE_NOT_SUPPORTED = "com.xtremeprog.sdk.ble.not_supported";
	public static final String BLE_NO_BT_ADAPTER = "com.xtremeprog.sdk.ble.no_bt_adapter";
	public static final String BLE_STATUS_ABNORMAL = "com.xtremeprog.sdk.ble.status_abnormal";
	/**
	 * @see BleService#bleRequestFailed
	 */
	public static final String BLE_REQUEST_FAILED = "com.xtremeprog.sdk.ble.request_failed";
	/**
	 * @see BleService#bleDeviceFound
	 */
	public static final String BLE_DEVICE_FOUND = "com.xtremeprog.sdk.ble.device_found";
	/**
	 * @see BleService#bleGattConnected
	 */
	public static final String BLE_GATT_CONNECTED = "com.xtremeprog.sdk.ble.gatt_connected";
	/**
	 * @see BleService#bleGattDisConnected
	 */
	public static final String BLE_GATT_DISCONNECTED = "com.xtremeprog.sdk.ble.gatt_disconnected";
	/**
	 * @see BleService#bleServiceDiscovered
	 */
	public static final String BLE_SERVICE_DISCOVERED = "com.xtremeprog.sdk.ble.service_discovered";
	/**
	 * @see BleService#bleCharacteristicRead
	 */
	public static final String BLE_CHARACTERISTIC_READ = "com.xtremeprog.sdk.ble.characteristic_read";
	/**
	 * @see BleService#bleCharacteristicNotification
	 */
	public static final String BLE_CHARACTERISTIC_NOTIFICATION = "com.xtremeprog.sdk.ble.characteristic_notification";
	/**
	 * @see BleService#bleCharacteristicIndication
	 */
	public static final String BLE_CHARACTERISTIC_INDICATION = "com.xtremeprog.sdk.ble.characteristic_indication";
	/**
	 * @see BleService#bleCharacteristicWrite
	 */
	public static final String BLE_CHARACTERISTIC_WRITE = "com.xtremeprog.sdk.ble.characteristic_write";
	/**
	 * @see BleService#bleCharacteristicChanged
	 */
	public static final String BLE_CHARACTERISTIC_CHANGED = "com.xtremeprog.sdk.ble.characteristic_changed";

	/** Intent extras */
	public static final String EXTRA_DEVICE = "DEVICE";
	public static final String EXTRA_RSSI = "RSSI";
	public static final String EXTRA_SCAN_RECORD = "SCAN_RECORD";
	public static final String EXTRA_SOURCE = "SOURCE";
	public static final String EXTRA_ADDR = "ADDRESS";
	public static final String EXTRA_CONNECTED = "CONNECTED";
	public static final String EXTRA_STATUS = "STATUS";
	public static final String EXTRA_UUID = "UUID";
	public static final String EXTRA_VALUE = "VALUE";
	public static final String EXTRA_REQUEST = "REQUEST";
	public static final String EXTRA_REASON = "REASON";

	/** Source of device entries in the device list */
	public static final int DEVICE_SOURCE_SCAN = 0;
	public static final int DEVICE_SOURCE_BONDED = 1;
	public static final int DEVICE_SOURCE_CONNECTED = 2;

	public static final UUID DESC_CCC = UUID
			.fromString("00002902-0000-1000-8000-00805f9b34fb");

	public enum BLESDK {
		NOT_SUPPORTED, ANDROID, SAMSUNG, BROADCOM
	}

	private final IBinder mBinder = new LocalBinder();
	private BLESDK mBleSDK;
	private IBle mBle;
	private Queue<BleRequest> mRequestQueue = new LinkedList<BleRequest>();
	private BleRequest mCurrentRequest = null;
	private static final int REQUEST_TIMEOUT = 10 * 10; // total timeout =
														// REQUEST_TIMEOUT *
														// 100ms
	private boolean mCheckTimeout = false;
	private int mElapsed = 0;
	private Thread mRequestTimeout;
	private String mNotificationAddress;

	private Runnable mTimeoutRunnable = new Runnable() {
		@Override
		public void run() {
			Log.d(TAG, "monitoring thread start");
			mElapsed = 0;
			try {
				while (mCheckTimeout) {
					// Log.d(TAG, "monitoring timeout seconds: " + mElapsed);
					Thread.sleep(100);
					mElapsed++;

					if (mElapsed > REQUEST_TIMEOUT && mCurrentRequest != null) {
						Log.d(TAG, "-processrequest type "
								+ mCurrentRequest.type + " address "
								+ mCurrentRequest.address + " [timeout]");
						bleRequestFailed(mCurrentRequest.address,
								mCurrentRequest.type, FailReason.TIMEOUT);
						bleStatusAbnormal("-processrequest type "
								+ mCurrentRequest.type + " address "
								+ mCurrentRequest.address + " [timeout]");
						if (mBle != null) {
							mBle.disconnect(mCurrentRequest.address);
						}
						new Thread(new Runnable() {
							@Override
							public void run() {
								mCurrentRequest = null;
								processNextRequest();
							}
						}, "th-ble").start();
						break;
					}
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
				Log.d(TAG, "monitoring thread exception");
			}
			Log.d(TAG, "monitoring thread stop");
		}
	};

	public static IntentFilter getIntentFilter() {
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(BLE_NOT_SUPPORTED);
		intentFilter.addAction(BLE_NO_BT_ADAPTER);
		intentFilter.addAction(BLE_STATUS_ABNORMAL);
		intentFilter.addAction(BLE_REQUEST_FAILED);
		intentFilter.addAction(BLE_DEVICE_FOUND);
		intentFilter.addAction(BLE_GATT_CONNECTED);
		intentFilter.addAction(BLE_GATT_DISCONNECTED);
		intentFilter.addAction(BLE_SERVICE_DISCOVERED);
		intentFilter.addAction(BLE_CHARACTERISTIC_READ);
		intentFilter.addAction(BLE_CHARACTERISTIC_NOTIFICATION);
		intentFilter.addAction(BLE_CHARACTERISTIC_WRITE);
		intentFilter.addAction(BLE_CHARACTERISTIC_CHANGED);
		return intentFilter;
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	public class LocalBinder extends Binder {
		public BleService getService() {
			return BleService.this;
		}
	}

	@Override
	public void onCreate() {
		mBleSDK = getBleSDK();
		if (mBleSDK == BLESDK.NOT_SUPPORTED) {
			return;
		}

		Log.d(TAG, " " + mBleSDK);
		if (mBleSDK == BLESDK.BROADCOM) {
			mBle = new BroadcomBle(this);
		} else if (mBleSDK == BLESDK.ANDROID) {
			mBle = new AndroidBle(this);
		} else if (mBleSDK == BLESDK.SAMSUNG) {
			mBle = new SamsungBle(this);
		}
	}

	protected void bleNotSupported() {
		Intent intent = new Intent(BleService.BLE_NOT_SUPPORTED);
		sendBroadcast(intent);
	}

	protected void bleNoBtAdapter() {
		Intent intent = new Intent(BleService.BLE_NO_BT_ADAPTER);
		sendBroadcast(intent);
	}

	private BLESDK getBleSDK() {
		if (getPackageManager().hasSystemFeature(
				PackageManager.FEATURE_BLUETOOTH_LE)) {
			// android 4.3
			return BLESDK.ANDROID;
		}

		ArrayList<String> libraries = new ArrayList<String>();
		for (String i : getPackageManager().getSystemSharedLibraryNames()) {
			libraries.add(i);
		}

		if (android.os.Build.VERSION.SDK_INT >= 17) {
			// android 4.2.2
			if (libraries.contains("com.samsung.android.sdk.bt")) {
				return BLESDK.SAMSUNG;
			} else if (libraries.contains("com.broadcom.bt")) {
				return BLESDK.BROADCOM;
			}
		}

		bleNotSupported();
		return BLESDK.NOT_SUPPORTED;
	}

	public IBle getBle() {
		return mBle;
	}

	/**
	 * Send {@link BleService#BLE_DEVICE_FOUND} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_DEVICE} device {@link BluetoothDevice} <br>
	 * {@link BleService#EXTRA_RSSI} rssi int<br>
	 * {@link BleService#EXTRA_SCAN_RECORD} scan record byte[] <br>
	 * {@link BleService#EXTRA_SOURCE} source int, not used now <br>
	 */
	protected void bleDeviceFound(BluetoothDevice device, int rssi,
			byte[] scanRecord, int source) {
		Log.d("blelib", "[" + new Date().toLocaleString() + "] device found "
				+ device.getAddress());
		Intent intent = new Intent(BleService.BLE_DEVICE_FOUND);
		intent.putExtra(BleService.EXTRA_DEVICE, device);
		intent.putExtra(BleService.EXTRA_RSSI, rssi);
		intent.putExtra(BleService.EXTRA_SCAN_RECORD, scanRecord);
		intent.putExtra(BleService.EXTRA_SOURCE, source);
		sendBroadcast(intent);
	}

	/**
	 * Send {@link BleService#BLE_GATT_CONNECTED} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_DEVICE} device {@link BluetoothDevice} <br>
	 */
	protected void bleGattConnected(BluetoothDevice device) {
		Intent intent = new Intent(BLE_GATT_CONNECTED);
		intent.putExtra(EXTRA_DEVICE, device);
		intent.putExtra(EXTRA_ADDR, device.getAddress());
		sendBroadcast(intent);
		requestProcessed(device.getAddress(), RequestType.CONNECT_GATT, true);
	}

	/**
	 * Send {@link BleService#BLE_GATT_DISCONNECTED} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_ADDR} device address {@link String} <br>
	 * 
	 * @param address
	 */
	protected void bleGattDisConnected(String address) {
		Intent intent = new Intent(BLE_GATT_DISCONNECTED);
		intent.putExtra(EXTRA_ADDR, address);
		sendBroadcast(intent);
		requestProcessed(address, RequestType.CONNECT_GATT, false);
	}

	/**
	 * Send {@link BleService#BLE_SERVICE_DISCOVERED} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_ADDR} device address {@link String} <br>
	 * 
	 * @param address
	 */
	protected void bleServiceDiscovered(String address) {
		Intent intent = new Intent(BLE_SERVICE_DISCOVERED);
		intent.putExtra(EXTRA_ADDR, address);
		sendBroadcast(intent);
		requestProcessed(address, RequestType.DISCOVER_SERVICE, true);
	}

	protected void requestProcessed(String address, RequestType requestType,
			boolean success) {
		if (mCurrentRequest != null && mCurrentRequest.type == requestType) {
			clearTimeoutThread();
			Log.d(TAG, "-processrequest type " + requestType + " address "
					+ address + " [success: " + success + "]");
			if (!success) {
				bleRequestFailed(mCurrentRequest.address, mCurrentRequest.type,
						FailReason.RESULT_FAILED);
			}
			new Thread(new Runnable() {
				@Override
				public void run() {
					mCurrentRequest = null;
					processNextRequest();
				}
			}, "th-ble").start();
		}
	}

	private void clearTimeoutThread() {
		if (mRequestTimeout.isAlive()) {
			try {
				mCheckTimeout = false;
				mRequestTimeout.join();
				mRequestTimeout = null;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Send {@link BleService#BLE_CHARACTERISTIC_READ} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_ADDR} device address {@link String} <br>
	 * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>
	 * {@link BleService#EXTRA_STATUS} read status {@link Integer} Not used now <br>
	 * {@link BleService#EXTRA_VALUE} data byte[] <br>
	 * 
	 * @param address
	 * @param uuid
	 * @param status
	 * @param value
	 */
	protected void bleCharacteristicRead(String address, String uuid,
			int status, byte[] value) {
		Intent intent = new Intent(BLE_CHARACTERISTIC_READ);
		intent.putExtra(EXTRA_ADDR, address);
		intent.putExtra(EXTRA_UUID, uuid);
		intent.putExtra(EXTRA_STATUS, status);
		intent.putExtra(EXTRA_VALUE, value);
		sendBroadcast(intent);
		requestProcessed(address, RequestType.READ_CHARACTERISTIC, true);
	}

	protected void addBleRequest(BleRequest request) {
		synchronized (mRequestQueue) {
			mRequestQueue.add(request);
			processNextRequest();
		}
	}

	private synchronized void processNextRequest() {
		if (mCurrentRequest != null) {
			return;
		}

		if (mRequestQueue.isEmpty()) {
			return;
		}
		mCurrentRequest = mRequestQueue.remove();
		Log.d(TAG, "+processrequest type " + mCurrentRequest.type + " address "
				+ mCurrentRequest.address + " remark " + mCurrentRequest.remark);
		startTimeoutThread();
		boolean ret = false;
		switch (mCurrentRequest.type) {
		case CONNECT_GATT:
			ret = ((IBleRequestHandler) mBle).connect(mCurrentRequest.address);
			break;
		case DISCOVER_SERVICE:
			ret = mBle.discoverServices(mCurrentRequest.address);
			break;
		case CHARACTERISTIC_NOTIFICATION:
		case CHARACTERISTIC_INDICATION:
		case CHARACTERISTIC_STOP_NOTIFICATION:
			ret = ((IBleRequestHandler) mBle).characteristicNotification(
					mCurrentRequest.address, mCurrentRequest.characteristic);
			break;
		case READ_CHARACTERISTIC:
			ret = ((IBleRequestHandler) mBle).readCharacteristic(
					mCurrentRequest.address, mCurrentRequest.characteristic);
			break;
		case WRITE_CHARACTERISTIC:
			ret = ((IBleRequestHandler) mBle).writeCharacteristic(
					mCurrentRequest.address, mCurrentRequest.characteristic);
			break;
		case READ_DESCRIPTOR:
			break;
		default:
			break;
		}

		if (!ret) {
			clearTimeoutThread();
			Log.d(TAG, "-processrequest type " + mCurrentRequest.type
					+ " address " + mCurrentRequest.address + " [fail start]");
			bleRequestFailed(mCurrentRequest.address, mCurrentRequest.type,
					FailReason.START_FAILED);
			new Thread(new Runnable() {
				@Override
				public void run() {
					mCurrentRequest = null;
					processNextRequest();
				}
			}, "th-ble").start();
		}
	}

	private void startTimeoutThread() {
		mCheckTimeout = true;
		mRequestTimeout = new Thread(mTimeoutRunnable);
		mRequestTimeout.start();
	}

	protected BleRequest getCurrentRequest() {
		return mCurrentRequest;
	}

	protected void setCurrentRequest(BleRequest mCurrentRequest) {
		this.mCurrentRequest = mCurrentRequest;
	}

	/**
	 * Send {@link BleService#BLE_CHARACTERISTIC_NOTIFICATION} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_ADDR} device address {@link String} <br>
	 * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>
	 * {@link BleService#EXTRA_STATUS} read status {@link Integer} Not used now <br>
	 * 
	 * @param address
	 * @param uuid
	 * @param status
	 */
	protected void bleCharacteristicNotification(String address, String uuid,
			boolean isEnabled, int status) {
		Intent intent = new Intent(BLE_CHARACTERISTIC_NOTIFICATION);
		intent.putExtra(EXTRA_ADDR, address);
		intent.putExtra(EXTRA_UUID, uuid);
		intent.putExtra(EXTRA_VALUE, isEnabled);
		intent.putExtra(EXTRA_STATUS, status);
		sendBroadcast(intent);
		if (isEnabled) {
			requestProcessed(address, RequestType.CHARACTERISTIC_NOTIFICATION,
					true);
		} else {
			requestProcessed(address,
					RequestType.CHARACTERISTIC_STOP_NOTIFICATION, true);
		}
		setNotificationAddress(address);
	}

	/**
	 * Send {@link BleService#BLE_CHARACTERISTIC_INDICATION} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_ADDR} device address {@link String} <br>
	 * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>
	 * {@link BleService#EXTRA_STATUS} read status {@link Integer} Not used now <br>
	 * 
	 * @param address
	 * @param uuid
	 * @param status
	 */
	protected void bleCharacteristicIndication(String address, String uuid,
			int status) {
		Intent intent = new Intent(BLE_CHARACTERISTIC_INDICATION);
		intent.putExtra(EXTRA_ADDR, address);
		intent.putExtra(EXTRA_UUID, uuid);
		intent.putExtra(EXTRA_STATUS, status);
		sendBroadcast(intent);
		requestProcessed(address, RequestType.CHARACTERISTIC_INDICATION, true);
		setNotificationAddress(address);
	}

	/**
	 * Send {@link BleService#BLE_CHARACTERISTIC_WRITE} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_ADDR} device address {@link String} <br>
	 * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>
	 * {@link BleService#EXTRA_STATUS} read status {@link Integer} Not used now <br>
	 * 
	 * @param address
	 * @param uuid
	 * @param status
	 */
	protected void bleCharacteristicWrite(String address, String uuid,
			int status) {
		Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE);
		intent.putExtra(EXTRA_ADDR, address);
		intent.putExtra(EXTRA_UUID, uuid);
		intent.putExtra(EXTRA_STATUS, status);
		sendBroadcast(intent);
		requestProcessed(address, RequestType.WRITE_CHARACTERISTIC, true);
	}

	/**
	 * Send {@link BleService#BLE_CHARACTERISTIC_CHANGED} broadcast. <br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_ADDR} device address {@link String} <br>
	 * {@link BleService#EXTRA_UUID} characteristic uuid {@link String}<br>
	 * {@link BleService#EXTRA_VALUE} data byte[] <br>
	 * 
	 * @param address
	 * @param uuid
	 * @param value
	 */
	protected void bleCharacteristicChanged(String address, String uuid,
			byte[] value) {
		Intent intent = new Intent(BLE_CHARACTERISTIC_CHANGED);
		intent.putExtra(EXTRA_ADDR, address);
		intent.putExtra(EXTRA_UUID, uuid);
		intent.putExtra(EXTRA_VALUE, value);
		sendBroadcast(intent);
	}

	/**
	 * @param reason
	 */
	protected void bleStatusAbnormal(String reason) {
		Intent intent = new Intent(BLE_STATUS_ABNORMAL);
		intent.putExtra(EXTRA_VALUE, reason);
		sendBroadcast(intent);
	}

	/**
	 * Sent when BLE request failed.<br>
	 * <br>
	 * Data in the broadcast intent: <br>
	 * {@link BleService#EXTRA_ADDR} device address {@link String} <br>
	 * {@link BleService#EXTRA_REQUEST} request type
	 * {@link BleRequest.RequestType} <br>
	 * {@link BleService#EXTRA_REASON} fail reason {@link BleRequest.FailReason} <br>
	 */
	protected void bleRequestFailed(String address, RequestType type,
			FailReason reason) {
		Intent intent = new Intent(BLE_REQUEST_FAILED);
		intent.putExtra(EXTRA_ADDR, address);
		intent.putExtra(EXTRA_REQUEST, type);
		intent.putExtra(EXTRA_REASON, reason.ordinal());
		sendBroadcast(intent);
	}

	protected String getNotificationAddress() {
		return mNotificationAddress;
	}

	protected void setNotificationAddress(String mNotificationAddress) {
		this.mNotificationAddress = mNotificationAddress;
	}
}


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BroadcomBle.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;

import com.broadcom.bt.gatt.BluetoothGatt;
import com.broadcom.bt.gatt.BluetoothGattAdapter;
import com.broadcom.bt.gatt.BluetoothGattCallback;
import com.broadcom.bt.gatt.BluetoothGattCharacteristic;
import com.broadcom.bt.gatt.BluetoothGattDescriptor;
import com.broadcom.bt.gatt.BluetoothGattService;
import com.xtremeprog.sdk.ble.BleRequest.RequestType;

public class BroadcomBle implements IBle, IBleRequestHandler {
	private BluetoothAdapter mBtAdapter;
	private BleService mService;
	private BluetoothGatt mBluetoothGatt;
	private boolean mScanning;
	private String mAddress;

	private final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() {
		@Override
		public void onAppRegistered(int status) {
		}

		@Override
		public void onScanResult(BluetoothDevice device, int rssi,
				byte[] scanRecord) {
			mService.bleDeviceFound(device, rssi, scanRecord,
					BleService.DEVICE_SOURCE_SCAN);
		}

		@Override
		public void onConnectionStateChange(BluetoothDevice device, int status,
				int newState) {
			if (mBluetoothGatt == null) {
				return;
			}

			if (newState == BluetoothProfile.STATE_CONNECTED) {
				mService.bleGattConnected(device);
				mBluetoothGatt.discoverServices(device);
				mAddress = device.getAddress();
			} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				mService.bleGattDisConnected(device.getAddress());
				mAddress = null;
			}
		}

		@Override
		public void onServicesDiscovered(BluetoothDevice device, int status) {
			mService.bleServiceDiscovered(device.getAddress());
		}

		@Override
		public void onCharacteristicRead(
				BluetoothGattCharacteristic characteristic, int status) {
			if (status == BluetoothGatt.GATT_SUCCESS) {
				mService.bleCharacteristicRead(mAddress, characteristic
						.getUuid().toString(), status, characteristic
						.getValue());
			}
		}

		@Override
		public void onCharacteristicChanged(
				BluetoothGattCharacteristic characteristic) {
			String address = mService.getNotificationAddress();
			mService.bleCharacteristicChanged(address, characteristic.getUuid()
					.toString(), characteristic.getValue());
		}

		@Override
		public void onDescriptorRead(BluetoothGattDescriptor descriptor,
				int status) {
			BleRequest request = mService.getCurrentRequest();
			String address = request.address;
			byte[] value = descriptor.getValue();
			byte[] val_set = null;
			if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {
				val_set = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
			} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {
				val_set = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;
			} else {
				val_set = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;
			}

			if (Arrays.equals(value, val_set)) {
				if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), true,
							status);
				} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {
					mService.bleCharacteristicIndication(address, descriptor
							.getCharacteristic().getUuid().toString(), status);
				} else {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), false,
							status);
				}
				return;
			}

			if (!descriptor.setValue(val_set)) {
				mService.requestProcessed(address, request.type, false);
			}

			mBluetoothGatt.writeDescriptor(descriptor);
		};

		@Override
		public void onDescriptorWrite(BluetoothGattDescriptor descriptor,
				int status) {
			BleRequest request = mService.getCurrentRequest();
			String address = request.address;
			if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION
					|| request.type == RequestType.CHARACTERISTIC_INDICATION
					|| request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {
				if (status != BluetoothGatt.GATT_SUCCESS) {
					mService.requestProcessed(address, request.type, false);
					return;
				}

				if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), true,
							status);
				} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {
					mService.bleCharacteristicIndication(address, descriptor
							.getCharacteristic().getUuid().toString(), status);
				} else {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), false,
							status);
				}
				return;
			}
		};
	};

	private final BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() {
		@Override
		public void onServiceConnected(int profile, BluetoothProfile proxy) {
			mBluetoothGatt = (BluetoothGatt) proxy;
			mBluetoothGatt.registerApp(mGattCallbacks);
		}

		@Override
		public void onServiceDisconnected(int profile) {
			for ( BluetoothDevice d : mBluetoothGatt.getConnectedDevices() ) {
				mBluetoothGatt.cancelConnection(d);
			}
			mBluetoothGatt = null;
		}
	};

	public BroadcomBle(BleService service) {
		mService = service;
		mBtAdapter = BluetoothAdapter.getDefaultAdapter();
		if (mBtAdapter == null) {
			mService.bleNoBtAdapter();
			return;
		}
		BluetoothGattAdapter.getProfileProxy(mService, mProfileServiceListener,
				BluetoothGattAdapter.GATT);
	}

	@Override
	public void startScan() {
		if (mScanning) {
			return;
		}

		if (mBluetoothGatt == null) {
			mScanning = false;
			return;
		}

		mScanning = true;
		mBluetoothGatt.startScan();
	}

	@Override
	public void stopScan() {
		if (!mScanning || mBluetoothGatt == null) {
			return;
		}

		mScanning = false;
		mBluetoothGatt.stopScan();
	}

	@Override
	public boolean adapterEnabled() {
		if (mBtAdapter != null) {
			return mBtAdapter.isEnabled();
		}
		return false;
	}

	@Override
	public boolean connect(String address) {
		BluetoothDevice device = mBtAdapter.getRemoteDevice(address);
		return mBluetoothGatt.connect(device, false);
	}

	@Override
	public void disconnect(String address) {
		BluetoothDevice device = mBtAdapter.getRemoteDevice(address);
		mBluetoothGatt.cancelConnection(device);
	}

	@Override
	public ArrayList<BleGattService> getServices(String address) {
		ArrayList<BleGattService> list = new ArrayList<BleGattService>();
		BluetoothDevice device = mBtAdapter.getRemoteDevice(address);
		List<BluetoothGattService> services = mBluetoothGatt
				.getServices(device);
		for (BluetoothGattService s : services) {
			list.add(new BleGattService(s));
		}
		return list;
	}

	@Override
	public boolean requestReadCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		mService.addBleRequest(new BleRequest(RequestType.READ_CHARACTERISTIC,
				address, characteristic));
		return true;
	}

	@Override
	public boolean discoverServices(String address) {
		return true;
	}

	@Override
	public boolean readCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		if (characteristic.getGattCharacteristicB() != null) {
			return mBluetoothGatt.readCharacteristic(characteristic
					.getGattCharacteristicB());
		}
		return false;
	}

	@Override
	public BleGattService getService(String address, UUID uuid) {
		BluetoothGattService service = mBluetoothGatt.getService(
				mBtAdapter.getRemoteDevice(address), uuid);
		if (service == null) {
			return null;
		} else {
			return new BleGattService(service);
		}
	}

	@Override
	public boolean requestCharacteristicNotification(String address,
			BleGattCharacteristic characteristic) {
		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_NOTIFICATION, address,
				characteristic));
		return true;
	}

	@Override
	public boolean characteristicNotification(String address,
			BleGattCharacteristic characteristic) {
		BleRequest request = mService.getCurrentRequest();
		BluetoothGattCharacteristic b = characteristic.getGattCharacteristicB();

		boolean enable = true;
		if (request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {
			enable = false;
		}
		if (!mBluetoothGatt.setCharacteristicNotification(b, enable)) {
			return false;
		}

		BluetoothGattDescriptor descriptor = b
				.getDescriptor(BleService.DESC_CCC);
		if (descriptor == null) {
			return false;
		}

		return mBluetoothGatt.readDescriptor(descriptor);
	}

	@Override
	public boolean requestWriteCharacteristic(String address,
			BleGattCharacteristic characteristic, String remark) {
		mService.addBleRequest(new BleRequest(RequestType.WRITE_CHARACTERISTIC,
				address, characteristic));
		return true;
	}

	@Override
	public boolean writeCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		return mBluetoothGatt.writeCharacteristic(characteristic
				.getGattCharacteristicB());
	}

	@Override
	public boolean requestConnect(String address) {
		if (mAddress != null) {
			return false;
		}
		mService.addBleRequest(new BleRequest(RequestType.CONNECT_GATT, address));
		return true;
	}

	@Override
	public String getBTAdapterMacAddr() {
		if (mBtAdapter != null) {
			return mBtAdapter.getAddress();
		}
		return null;
	}

	@Override
	public boolean requestIndication(String address,
			BleGattCharacteristic characteristic) {
		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_INDICATION, address, characteristic));
		return true;
	}

	@Override
	public boolean requestStopNotification(String address,
			BleGattCharacteristic characteristic) {
		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_STOP_NOTIFICATION, address,
				characteristic));
		return true;
	}
}


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/IBle.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

import java.util.ArrayList;
import java.util.UUID;

public interface IBle {

	public String getBTAdapterMacAddr();

	/**
	 * Will receive broadcast {@link BleService#BLE_DEVICE_FOUND} if device
	 * found.
	 */
	public void startScan();

	/**
	 * Stop BLE scan.
	 */
	public void stopScan();

	/**
	 * Check if bluetooth adapter is enabled.
	 * 
	 * @return enabled
	 */
	public boolean adapterEnabled();

	/**
	 * Disconnect BLE device. Will receive
	 * {@link BleService#BLE_GATT_DISCONNECTED} broadcast if device
	 * disconnected.
	 * 
	 * @param address
	 *            BLE device address.
	 */
	public void disconnect(String address);

	/**
	 * Discover BLE services. Will receive
	 * {@link BleService#BLE_SERVICE_DISCOVERED} broadcast if device service
	 * discovered.
	 * 
	 * @param address
	 * @return
	 */
	public boolean discoverServices(String address);

	/**
	 * Get discovered services for BLE device. Call this function after
	 * {@link BleService#BLE_SERVICE_DISCOVERED} broadcast is received.
	 * 
	 * @param address
	 * @return List of {@link BleGattService}
	 */
	public ArrayList<BleGattService> getServices(String address);

	/**
	 * Get discovered service by uuid. Call this function after
	 * {@link BleService#BLE_SERVICE_DISCOVERED} broadcast is received.
	 * 
	 * @param address
	 * @param uuid
	 * @return {@link BleGattService}
	 */
	public BleGattService getService(String address, UUID uuid);

	/**
	 * Request to connect a BLE device by address. Will receive
	 * {@link BleService#BLE_GATT_CONNECTED} broadcast if device connected.
	 * 
	 * @param address
	 * @return if request be inserted into queue successfully.
	 */
	public boolean requestConnect(String address);

	/**
	 * Request to read characteristic. Will receive
	 * {@link BleService#BLE_CHARACTERISTIC_READ} broadcast if characteristic
	 * read.
	 * 
	 * @param address
	 * @param characteristic
	 *            Get characteristic from {@link BleGattService}
	 * @return if request be inserted into queue successfully.
	 */
	public boolean requestReadCharacteristic(String address,
			BleGattCharacteristic characteristic);

	/**
	 * Request characteristic notification. Will receive
	 * {@link BleService#BLE_CHARACTERISTIC_NOTIFICATION} broadcast if
	 * notification set OK. When the characteristic's value changed,
	 * {@link BleService#BLE_CHARACTERISTIC_CHANGED} broadcast will be received
	 * also.
	 * 
	 * @param address
	 * @param characteristic
	 *            Get characteristic from {@link BleGattService}
	 * @return if request be inserted into queue successfully.
	 */
	public boolean requestCharacteristicNotification(String address,
			BleGattCharacteristic characteristic);

	public boolean requestStopNotification(String address,
			BleGattCharacteristic characteristic);

	/**
	 * Request characteristic indication. Will receive
	 * {@link BleService#BLE_CHARACTERISTIC_INDICATION} broadcast if indication
	 * set OK. When the characteristic's value changed,
	 * {@link BleService#BLE_CHARACTERISTIC_CHANGED} broadcast will be received
	 * also.
	 * 
	 * @param address
	 * @param characteristic
	 *            Get characteristic from {@link BleGattService}
	 * @return if request be inserted into queue successfully.
	 */
	public boolean requestIndication(String address,
			BleGattCharacteristic characteristic);

	/**
	 * Request write characteristic value. Will receive
	 * {@link BleService#BLE_CHARACTERISTIC_WRITE} broadcast if characteristic
	 * value be written.
	 * 
	 * @param address
	 * @param characteristic
	 *            Get characteristic from {@link BleGattService}
	 * @param remark
	 *            For debug purpose.
	 * @return if request be inserted into queue successfully.
	 */
	public boolean requestWriteCharacteristic(String address,
			BleGattCharacteristic characteristic, String remark);
}


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/IBleRequestHandler.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

public interface IBleRequestHandler {

	public boolean connect(String address);

	/**
	 * @param address
	 * @param characteristic
	 * @return
	 */
	public boolean readCharacteristic(String address,
			BleGattCharacteristic characteristic);

	/**
	 * @param address
	 * @param characteristic
	 * @return
	 */
	public boolean characteristicNotification(String address,
			BleGattCharacteristic characteristic);

	/**
	 * @param address
	 * @param characteristic
	 * @return
	 */
	public boolean writeCharacteristic(String address,
			BleGattCharacteristic characteristic);
}


================================================
FILE: BleLibrary/src/com/xtremeprog/sdk/ble/SamsungBle.java
================================================
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.xtremeprog.sdk.ble;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.util.Log;

import com.samsung.android.sdk.bt.gatt.BluetoothGatt;
import com.samsung.android.sdk.bt.gatt.BluetoothGattAdapter;
import com.samsung.android.sdk.bt.gatt.BluetoothGattCallback;
import com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic;
import com.samsung.android.sdk.bt.gatt.BluetoothGattDescriptor;
import com.samsung.android.sdk.bt.gatt.BluetoothGattService;
import com.xtremeprog.sdk.ble.BleRequest.RequestType;

public class SamsungBle implements IBle, IBleRequestHandler {

	protected static final String TAG = "blelib";

	private BluetoothAdapter mBtAdapter;
	private BleService mService;
	private BluetoothGatt mBluetoothGatt;
	private boolean mScanning;

	private final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() {
		@Override
		public void onAppRegistered(int status) {
		}

		@Override
		public void onScanResult(BluetoothDevice device, int rssi,
				byte[] scanRecord) {
			mService.bleDeviceFound(device, rssi, scanRecord,
					BleService.DEVICE_SOURCE_SCAN);
		}

		@Override
		public void onConnectionStateChange(BluetoothDevice device, int status,
				int newState) {
			if (mBluetoothGatt == null) {
				return;
			}

			if (status != BluetoothGatt.GATT_SUCCESS) {
				disconnect(device.getAddress());
				mService.bleGattDisConnected(device.getAddress());
				return;
			}

			if (newState == BluetoothProfile.STATE_CONNECTED) {
				mService.bleGattConnected(device);
				mService.addBleRequest(new BleRequest(
						RequestType.DISCOVER_SERVICE, device.getAddress()));
			} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				mService.bleGattDisConnected(device.getAddress());
				disconnect(device.getAddress());
			}
		}

		@Override
		public void onServicesDiscovered(BluetoothDevice device, int status) {
			String address = device.getAddress();
			if (status != BluetoothGatt.GATT_SUCCESS) {
				disconnect(address);
				mService.bleGattDisConnected(address);
				mService.requestProcessed(address,
						RequestType.DISCOVER_SERVICE, false);
				return;
			}
			mService.bleServiceDiscovered(device.getAddress());
		}

		@Override
		public void onCharacteristicRead(
				BluetoothGattCharacteristic characteristic, int status) {
			BleRequest request = mService.getCurrentRequest();
			String address = request.address;
			if (status != BluetoothGatt.GATT_SUCCESS) {
				mService.requestProcessed(address,
						RequestType.READ_CHARACTERISTIC, false);
				return;
			}
			mService.bleCharacteristicRead(address, characteristic.getUuid()
					.toString(), status, characteristic.getValue());
		}

		@Override
		public void onCharacteristicChanged(
				BluetoothGattCharacteristic characteristic) {
			Log.d(TAG, "onCharacteristicChanged");
			String address = mService.getNotificationAddress();
			mService.bleCharacteristicChanged(address, characteristic.getUuid()
					.toString(), characteristic.getValue());
		}

		@Override
		public void onCharacteristicWrite(
				BluetoothGattCharacteristic characteristic, int status) {
			BleRequest request = mService.getCurrentRequest();
			String address = request.address;
			if (status != BluetoothGatt.GATT_SUCCESS) {
				mService.requestProcessed(address,
						RequestType.WRITE_CHARACTERISTIC, false);
				return;
			}
			mService.bleCharacteristicWrite(address, characteristic.getUuid()
					.toString(), status);
		};

		@Override
		public void onDescriptorRead(BluetoothGattDescriptor descriptor,
				int status) {
			BleRequest request = mService.getCurrentRequest();
			String address = request.address;
			byte[] value = descriptor.getValue();
			byte[] val_set = null;
			if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {
				val_set = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
			} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {
				val_set = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE;
			} else {
				val_set = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;
			}

			if (Arrays.equals(value, val_set)) {
				if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), true,
							status);
				} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {
					mService.bleCharacteristicIndication(address, descriptor
							.getCharacteristic().getUuid().toString(), status);
				} else {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), false,
							status);
				}
				return;
			}

			if (!descriptor.setValue(val_set)) {
				mService.requestProcessed(address, request.type, false);
			}

			mBluetoothGatt.writeDescriptor(descriptor);
		};

		@Override
		public void onDescriptorWrite(BluetoothGattDescriptor descriptor,
				int status) {
			BleRequest request = mService.getCurrentRequest();
			String address = request.address;
			if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION
					|| request.type == RequestType.CHARACTERISTIC_INDICATION
					|| request.type == RequestType.CHARACTERISTIC_STOP_NOTIFICATION) {
				if (status != BluetoothGatt.GATT_SUCCESS) {
					mService.requestProcessed(address, request.type, false);
					return;
				}

				if (request.type == RequestType.CHARACTERISTIC_NOTIFICATION) {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), true,
							status);
				} else if (request.type == RequestType.CHARACTERISTIC_INDICATION) {
					mService.bleCharacteristicIndication(address, descriptor
							.getCharacteristic().getUuid().toString(), status);
				} else {
					mService.bleCharacteristicNotification(address, descriptor
							.getCharacteristic().getUuid().toString(), false,
							status);
				}
				return;
			}

		};
	};

	private final BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() {
		@Override
		public void onServiceConnected(int profile, BluetoothProfile proxy) {
			mBluetoothGatt = (BluetoothGatt) proxy;
			mBluetoothGatt.registerApp(mGattCallbacks);
		}

		@Override
		public void onServiceDisconnected(int profile) {
			mBluetoothGatt = null;
		}
	};

	public SamsungBle(BleService service) {
		mService = service;
		mBtAdapter = BluetoothAdapter.getDefaultAdapter();
		if (mBtAdapter == null) {
			mService.bleNoBtAdapter();
			return;
		}
		BluetoothGattAdapter.getProfileProxy(mService, mProfileServiceListener,
				BluetoothGattAdapter.GATT);
	}

	@Override
	public void startScan() {
		if (mScanning) {
			return;
		}

		if (mBluetoothGatt == null) {
			mScanning = false;
			return;
		}

		mScanning = true;
		mBluetoothGatt.startScan();
	}

	@Override
	public void stopScan() {
		if (!mScanning || mBluetoothGatt == null) {
			return;
		}

		mScanning = false;
		mBluetoothGatt.stopScan();
	}

	@Override
	public boolean adapterEnabled() {
		if (mBtAdapter != null) {
			return mBtAdapter.isEnabled();
		}
		return false;
	}

	@Override
	public boolean connect(String address) {
		BluetoothDevice device = mBtAdapter.getRemoteDevice(address);
		return mBluetoothGatt.connect(device, false);
	}

	@Override
	public void disconnect(String address) {
		BluetoothDevice device = mBtAdapter.getRemoteDevice(address);
		mBluetoothGatt.cancelConnection(device);
	}

	@Override
	public ArrayList<BleGattService> getServices(String address) {
		ArrayList<BleGattService> list = new ArrayList<BleGattService>();
		BluetoothDevice device = mBtAdapter.getRemoteDevice(address);
		List<BluetoothGattService> services = mBluetoothGatt
				.getServices(device);
		for (BluetoothGattService s : services) {
			list.add(new BleGattService(s));
		}
		return list;
	}

	@Override
	public boolean requestReadCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		mService.addBleRequest(new BleRequest(RequestType.READ_CHARACTERISTIC,
				address, characteristic));
		return true;
	}

	@Override
	public boolean discoverServices(String address) {
		return mBluetoothGatt.discoverServices(mBtAdapter
				.getRemoteDevice(address));
	}

	@Override
	public boolean readCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		return mBluetoothGatt.readCharacteristic(characteristic
				.getGattCharacteristicS());
	}

	@Override
	public BleGattService getService(String address, UUID uuid) {
		BluetoothGattService service = mBluetoothGatt.getService(
				mBtAdapter.getRemoteDevice(address), uuid);
		if (service == null) {
			return null;
		} else {
			return new BleGattService(service);
		}
	}

	@Override
	public boolean requestCharacteristicNotification(String address,
			BleGattCharacteristic characteristic) {
		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_NOTIFICATION, address,
				characteristic));
		return true;
	}

	@Override
	public boolean characteristicNotification(String address,
			BleGattCharacteristic characteristic) {
		BluetoothGattCharacteristic c = characteristic.getGattCharacteristicS();

		if (!mBluetoothGatt.setCharacteristicNotification(c, true)) {
			return false;
		}

		BluetoothGattDescriptor descriptor = c
				.getDescriptor(BleService.DESC_CCC);
		if (descriptor == null) {
			return false;
		}

		return mBluetoothGatt.readDescriptor(descriptor);
	}

	@Override
	public boolean requestWriteCharacteristic(String address,
			BleGattCharacteristic characteristic, String remark) {
		mService.addBleRequest(new BleRequest(RequestType.WRITE_CHARACTERISTIC,
				address, characteristic));
		return true;
	}

	@Override
	public boolean writeCharacteristic(String address,
			BleGattCharacteristic characteristic) {
		return mBluetoothGatt.writeCharacteristic(characteristic
				.getGattCharacteristicS());
	}

	@Override
	public boolean requestConnect(String address) {
		mService.addBleRequest(new BleRequest(RequestType.CONNECT_GATT, address));
		return true;
	}

	@Override
	public String getBTAdapterMacAddr() {
		if (mBtAdapter != null) {
			return mBtAdapter.getAddress();
		}
		return null;
	}

	@Override
	public boolean requestIndication(String address,
			BleGattCharacteristic characteristic) {
		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_INDICATION, address, characteristic));
		return true;
	}

	@Override
	public boolean requestStopNotification(String address,
			BleGattCharacteristic characteristic) {
		mService.addBleRequest(new BleRequest(
				RequestType.CHARACTERISTIC_STOP_NOTIFICATION, address,
				characteristic));
		return true;
	}
}


================================================
FILE: BluetoothLeGatt/.classpath
================================================
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
	<classpathentry kind="src" path="src"/>
	<classpathentry kind="src" path="gen"/>
	<classpathentry kind="output" path="bin/classes"/>
</classpath>


================================================
FILE: BluetoothLeGatt/.project
================================================
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
	<name>DeviceScanActivity</name>
	<comment></comment>
	<projects>
	</projects>
	<buildSpec>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>org.eclipse.jdt.core.javabuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
		<buildCommand>
			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
			<arguments>
			</arguments>
		</buildCommand>
	</buildSpec>
	<natures>
		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
		<nature>org.eclipse.jdt.core.javanature</nature>
	</natures>
</projectDescription>


================================================
FILE: BluetoothLeGatt/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The Android Open Source Project

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

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

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bluetooth.le"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="17"
        android:targetSdkVersion="17" />
    <!--
    Declare this required feature if you want to make the app available to BLE-capable
    devices only.  If you want to make your app available to devices that don't support BLE,
    you should omit this in the manifest.  Instead, determine BLE capability by using
    PackageManager.hasSystemFeature(FEATURE_BLUETOOTH_LE)
    -->
    <uses-feature
        android:name="android.hardware.bluetooth_le"
        android:required="true" />

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:name="com.example.bluetooth.le.BleApplication"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Holo.Light" >
        <activity
            android:name="com.example.bluetooth.le.DeviceScanActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.example.bluetooth.le.DeviceControlActivity" >
        </activity>

        <service
            android:name="com.xtremeprog.sdk.ble.BleService"
            android:enabled="true" />

        <activity
            android:name="com.example.bluetooth.le.CharacteristicActivity"
            android:label="@string/title_activity_characteristic" >
        </activity>
    </application>

</manifest>

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

# Project target.
target=android-17
android.library.reference.1=../BleLibrary


================================================
FILE: BluetoothLeGatt/res/layout/actionbar_indeterminate_progress.xml
================================================
<!--
  Copyright 2013 Google Inc.

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

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

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_height="wrap_content"
             android:layout_width="56dp"
             android:minWidth="56dp">
    <ProgressBar android:layout_width="32dp"
                 android:layout_height="32dp"
                 android:layout_gravity="center"/>
</FrameLayout>


================================================
FILE: BluetoothLeGatt/res/layout/activity_characteristic.xml
================================================
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp"
    tools:context="com.example.bluetooth.le.CharacteristicActivity" >

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/tv_uuid"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="ASCII: "
            android:textSize="18sp" />

        <TextView
            android:id="@+id/tv_ascii"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="HEX: "
            android:textSize="18sp" />

        <TextView
            android:id="@+id/tv_hex"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/btn_read"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Read"
            android:visibility="gone" />

        <Button
            android:id="@+id/btn_notify"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start Notify"
            android:visibility="gone" />

        <Button
            android:id="@+id/btn_indicate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Indicate"
            android:visibility="gone" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/ll_write"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:visibility="gone" >

        <Button
            android:id="@+id/btn_write"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Write" />

        <EditText
            android:id="@+id/et_hex"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="0x0A30BC" />
    </LinearLayout>

</LinearLayout>

================================================
FILE: BluetoothLeGatt/res/layout/gatt_services_characteristics.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2013 The Android Open Source Project

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

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

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/label_device_address"
            android:textSize="18sp" />

        <Space
            android:layout_width="5dp"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/device_address"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="18sp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/label_state"
            android:textSize="18sp" />

        <Space
            android:layout_width="5dp"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/connection_state"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/disconnected"
            android:textSize="18sp" />
    </LinearLayout>

    <ExpandableListView
        android:id="@+id/gatt_services_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

================================================
FILE: BluetoothLeGatt/res/layout/listitem_device.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 The Android Open Source Project

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

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

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="wrap_content">
    <TextView android:id="@+id/device_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="24dp"/>
    <TextView android:id="@+id/device_address"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="12dp"/>
</LinearLayout>

================================================
FILE: BluetoothLeGatt/res/menu/characteristic.xml
================================================
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.example.bluetooth.le.CharacteristicActivity" >

    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:showAsAction="never"
        android:title="@string/action_settings"/>

</menu>


================================================
FILE: BluetoothLeGatt/res/menu/gatt_services.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 The Android Open Source Project

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

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

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_refresh"
          android:checkable="false"
          android:orderInCategory="1"
          android:showAsAction="ifRoom"/>
    <item android:id="@+id/menu_connect"
          android:title="@string/menu_connect"
          android:orderInCategory="100"
          android:showAsAction="ifRoom|withText"/>
    <item android:id="@+id/menu_disconnect"
          android:title="@string/menu_disconnect"
          android:orderInCategory="101"
          android:showAsAction="ifRoom|withText"/>
</menu>


================================================
FILE: BluetoothLeGatt/res/menu/main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2013 The Android Open Source Project

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

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

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_refresh"
          android:checkable="false"
          android:orderInCategory="1"
          android:showAsAction="ifRoom"/>
    <item android:id="@+id/menu_scan"
          android:title="@string/menu_scan"
          android:orderInCategory="100"
          android:showAsAction="ifRoom|withText"/>
    <item android:id="@+id/menu_stop"
          android:title="@string/menu_stop"
          android:orderInCategory="101"
          android:showAsAction="ifRoom|withText"/>
</menu>


================================================
FILE: BluetoothLeGatt/res/values/dimens.xml
================================================
<resources>

    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>

</resources>


================================================
FILE: BluetoothLeGatt/res/values/strings.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<!--
     Copyright (C) 2013 The Android Open Source Project

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

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

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

    <string name="app_name">BLE Sample</string>
    <string name="ble_not_supported">BLE is not supported</string>
    <string name="label_data">Data:</string>
    <string name="label_device_address">Device address:</string>
    <string name="label_state">State:</string>
    <string name="no_data">No data</string>
    <string name="connected">Connected</string>
    <string name="disconnected">Disconnected</string>
    <string name="title_devices">BLE Device Scan</string>
    <string name="error_bluetooth_not_supported">Bluetooth not supported.</string>
    <string name="unknown_device">Unknown device</string>
    <string name="unknown_characteristic">Unknown characteristic</string>
    <string name="unknown_service">Unknown service</string>

    <!-- Menu items -->
    <string name="menu_connect">Connect</string>
    <string name="menu_disconnect">Disconnect</string>
    <string name="menu_scan">Scan</string>
    <string name="menu_stop">Stop</string>
    <string name="title_activity_characteristic">CharacteristicActivity</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>

</resources>


================================================
FILE: BluetoothLeGatt/res/values-w820dp/dimens.xml
================================================
<resources>

    <!--
         Example customization of dimensions originally defined in res/values/dimens.xml
         (such as screen margins) for screens with more than 820dp of available width. This
         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
    -->
    <dimen name="activity_horizontal_margin">64dp</dimen>

</resources>


================================================
FILE: BluetoothLeGatt/src/com/example/bluetooth/le/BleApplication.java
================================================
package com.example.bluetooth.le;

import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;

import com.xtremeprog.sdk.ble.BleService;
import com.xtremeprog.sdk.ble.IBle;

public class BleApplication extends Application {

	private BleService mService;
	private IBle mBle;

	private final ServiceConnection mServiceConnection = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName className,
				IBinder rawBinder) {
			mService = ((BleService.LocalBinder) rawBinder).getService();
			mBle = mService.getBle();
			if (mBle != null && !mBle.adapterEnabled()) {
				// TODO: enalbe adapter
			}
		}

		@Override
		public void onServiceDisconnected(ComponentName classname) {
			mService = null;
		}
	};

	@Override
	public void onCreate() {
		super.onCreate();

		Intent bindIntent = new Intent(this, BleService.class);
		bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
	}
	
	public IBle getIBle() {
		return mBle;
	}
}


================================================
FILE: BluetoothLeGatt/src/com/example/bluetooth/le/CharacteristicActivity.java
================================================
package com.example.bluetooth.le;

import java.util.UUID;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.xtremeprog.sdk.ble.BleGattCharacteristic;
import com.xtremeprog.sdk.ble.BleService;
import com.xtremeprog.sdk.ble.IBle;

public class CharacteristicActivity extends Activity {

	private String mDeviceAddress;
	private IBle mBle;
	private BleGattCharacteristic mCharacteristic;

	private View.OnClickListener onClickListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			if (v.getId() == R.id.btn_read) {
				mBle.requestReadCharacteristic(mDeviceAddress, mCharacteristic);
			} else if (v.getId() == R.id.btn_notify) {
				if (mNotifyStarted) {
					mBle.requestStopNotification(mDeviceAddress,
							mCharacteristic);
				} else {
					mBle.requestCharacteristicNotification(mDeviceAddress,
							mCharacteristic);
				}
			} else if (v.getId() == R.id.btn_indicate) {
				mBle.requestIndication(mDeviceAddress, mCharacteristic);
			} else if (v.getId() == R.id.btn_write) {
				String val = et_hex.getText().toString();
				try {
					byte[] data = Hex.decodeHex(val.toCharArray());
					mCharacteristic.setValue(data);
					mBle.requestWriteCharacteristic(mDeviceAddress,
							mCharacteristic, "");
				} catch (DecoderException e) {
					e.printStackTrace();
				}
			}
		}
	};

	private final BroadcastReceiver mBleReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			Bundle extras = intent.getExtras();
			if (!mDeviceAddress.equals(extras.getString(BleService.EXTRA_ADDR))) {
				return;
			}

			String uuid = extras.getString(BleService.EXTRA_UUID);
			if (uuid != null
					&& !mCharacteristic.getUuid().toString().equals(uuid)) {
				return;
			}

			String action = intent.getAction();
			if (BleService.BLE_GATT_DISCONNECTED.equals(action)) {
				Toast.makeText(CharacteristicActivity.this,
						"Device disconnected...", Toast.LENGTH_SHORT).show();
				finish();
			} else if (BleService.BLE_CHARACTERISTIC_READ.equals(action)
					|| BleService.BLE_CHARACTERISTIC_CHANGED.equals(action)) {
				byte[] val = extras.getByteArray(BleService.EXTRA_VALUE);
				tv_ascii.setText(new String(val));
				tv_hex.setText("0x" + new String(Hex.encodeHex(val)));
			} else if (BleService.BLE_CHARACTERISTIC_NOTIFICATION
					.equals(action)) {
				Toast.makeText(CharacteristicActivity.this,
						"Notification state changed!", Toast.LENGTH_SHORT)
						.show();
				mNotifyStarted = extras.getBoolean(BleService.EXTRA_VALUE);
				if (mNotifyStarted) {
					btn_notify.setText("Stop Notify");
				} else {
					btn_notify.setText("Start Notify");
				}
			} else if (BleService.BLE_CHARACTERISTIC_INDICATION.equals(action)) {
				Toast.makeText(CharacteristicActivity.this,
						"Indication state changed!", Toast.LENGTH_SHORT).show();
			} else if (BleService.BLE_CHARACTERISTIC_WRITE.equals(action)) {
				Toast.makeText(CharacteristicActivity.this, "Write success!",
						Toast.LENGTH_SHORT).show();
			}
		}
	};
	private TextView tv_ascii;
	private TextView tv_hex;
	private EditText et_hex;
	private boolean mNotifyStarted;
	private Button btn_notify;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_characteristic);

		mDeviceAddress = getIntent().getStringExtra("address");
		String service = getIntent().getStringExtra("service");
		String characteristic = getIntent().getStringExtra("characteristic");
		BleApplication app = (BleApplication) getApplication();
		mBle = app.getIBle();
		mCharacteristic = mBle.getService(mDeviceAddress,
				UUID.fromString(service)).getCharacteristic(
				UUID.fromString(characteristic));
		mNotifyStarted = false;

		TextView tv_name = (TextView) findViewById(R.id.tv_name);
		TextView tv_uuid = (TextView) findViewById(R.id.tv_uuid);
		tv_ascii = (TextView) findViewById(R.id.tv_ascii);
		tv_hex = (TextView) findViewById(R.id.tv_hex);

		tv_name.setText(Utils.BLE_CHARACTERISTICS.containsKey(characteristic) ? Utils.BLE_CHARACTERISTICS
				.get(characteristic) : "unknown characteristic");
		tv_uuid.setText(mCharacteristic.getUuid().toString());

		View btn_read = findViewById(R.id.btn_read);
		btn_notify = (Button) findViewById(R.id.btn_notify);
		View btn_indicate = findViewById(R.id.btn_indicate);
		View ll_write = findViewById(R.id.ll_write);
		View btn_write = findViewById(R.id.btn_write);
		et_hex = (EditText) findViewById(R.id.et_hex);
		btn_read.setOnClickListener(onClickListener);
		btn_notify.setOnClickListener(onClickListener);
		btn_indicate.setOnClickListener(onClickListener);
		btn_write.setOnClickListener(onClickListener);

		final int charaProp = mCharacteristic.getProperties();
		if ((charaProp & BleGattCharacteristic.PROPERTY_READ) > 0) {
			btn_read.setVisibility(View.VISIBLE);
		}
		if ((charaProp & BleGattCharacteristic.PROPERTY_NOTIFY) > 0) {
			btn_notify.setVisibility(View.VISIBLE);
		}
		if ((charaProp & BleGattCharacteristic.PROPERTY_INDICATE) > 0) {
			btn_indicate.setVisibility(View.VISIBLE);
		}
		if ((charaProp & BleGattCharacteristic.PROPERTY_WRITE) > 0) {
			ll_write.setVisibility(View.VISIBLE);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.characteristic, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onResume() {
		super.onResume();
		registerReceiver(mBleReceiver, BleService.getIntentFilter());
	}

	@Override
	public void onPanelClosed(int featureId, Menu menu) {
		super.onPanelClosed(featureId, menu);
		unregisterReceiver(mBleReceiver);
	}
}


================================================
FILE: BluetoothLeGatt/src/com/example/bluetooth/le/DeviceControlActivity.java
================================================
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.example.bluetooth.le;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;

import com.xtremeprog.sdk.ble.BleGattCharacteristic;
import com.xtremeprog.sdk.ble.BleGattService;
import com.xtremeprog.sdk.ble.BleService;
import com.xtremeprog.sdk.ble.IBle;
//import android.bluetooth.BluetoothGattCharacteristic;
//import android.bluetooth.BluetoothGattService;

/**
 * For a given BLE device, this Activity provides the user interface to connect,
 * display data, and display GATT services and characteristics supported by the
 * device. The Activity communicates with {@code BluetoothLeService}, which in
 * turn interacts with the Bluetooth LE API.
 */
public class DeviceControlActivity extends Activity {
	private final static String TAG = DeviceControlActivity.class
			.getSimpleName();

	public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
	public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";

	private TextView mConnectionState;
	private String mDeviceName;
	private String mDeviceAddress;
	private ExpandableListView mGattServicesList;
	private ArrayList<ArrayList<BleGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BleGattCharacteristic>>();
	private boolean mConnected = false;

	private final String LIST_NAME = "NAME";
	private final String LIST_UUID = "UUID";

	protected IBle mBle;

	// Handles various events fired by the Service.
	// ACTION_GATT_CONNECTED: connected to a GATT server.
	// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
	// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
	// ACTION_DATA_AVAILABLE: received data from the device. This can be a
	// result of read
	// or notification operations.
	private final BroadcastReceiver mBleReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			Bundle extras = intent.getExtras();
			if (!mDeviceAddress.equals(extras.getString(BleService.EXTRA_ADDR))) {
				return;
			}

			String action = intent.getAction();
			if (BleService.BLE_GATT_CONNECTED.equals(action)) {
				mConnected = true;
				updateConnectionState(R.string.connected);
				invalidateOptionsMenu();
			} else if (BleService.BLE_GATT_DISCONNECTED.equals(action)) {
				onDeviceDisconnected();
			} else if (BleService.BLE_SERVICE_DISCOVERED.equals(action)) {
				displayGattServices(mBle.getServices(mDeviceAddress));
			}
		}
	};

	// If a given GATT characteristic is selected, check for supported features.
	// This sample
	// demonstrates 'Read' and 'Notify' features. See
	// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for
	// the complete
	// list of supported characteristic features.
	private final ExpandableListView.OnChildClickListener servicesListClickListner = new ExpandableListView.OnChildClickListener() {
		@Override
		public boolean onChildClick(ExpandableListView parent, View v,
				int groupPosition, int childPosition, long id) {
			Log.d(TAG, "onChildClick " + groupPosition + " " + childPosition);
			if (mGattCharacteristics != null) {
				final BleGattCharacteristic characteristic = mGattCharacteristics
						.get(groupPosition).get(childPosition);
				Intent intent = new Intent(DeviceControlActivity.this,
						CharacteristicActivity.class);
				intent.putExtra("address", mDeviceAddress);
				Log.d(TAG, "service size " + mBle.getServices(mDeviceAddress).size());
				intent.putExtra("service", mBle.getServices(mDeviceAddress)
						.get(groupPosition).getUuid().toString());
				intent.putExtra("characteristic", characteristic.getUuid()
						.toString().toUpperCase());
				startActivity(intent);
				return true;
			}
			return false;
		}
	};

	private void clearUI() {
		mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.gatt_services_characteristics);

		final Intent intent = getIntent();
		mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
		mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);

		// Sets up UI references.
		((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
		mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);
		mGattServicesList.setOnChildClickListener(servicesListClickListner);
		mConnectionState = (TextView) findViewById(R.id.connection_state);

		getActionBar().setTitle(mDeviceName);
		getActionBar().setDisplayHomeAsUpEnabled(true);
		BleApplication app = (BleApplication) getApplication();
		mBle = app.getIBle();
	}

	@Override
	protected void onResume() {
		super.onResume();
		registerReceiver(mBleReceiver, BleService.getIntentFilter());
		ArrayList<BleGattService> services = mBle.getServices(mDeviceAddress);
		if (services == null || services.size() == 0) {
			onDeviceDisconnected();
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
		unregisterReceiver(mBleReceiver);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (mBle != null) {
			mBle.disconnect(mDeviceAddress);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.gatt_services, menu);
		if (mConnected) {
			menu.findItem(R.id.menu_connect).setVisible(true);
			menu.findItem(R.id.menu_disconnect).setVisible(true);
		} else {
			menu.findItem(R.id.menu_connect).setVisible(true);
			menu.findItem(R.id.menu_disconnect).setVisible(true);
		}
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_connect:
			mBle.requestConnect(mDeviceAddress);
			return true;
		case R.id.menu_disconnect:
			mBle.disconnect(mDeviceAddress);
			onDeviceDisconnected();
			return true;
		case android.R.id.home:
			onBackPressed();
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	private void updateConnectionState(final int resourceId) {
		runOnUiThread(new Runnable() {
			@Override
			public void run() {
				mConnectionState.setText(resourceId);
			}
		});
	}

	// Demonstrates how to iterate through the supported GATT
	// Services/Characteristics.
	// In this sample, we populate the data structure that is bound to the
	// ExpandableListView
	// on the UI.
	private void displayGattServices(List<BleGattService> gattServices) {
		if (gattServices == null)
			return;
		String uuid = null;
		String unknownServiceString = getResources().getString(
				R.string.unknown_service);
		String unknownCharaString = getResources().getString(
				R.string.unknown_characteristic);
		ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
		ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();
		mGattCharacteristics = new ArrayList<ArrayList<BleGattCharacteristic>>();

		// Loops through available GATT Services.
		for (BleGattService gattService : gattServices) {
			HashMap<String, String> currentServiceData = new HashMap<String, String>();
			uuid = gattService.getUuid().toString().toUpperCase();

			currentServiceData.put(LIST_NAME, Utils.BLE_SERVICES
					.containsKey(uuid) ? Utils.BLE_SERVICES.get(uuid)
					: unknownServiceString);
			currentServiceData.put(LIST_UUID, uuid);
			gattServiceData.add(currentServiceData);

			ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>();
			List<BleGattCharacteristic> gattCharacteristics = gattService
					.getCharacteristics();
			ArrayList<BleGattCharacteristic> charas = new ArrayList<BleGattCharacteristic>();

			// Loops through available Characteristics.
			for (BleGattCharacteristic gattCharacteristic : gattCharacteristics) {
				charas.add(gattCharacteristic);
				HashMap<String, String> currentCharaData = new HashMap<String, String>();
				uuid = gattCharacteristic.getUuid().toString().toUpperCase();
				currentCharaData
						.put(LIST_NAME,
								Utils.BLE_CHARACTERISTICS.containsKey(uuid) ? Utils.BLE_CHARACTERISTICS
										.get(uuid) : unknownCharaString);
				currentCharaData.put(LIST_UUID, uuid);
				gattCharacteristicGroupData.add(currentCharaData);
			}
			mGattCharacteristics.add(charas);
			gattCharacteristicData.add(gattCharacteristicGroupData);
		}

		SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
				this, gattServiceData,
				android.R.layout.simple_expandable_list_item_2, new String[] {
						LIST_NAME, LIST_UUID }, new int[] { android.R.id.text1,
						android.R.id.text2 }, gattCharacteristicData,
				android.R.layout.simple_expandable_list_item_2, new String[] {
						LIST_NAME, LIST_UUID }, new int[] { android.R.id.text1,
						android.R.id.text2 });
		mGattServicesList.setAdapter(gattServiceAdapter);
	}

	private void onDeviceDisconnected() {
		mConnected = false;
		updateConnectionState(R.string.disconnected);
		invalidateOptionsMenu();
		clearUI();
	}
}


================================================
FILE: BluetoothLeGatt/src/com/example/bluetooth/le/DeviceScanActivity.java
================================================
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * This XPG software is supplied to you by Xtreme Programming Group, Inc.
 * ("XPG") in consideration of your agreement to the following terms, and your
 * use, installation, modification or redistribution of this XPG software
 * constitutes acceptance of these terms.� If you do not agree with these terms,
 * please do not use, install, modify or redistribute this XPG software.
 * 
 * In consideration of your agreement to abide by the following terms, and
 * subject to these terms, XPG grants you a non-exclusive license, under XPG's
 * copyrights in this original XPG software (the "XPG Software"), to use and
 * redistribute the XPG Software, in source and/or binary forms; provided that
 * if you redistribute the XPG Software, with or without modifications, you must
 * retain this notice and the following text and disclaimers in all such
 * redistributions of the XPG Software. Neither the name, trademarks, service
 * marks or logos of XPG Inc. may be used to endorse or promote products derived
 * from the XPG Software without specific prior written permission from XPG.�
 * Except as expressly stated in this notice, no other rights or licenses,
 * express or implied, are granted by XPG herein, including but not limited to
 * any patent rights that may be infringed by your derivative works or by other
 * works in which the XPG Software may be incorporated.
 * 
 * The XPG Software is provided by XPG on an "AS IS" basis.� XPG MAKES NO
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
 * WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, REGARDING THE XPG SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
 * COMBINATION WITH YOUR PRODUCTS.
 * 
 * IN NO EVENT SHALL XPG BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
 * AND/OR DISTRIBUTION OF THE XPG SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER
 * THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
 * OTHERWISE, EVEN IF XPG HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * ABOUT XPG: Established since June 2005, Xtreme Programming Group, Inc. (XPG)
 * is a digital solutions company based in the United States and China. XPG
 * integrates cutting-edge hardware designs, mobile applications, and cloud
 * computing technologies to bring innovative products to the marketplace. XPG's
 * partners and customers include global leading corporations in semiconductor,
 * home appliances, health/wellness electronics, toys and games, and automotive
 * industries. Visit www.xtremeprog.com for more information.
 * 
 * Copyright (C) 2013 Xtreme Programming Group, Inc. All Rights Reserved.
 */

package com.example.bluetooth.le;

import java.util.ArrayList;

import android.app.Activity;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.xtremeprog.sdk.ble.BleService;
import com.xtremeprog.sdk.ble.IBle;

/**
 * Activity for scanning and displaying available Bluetooth LE devices.
 */
public class DeviceScanActivity extends ListActivity {
	private LeDeviceListAdapter mLeDeviceListAdapter;
	private boolean mScanning;
	private Handler mHandler;
	private IBle mBle;

	private static final int REQUEST_ENABLE_BT = 1;
	// Stops scanning after 10 seconds.
	private static final long SCAN_PERIOD = 10000;

	private final BroadcastReceiver mBleReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (BleService.BLE_NOT_SUPPORTED.equals(action)) {
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						Toast.makeText(DeviceScanActivity.this,
								"Ble not support", Toast.LENGTH_SHORT).show();
						finish();
					}
				});
			} else if (BleService.BLE_DEVICE_FOUND.equals(action)) {
				// device found
				Bundle extras = intent.getExtras();
				final BluetoothDevice device = extras
						.getParcelable(BleService.EXTRA_DEVICE);
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						mLeDeviceListAdapter.addDevice(device);
						mLeDeviceListAdapter.notifyDataSetChanged();
					}
				});
			} else if (BleService.BLE_NO_BT_ADAPTER.equals(action)) {
				runOnUiThread(new Runnable() {
					@Override
					public void run() {
						Toast.makeText(DeviceScanActivity.this,
								"No bluetooth adapter", Toast.LENGTH_SHORT)
								.show();
						finish();
					}
				});
			}
		}
	};

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getActionBar().setTitle(R.string.title_devices);
		mHandler = new Handler();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		if (!mScanning) {
			menu.findItem(R.id.menu_stop).setVisible(false);
			menu.findItem(R.id.menu_scan).setVisible(true);
			menu.findItem(R.id.menu_refresh).setActionView(null);
		} else {
			menu.findItem(R.id.menu_stop).setVisible(true);
			menu.findItem(R.id.menu_scan).setVisible(false);
			menu.findItem(R.id.menu_refresh).setActionView(
					R.layout.actionbar_indeterminate_progress);
		}
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_scan:
			mLeDeviceListAdapter.clear();
			scanLeDevice(true);
			break;
		case R.id.menu_stop:
			scanLeDevice(false);
			break;
		}
		return true;
	}

	@Override
	protected void onResume() {
		super.onResume();
		registerReceiver(mBleReceiver, BleService.getIntentFilter());

		// Ensures Bluetooth is enabled on the device. If Bluetooth is not
		// currently enabled,
		// fire an intent to display a dialog asking the user to grant
		// permission to enable it.
		if (mBle != null && !mBle.adapterEnabled()) {
			Intent enableBtIntent = new Intent(
					BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
		}

		// Initializes list view adapter.
		mLeDeviceListAdapter = new LeDeviceListAdapter();
		setListAdapter(mLeDeviceListAdapter);
		scanLeDevice(true);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// User chose not to enable Bluetooth.
		if (requestCode == REQUEST_ENABLE_BT
				&& resultCode == Activity.RESULT_CANCELED) {
			finish();
			return;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	@Override
	protected void onPause() {
		super.onPause();
		unregisterReceiver(mBleReceiver);
		scanLeDevice(false);
		mLeDeviceListAdapter.clear();
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
		if (device == null)
			return;
		final Intent intent = new Intent(this, DeviceControlActivity.class);
		intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME,
				device.getName());
		intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS,
				device.getAddress());
		if (mBle != null) {
			mBle.stopScan();
		}
		startActivity(intent);
	}

	private void scanLeDevice(final boolean enable) {
		BleApplication app = (BleApplication) getApplication();
		mBle = app.getIBle();
		if (mBle == null) {
			return;
		}
		if (enable) {
			// Stops scanning after a pre-defined scan period.
			mHandler.postDelayed(new Runnable() {
				@Override
				public void run() {
					mScanning = false;
					if (mBle != null) {
						mBle.stopScan();
					}
					invalidateOptionsMenu();
				}
			}, SCAN_PERIOD);

			mScanning = true;
			if (mBle != null) {
				mBle.startScan();
			}
		} else {
			mScanning = false;
			if (mBle != null) {
				mBle.stopScan();
			}
		}
		invalidateOptionsMenu();
	}

	// Adapter for holding devices found through scanning.
	private class LeDeviceListAdapter extends BaseAdapter {
		private ArrayList<BluetoothDevice> mLeDevices;
		private LayoutInflater mInflator;

		public LeDeviceListAdapter() {
			super();
			mLeDevices = new ArrayList<BluetoothDevice>();
			mInflator = DeviceScanActivity.this.getLayoutInflater();
		}

		public void addDevice(BluetoothDevice device) {
			if (!mLeDevices.contains(device)) {
				mLeDevices.add(device);
			}
		}

		public BluetoothDevice getDevice(int position) {
			return mLeDevices.get(position);
		}

		public void clear() {
			mLeDevices.clear();
		}

		@Override
		public int getCount() {
			return mLeDevices.size();
		}

		@Override
		public Object getItem(int i) {
			return mLeDevices.get(i);
		}

		@Override
		public long getItemId(int i) {
			return i;
		}

		@Override
		public View getView(int i, View view, ViewGroup viewGroup) {
			ViewHolder viewHolder;
			// General ListView optimization code.
			if (view == null) {
				view = mInflator.inflate(R.layout.listitem_device, null);
				viewHolder = new ViewHolder();
				viewHolder.deviceAddress = (TextView) view
						.findViewById(R.id.device_address);
				viewHolder.deviceName = (TextView) view
						.findViewById(R.id.device_name);
				view.setTag(viewHolder);
			} else {
				viewHolder = (ViewHolder) view.getTag();
			}

			BluetoothDevice device = mLeDevices.get(i);
			final String deviceName = device.getName();
			if (deviceName != null && deviceName.length() > 0)
				viewHolder.deviceName.setText(deviceName);
			else
				viewHolder.deviceName.setText(R.string.unknown_device);
			viewHolder.deviceAddress.setText(device.getAddress());

			return view;
		}
	}

	static class ViewHolder {
		TextView deviceName;
		TextView deviceAddress;
	}
}

================================================
FILE: BluetoothLeGatt/src/com/example/bluetooth/le/Utils.java
================================================
package com.example.bluetooth.le;

import java.util.HashMap;
import java.util.Map;

public class Utils {
	public static Map<String, String> BLE_SERVICES = new HashMap<String, String>();
	public static Map<String, String> BLE_CHARACTERISTICS = new HashMap<String, String>();
	
	static {
		BLE_SERVICES.put("00001811-0000-1000-8000-00805F9B34FB", "Alert Notification Service");
		BLE_SERVICES.put("0000180F-0000-1000-8000-00805F9B34FB", "Battery Service");
		BLE_SERVICES.put("00001810-0000-1000-8000-00805F9B34FB", "Blood Pressure");
		BLE_SERVICES.put("00001805-0000-1000-8000-00805F9B34FB", "Current Time Service");
		BLE_SERVICES.put("00001818-0000-1000-8000-00805F9B34FB", "Cycling Power");
		BLE_SERVICES.put("00001816-0000-1000-8000-00805F9B34FB", "Cycling Speed and Cadence");
		BLE_SERVICES.put("0000180A-0000-1000-8000-00805F9B34FB", "Device Information");
		BLE_SERVICES.put("00001800-0000-1000-8000-00805F9B34FB", "Generic Access");
		BLE_SERVICES.put("00001801-0000-1000-8000-00805F9B34FB", "Generic Attribute");
		BLE_SERVICES.put("00001808-0000-1000-8000-00805F9B34FB", "Glucose");
		BLE_SERVICES.put("00001809-0000-1000-8000-00805F9B34FB", "Health Thermometer");
		BLE_SERVICES.put("0000180D-0000-1000-8000-00805F9B34FB", "Heart Rate");
		BLE_SERVICES.put("00001812-0000-1000-8000-00805F9B34FB", "Human Interface Device");
		BLE_SERVICES.put("00001802-0000-1000-8000-00805F9B34FB", "Immediate Alert");
		BLE_SERVICES.put("00001803-0000-1000-8000-00805F9B34FB", "Link Loss");
		BLE_SERVICES.put("00001819-0000-1000-8000-00805F9B34FB", "Location and Navigation");
		BLE_SERVICES.put("00001807-0000-1000-8000-00805F9B34FB", "Next DST Change Service");
		BLE_SERVICES.put("0000180E-0000-1000-8000-00805F9B34FB", "Phone Alert Status Service");
		BLE_SERVICES.put("00001806-0000-1000-8000-00805F9B34FB", "Reference Time Update Service");
		BLE_SERVICES.put("00001814-0000-1000-8000-00805F9B34FB", "Running Speed and Cadence");
		BLE_SERVICES.put("00001813-0000-1000-8000-00805F9B34FB", "Scan Parameters");
		BLE_SERVICES.put("00001804-0000-1000-8000-00805F9B34FB", "Tx Power");
		
		BLE_CHARACTERISTICS.put("00002A43-0000-1000-8000-00805F9B34FB", "Alert Category ID");
		BLE_CHARACTERISTICS.put("00002A42-0000-1000-8000-00805F9B34FB", "Alert Category ID Bit Mask");
		BLE_CHARACTERISTICS.put("00002A06-0000-1000-8000-00805F9B34FB", "Alert Level");
		BLE_CHARACTERISTICS.put("00002A44-0000-1000-8000-00805F9B34FB", "Alert Notification Control Point");
		BLE_CHARACTERISTICS.put("00002A3F-0000-1000-8000-00805F9B34FB", "Alert Status");
		BLE_CHARACTERISTICS.put("00002A01-0000-1000-8000-00805F9B34FB", "Appearance");
		BLE_CHARACTERISTICS.put("00002A19-0000-1000-8000-00805F9B34FB", "Battery Level");
		BLE_CHARACTERISTICS.put("00002A49-0000-1000-8000-00805F9B34FB", "Blood Pressure Feature");
		BLE_CHARACTERISTICS.put("00002A35-0000-1000-8000-00805F9B34FB", "Blood Pressure Measurement");
		BLE_CHARACTERISTICS.put("00002A38-0000-1000-8000-00805F9B34FB", "Body Sensor Location");
		BLE_CHARACTERISTICS.put("00002A22-0000-1000-8000-00805F9B34FB", "Boot Keyboard Input Report");
		BLE_CHARACTERISTICS.put("00002A32-0000-1000-8000-00805F9B34FB", "Boot Keyboard Output Report");
		BLE_CHARACTERISTICS.put("00002A33-0000-1000-8000-00805F9B34FB", "Boot Mouse Input Report");
		BLE_CHARACTERISTICS.put("00002A5C-0000-1000-8000-00805F9B34FB", "CSC Feature");
		BLE_CHARACTERISTICS.put("00002A5B-0000-1000-8000-00805F9B34FB", "CSC Measurement");
		BLE_CHARACTERISTICS.put("00002A2B-0000-1000-8000-00805F9B34FB", "Current Time");
		BLE_CHARACTERISTICS.put("00002A66-0000-1000-8000-00805F9B34FB", "Cycling Power Control Point");
		BLE_CHARACTERISTICS.put("00002A65-0000-1000-8000-00805F9B34FB", "Cycling Power Feature");
		BLE_CHARACTERISTICS.put("00002A63-0000-1000-8000-00805F9B34FB", "Cycling Power Measurement");
		BLE_CHARACTERISTICS.put("00002A64-0000-1000-8000-00805F9B34FB", "Cycling Power Vector");
		BLE_CHARACTERISTICS.put("00002A08-0000-1000-8000-00805F9B34FB", "Date Time");
		BLE_CHARACTERISTICS.put("00002A0A-0000-1000-8000-00805F9B34FB", "Day Date Time");
		BLE_CHARACTERISTICS.put("00002A09-0000-1000-8000-00805F9B34FB", "Day of Week");
		BLE_CHARACTERISTICS.put("00002A00-0000-1000-8000-00805F9B34FB", "Device Name");
		BLE_CHARACTERISTICS.put("00002A0D-0000-1000-8000-00805F9B34FB", "DST Offset");
		BLE_CHARACTERISTICS.put("00002A0C-0000-1000-8000-00805F9B34FB", "Exact Time 256");
		BLE_CHARACTERISTICS.put("00002A26-0000-1000-8000-00805F9B34FB", "Firmware Revision String");
		BLE_CHARACTERISTICS.put("00002A51-0000-1000-8000-00805F9B34FB", "Glucose Feature");
		BLE_CHARACTERISTICS.put("00002A18-0000-1000-8000-00805F9B34FB", "Glucose Measurement");
		BLE_CHARACTERISTICS.put("00002A34-0000-1000-8000-00805F9B34FB", "Glucose Measurement Context");
		BLE_CHARACTERISTICS.put("00002A27-0000-1000-8000-00805F9B34FB", "Hardware Revision String");
		BLE_CHARACTERISTICS.put("00002A39-0000-1000-8000-00805F9B34FB", "Heart Rate Control Point");
		BLE_CHARACTERISTICS.put("00002A37-0000-1000-8000-00805F9B34FB", "Heart Rate Measurement");
		BLE_CHARACTERISTICS.put("00002A4C-0000-1000-8000-00805F9B34FB", "HID Control Point");
		BLE_CHARACTERISTICS.put("00002A4A-0000-1000-8000-00805F9B34FB", "HID Information");
		BLE_CHARACTERISTICS.put("00002A2A-0000-1000-8000-00805F9B34FB", "IEEE 11073-20601 Regulatory Certification Data List");
		BLE_CHARACTERISTICS.put("00002A36-0000-1000-8000-00805F9B34FB", "Intermediate Cuff Pressure");
		BLE_CHARACTERISTICS.put("00002A1E-0000-1000-8000-00805F9B34FB", "Intermediate Temperature");
		BLE_CHARACTERISTICS.put("00002A6B-0000-1000-8000-00805F9B34FB", "LN Control Point");
		BLE_CHARACTERISTICS.put("00002A6A-0000-1000-8000-00805F9B34FB", "LN Feature");
		BLE_CHARACTERISTICS.put("00002A0F-0000-1000-8000-00805F9B34FB", "Local Time Information");
		BLE_CHARACTERISTICS.put("00002A67-0000-1000-8000-00805F9B34FB", "Location and Speed");
		BLE_CHARACTERISTICS.put("00002A29-0000-1000-8000-00805F9B34FB", "Manufacturer Name String");
		BLE_CHARACTERISTICS.put("00002A21-0000-1000-8000-00805F9B34FB", "Measurement Interval");
		BLE_CHARACTERISTICS.put("00002A24-0000-1000-8000-00805F9B34FB", "Model Number String");
		BLE_CHARACTERISTICS.put("00002A68-0000-1000-8000-00805F9B34FB", "Navigation");
		BLE_CHARACTERISTICS.put("00002A46-0000-1000-8000-00805F9B34FB", "New Alert");
		BLE_CHARACTERISTICS.put("00002A04-0000-1000-8000-00805F9B34FB", "Peripheral Preferred Connection Parameters");
		BLE_CHARACTERISTICS.put("00002A02-0000-1000-8000-00805F9B34FB", "Peripheral Privacy Flag");
		BLE_CHARACTERISTICS.put("00002A50-0000-1000-8000-00805F9B34FB", "PnP ID");
		BLE_CHARACTERISTICS.put("00002A69-0000-1000-8000-00805F9B34FB", "Position Quality");
		BLE_CHARACTERISTICS.put("00002A4E-0000-1000-8000-00805F9B34FB", "Protocol Mode");
		BLE_CHARACTERISTICS.put("00002A03-0000-1000-8000-00805F9B34FB", "Reconnection Address");
		BLE_CHARACTERISTICS.put("00002A52-0000-1000-8000-00805F9B34FB", "Record Access Control Point");
		BLE_CHARACTERISTICS.put("00002A14-0000-1000-8000-00805F9B34FB", "Reference Time Information");
		BLE_CHARACTERISTICS.put("00002A4D-0000-1000-8000-00805F9B34FB", "Report");
		BLE_CHARACTERISTICS.put("00002A4B-0000-1000-8000-00805F9B34FB", "Report Map");
		BLE_CHARACTERISTICS.put("00002A40-0000-1000-8000-00805F9B34FB", "Ringer Control Point");
		BLE_CHARACTERISTICS.put("00002A41-0000-1000-8000-00805F9B34FB", "Ringer Setting");
		BLE_CHARACTERISTICS.put("00002A54-0000-1000-8000-00805F9B34FB", "RSC Feature");
		BLE_CHARACTERISTICS.put("00002A53-0000-1000-8000-00805F9B34FB", "RSC Measurement");
		BLE_CHARACTERISTICS.put("00002A55-0000-1000-8000-00805F9B34FB", "SC Control Point");
		BLE_CHARACTERISTICS.put("00002A4F-0000-1000-8000-00805F9B34FB", "Scan Interval Window");
		BLE_CHARACTERISTICS.put("00002A31-0000-1000-8000-00805F9B34FB", "Scan Refresh");
		BLE_CHARACTERISTICS.put("00002A5D-0000-1000-8000-00805F9B34FB", "Sensor Location");
		BLE_CHARACTERISTICS.put("00002A25-0000-1000-8000-00805F9B34FB", "Serial Number String");
		BLE_CHARACTERISTICS.put("00002A05-0000-1000-8000-00805F9B34FB", "Service Changed");
		BLE_CHARACTERISTICS.put("00002A28-0000-1000-8000-00805F9B34FB", "Software Revision String");
		BLE_CHARACTERISTICS.put("00002A47-0000-1000-8000-00805F9B34FB", "Supported New Alert Category");
		BLE_CHARACTERISTICS.put("00002A48-0000-1000-8000-00805F9B34FB", "Supported Unread Alert Category");
		BLE_CHARACTERISTICS.put("00002A23-0000-1000-8000-00805F9B34FB", "System ID");
		BLE_CHARACTERISTICS.put("00002A1C-0000-1000-8000-00805F9B34FB", "Temperature Measurement");
		BLE_CHARACTERISTICS.put("00002A1D-0000-1000-8000-00805F9B34FB", "Temperature Type");
		BLE_CHARACTERISTICS.put("00002A12-0000-1000-8000-00805F9B34FB", "Time Accuracy");
		BLE_CHARACTERISTICS.put("00002A13-0000-1000-8000-00805F9B34FB", "Time Source");
		BLE_CHARACTERISTICS.put("00002A16-0000-1000-8000-00805F9B34FB", "Time Update Control Point");
		BLE_CHARACTERISTICS.put("00002A17-0000-1000-8000-00805F9B34FB", "Time Update State");
		BLE_CHARACTERISTICS.put("00002A11-0000-1000-8000-00805F9B34FB", "Time with DST");
		BLE_CHARACTERISTICS.put("00002A0E-0000-1000-8000-00805F9B34FB", "Time Zone");
		BLE_CHARACTERISTICS.put("00002A07-0000-1000-8000-00805F9B34FB", "Tx Power Level");
		BLE_CHARACTERISTICS.put("00002A45-0000-1000-8000-00805F9B34FB", "Unread Alert Status");
	}
	
	private static Utils INSTANCE;
	
	private Utils() {}
	
	public static Utils getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new Utils();
		}
		return INSTANCE;
	}
}


================================================
FILE: LICENSE
================================================
Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright {yyyy} {name of copyright owner}

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

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

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

================================================
FILE: README.md
================================================
GizwitsBLE
==========

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

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

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

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

# Main Features
* Support Android 4.2 (Broadcom, Sumsung SDK) and Android 4.3+ 
* Built in Service, just start the service and receive BLE events by broadcast
* Built in BLE request queue

# Components
* BleLibrary: this is the library project you can reuse in your project.
* BluetoothLeGatt: this is the demo app project that uses BleLibrary.

# Compile & Run
## Eclipse
These two projects are eclipse projects. If you use eclipse, you can import these projects directly and run BluetoothLeGatt.
## Android Studio
If you use android studio, you should import these project.

When it goes to Libraries step, it will show libs and libs1, just choose libs and ignore libs1.

When it goes to select project SDK step, ensure you choose Android API > 17.

Then you can run BluetoothLeGatt in android studio.
Download .txt
gitextract_x58tzomf/

├── .gitignore
├── BleLibrary/
│   ├── .classpath
│   ├── .project
│   ├── AndroidManifest.xml
│   ├── libs/
│   │   ├── com.broadcom.bt.jar
│   │   ├── commons-codec-1.8.jar
│   │   └── samsung_ble_sdk_200.jar
│   ├── proguard-project.txt
│   ├── proguard.pro
│   ├── project.properties
│   ├── res/
│   │   ├── values/
│   │   │   ├── strings.xml
│   │   │   └── styles.xml
│   │   ├── values-v11/
│   │   │   └── styles.xml
│   │   └── values-v14/
│   │       └── styles.xml
│   └── src/
│       └── com/
│           └── xtremeprog/
│               └── sdk/
│                   └── ble/
│                       ├── AndroidBle.java
│                       ├── BleGattCharacteristic.java
│                       ├── BleGattService.java
│                       ├── BleRequest.java
│                       ├── BleService.java
│                       ├── BroadcomBle.java
│                       ├── IBle.java
│                       ├── IBleRequestHandler.java
│                       └── SamsungBle.java
├── BluetoothLeGatt/
│   ├── .classpath
│   ├── .project
│   ├── AndroidManifest.xml
│   ├── libs/
│   │   ├── com.broadcom.bt.jar
│   │   ├── commons-codec-1.8.jar
│   │   └── samsung_ble_sdk_200.jar
│   ├── project.properties
│   ├── res/
│   │   ├── layout/
│   │   │   ├── actionbar_indeterminate_progress.xml
│   │   │   ├── activity_characteristic.xml
│   │   │   ├── gatt_services_characteristics.xml
│   │   │   └── listitem_device.xml
│   │   ├── menu/
│   │   │   ├── characteristic.xml
│   │   │   ├── gatt_services.xml
│   │   │   └── main.xml
│   │   ├── values/
│   │   │   ├── dimens.xml
│   │   │   └── strings.xml
│   │   └── values-w820dp/
│   │       └── dimens.xml
│   └── src/
│       └── com/
│           └── example/
│               └── bluetooth/
│                   └── le/
│                       ├── BleApplication.java
│                       ├── CharacteristicActivity.java
│                       ├── DeviceControlActivity.java
│                       ├── DeviceScanActivity.java
│                       └── Utils.java
├── LICENSE
└── README.md
Download .txt
SYMBOL INDEX (231 symbols across 14 files)

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/AndroidBle.java
  class AndroidBle (line 73) | @SuppressLint("NewApi")
    method onLeScan (line 84) | @Override
    method onConnectionStateChange (line 93) | @Override
    method onServicesDiscovered (line 115) | @Override
    method onCharacteristicRead (line 127) | @Override
    method onCharacteristicChanged (line 143) | @Override
    method onCharacteristicWrite (line 153) | public void onCharacteristicWrite(BluetoothGatt gatt,
    method onDescriptorWrite (line 166) | public void onDescriptorWrite(BluetoothGatt gatt,
    method AndroidBle (line 196) | public AndroidBle(BleService service) {
    method startScan (line 215) | @Override
    method stopScan (line 220) | @Override
    method adapterEnabled (line 225) | @Override
    method connect (line 233) | @Override
    method disconnect (line 248) | @Override
    method getServices (line 259) | @Override
    method requestReadCharacteristic (line 276) | @Override
    method readCharacteristic (line 289) | public boolean readCharacteristic(String address,
    method discoverServices (line 299) | @Override
    method getService (line 313) | @Override
    method requestCharacteristicNotification (line 328) | @Override
    method characteristicNotification (line 342) | @Override
    method requestWriteCharacteristic (line 381) | @Override
    method writeCharacteristic (line 394) | @Override
    method requestConnect (line 407) | @Override
    method getBTAdapterMacAddr (line 418) | @Override
    method requestIndication (line 426) | @Override
    method requestStopNotification (line 440) | @Override

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BleGattCharacteristic.java
  class BleGattCharacteristic (line 55) | @SuppressLint("NewApi")
    method BleGattCharacteristic (line 115) | public BleGattCharacteristic(android.bluetooth.BluetoothGattCharacteri...
    method BleGattCharacteristic (line 121) | public BleGattCharacteristic(
    method BleGattCharacteristic (line 127) | public BleGattCharacteristic(
    method initInfo (line 133) | private void initInfo() {
    method getUuid (line 137) | public UUID getUuid() {
    method getGattCharacteristicA (line 149) | protected android.bluetooth.BluetoothGattCharacteristic getGattCharact...
    method getProperties (line 153) | public int getProperties() {
    method getGattCharacteristicB (line 165) | protected com.broadcom.bt.gatt.BluetoothGattCharacteristic getGattChar...
    method setGattCharacteristicB (line 169) | protected void setGattCharacteristicB(
    method getName (line 174) | public String getName() {
    method setName (line 178) | public void setName(String name) {
    method setValue (line 182) | public boolean setValue(byte[] val) {
    method getValue (line 194) | public byte[] getValue() {
    method setValue (line 206) | public boolean setValue(int value, int formatType, int offset) {
    method setValue (line 218) | public boolean setValue(int mantissa, int exponent, int formatType,
    method setValue (line 234) | public boolean setValue(String value) {
    method getStringValue (line 238) | public String getStringValue(int offset) {
    method getFloatValue (line 250) | public Float getFloatValue(int formatType, int offset) {
    method getIntValue (line 262) | public Integer getIntValue(int formatType, int offset) {
    method byte2uint24 (line 289) | private Integer byte2uint24(int offset, byte[] value) {
    method getGattCharacteristicS (line 297) | protected com.samsung.android.sdk.bt.gatt.BluetoothGattCharacteristic ...
    method setGattCharacteristicS (line 301) | protected void setGattCharacteristicS(
    method setGattCharacteristicA (line 306) | protected void setGattCharacteristicA(

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BleGattService.java
  class BleGattService (line 61) | @SuppressLint("NewApi")
    method BleGattService (line 70) | public BleGattService(com.samsung.android.sdk.bt.gatt.BluetoothGattSer...
    method BleGattService (line 76) | public BleGattService(com.broadcom.bt.gatt.BluetoothGattService s) {
    method BleGattService (line 82) | public BleGattService(android.bluetooth.BluetoothGattService s) {
    method initInfo (line 88) | private void initInfo() {
    method getUuid (line 92) | public UUID getUuid() {
    method getCharacteristics (line 104) | public List<BleGattCharacteristic> getCharacteristics() {
    method getCharacteristic (line 126) | public BleGattCharacteristic getCharacteristic(UUID uuid) {
    method setInfo (line 150) | public void setInfo(JSONObject info) {
    method getName (line 162) | public String getName() {
    method setName (line 166) | public void setName(String mName) {

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BleRequest.java
  class BleRequest (line 49) | public class BleRequest {
    type RequestType (line 50) | public enum RequestType {
    type FailReason (line 54) | public enum FailReason {
    method BleRequest (line 63) | public BleRequest(RequestType type, String address) {
    method BleRequest (line 68) | public BleRequest(RequestType type, String address,
    method BleRequest (line 75) | public BleRequest(RequestType type, String address,
    method equals (line 83) | @Override

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BleService.java
  class BleService (line 67) | public class BleService extends Service {
    type BLESDK (line 136) | public enum BLESDK {
    method run (line 154) | @Override
    method getIntentFilter (line 194) | public static IntentFilter getIntentFilter() {
    method onBind (line 211) | @Override
    class LocalBinder (line 216) | public class LocalBinder extends Binder {
      method getService (line 217) | public BleService getService() {
    method onCreate (line 222) | @Override
    method bleNotSupported (line 239) | protected void bleNotSupported() {
    method bleNoBtAdapter (line 244) | protected void bleNoBtAdapter() {
    method getBleSDK (line 249) | private BLESDK getBleSDK() {
    method getBle (line 274) | public IBle getBle() {
    method bleDeviceFound (line 287) | protected void bleDeviceFound(BluetoothDevice device, int rssi,
    method bleGattConnected (line 305) | protected void bleGattConnected(BluetoothDevice device) {
    method bleGattDisConnected (line 321) | protected void bleGattDisConnected(String address) {
    method bleServiceDiscovered (line 336) | protected void bleServiceDiscovered(String address) {
    method requestProcessed (line 343) | protected void requestProcessed(String address, RequestType requestType,
    method clearTimeoutThread (line 363) | private void clearTimeoutThread() {
    method bleCharacteristicRead (line 389) | protected void bleCharacteristicRead(String address, String uuid,
    method addBleRequest (line 400) | protected void addBleRequest(BleRequest request) {
    method processNextRequest (line 407) | private synchronized void processNextRequest() {
    method startTimeoutThread (line 463) | private void startTimeoutThread() {
    method getCurrentRequest (line 469) | protected BleRequest getCurrentRequest() {
    method setCurrentRequest (line 473) | protected void setCurrentRequest(BleRequest mCurrentRequest) {
    method bleCharacteristicNotification (line 489) | protected void bleCharacteristicNotification(String address, String uuid,
    method bleCharacteristicIndication (line 519) | protected void bleCharacteristicIndication(String address, String uuid,
    method bleCharacteristicWrite (line 542) | protected void bleCharacteristicWrite(String address, String uuid,
    method bleCharacteristicChanged (line 564) | protected void bleCharacteristicChanged(String address, String uuid,
    method bleStatusAbnormal (line 576) | protected void bleStatusAbnormal(String reason) {
    method bleRequestFailed (line 591) | protected void bleRequestFailed(String address, RequestType type,
    method getNotificationAddress (line 600) | protected String getNotificationAddress() {
    method setNotificationAddress (line 604) | protected void setNotificationAddress(String mNotificationAddress) {

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/BroadcomBle.java
  class BroadcomBle (line 66) | public class BroadcomBle implements IBle, IBleRequestHandler {
    method onAppRegistered (line 74) | @Override
    method onScanResult (line 78) | @Override
    method onConnectionStateChange (line 85) | @Override
    method onServicesDiscovered (line 102) | @Override
    method onCharacteristicRead (line 107) | @Override
    method onCharacteristicChanged (line 117) | @Override
    method onDescriptorRead (line 125) | @Override
    method onDescriptorWrite (line 163) | @Override
    method onServiceConnected (line 194) | @Override
    method onServiceDisconnected (line 200) | @Override
    method BroadcomBle (line 209) | public BroadcomBle(BleService service) {
    method startScan (line 220) | @Override
    method stopScan (line 235) | @Override
    method adapterEnabled (line 245) | @Override
    method connect (line 253) | @Override
    method disconnect (line 259) | @Override
    method getServices (line 265) | @Override
    method requestReadCharacteristic (line 277) | @Override
    method discoverServices (line 285) | @Override
    method readCharacteristic (line 290) | @Override
    method getService (line 300) | @Override
    method requestCharacteristicNotification (line 311) | @Override
    method characteristicNotification (line 320) | @Override
    method requestWriteCharacteristic (line 343) | @Override
    method writeCharacteristic (line 351) | @Override
    method requestConnect (line 358) | @Override
    method getBTAdapterMacAddr (line 367) | @Override
    method requestIndication (line 375) | @Override
    method requestStopNotification (line 383) | @Override

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/IBle.java
  type IBle (line 52) | public interface IBle {
    method getBTAdapterMacAddr (line 54) | public String getBTAdapterMacAddr();
    method startScan (line 60) | public void startScan();
    method stopScan (line 65) | public void stopScan();
    method adapterEnabled (line 72) | public boolean adapterEnabled();
    method disconnect (line 82) | public void disconnect(String address);
    method discoverServices (line 92) | public boolean discoverServices(String address);
    method getServices (line 101) | public ArrayList<BleGattService> getServices(String address);
    method getService (line 111) | public BleGattService getService(String address, UUID uuid);
    method requestConnect (line 120) | public boolean requestConnect(String address);
    method requestReadCharacteristic (line 132) | public boolean requestReadCharacteristic(String address,
    method requestCharacteristicNotification (line 147) | public boolean requestCharacteristicNotification(String address,
    method requestStopNotification (line 150) | public boolean requestStopNotification(String address,
    method requestIndication (line 165) | public boolean requestIndication(String address,
    method requestWriteCharacteristic (line 180) | public boolean requestWriteCharacteristic(String address,

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/IBleRequestHandler.java
  type IBleRequestHandler (line 49) | public interface IBleRequestHandler {
    method connect (line 51) | public boolean connect(String address);
    method readCharacteristic (line 58) | public boolean readCharacteristic(String address,
    method characteristicNotification (line 66) | public boolean characteristicNotification(String address,
    method writeCharacteristic (line 74) | public boolean writeCharacteristic(String address,

FILE: BleLibrary/src/com/xtremeprog/sdk/ble/SamsungBle.java
  class SamsungBle (line 67) | public class SamsungBle implements IBle, IBleRequestHandler {
    method onAppRegistered (line 77) | @Override
    method onScanResult (line 81) | @Override
    method onConnectionStateChange (line 88) | @Override
    method onServicesDiscovered (line 111) | @Override
    method onCharacteristicRead (line 124) | @Override
    method onCharacteristicChanged (line 138) | @Override
    method onCharacteristicWrite (line 147) | @Override
    method onDescriptorRead (line 161) | @Override
    method onDescriptorWrite (line 199) | @Override
    method onServiceConnected (line 231) | @Override
    method onServiceDisconnected (line 237) | @Override
    method SamsungBle (line 243) | public SamsungBle(BleService service) {
    method startScan (line 254) | @Override
    method stopScan (line 269) | @Override
    method adapterEnabled (line 279) | @Override
    method connect (line 287) | @Override
    method disconnect (line 293) | @Override
    method getServices (line 299) | @Override
    method requestReadCharacteristic (line 311) | @Override
    method discoverServices (line 319) | @Override
    method readCharacteristic (line 325) | @Override
    method getService (line 332) | @Override
    method requestCharacteristicNotification (line 343) | @Override
    method characteristicNotification (line 352) | @Override
    method requestWriteCharacteristic (line 370) | @Override
    method writeCharacteristic (line 378) | @Override
    method requestConnect (line 385) | @Override
    method getBTAdapterMacAddr (line 391) | @Override
    method requestIndication (line 399) | @Override
    method requestStopNotification (line 407) | @Override

FILE: BluetoothLeGatt/src/com/example/bluetooth/le/BleApplication.java
  class BleApplication (line 13) | public class BleApplication extends Application {
    method onServiceConnected (line 19) | @Override
    method onServiceDisconnected (line 29) | @Override
    method onCreate (line 35) | @Override
    method getIBle (line 43) | public IBle getIBle() {

FILE: BluetoothLeGatt/src/com/example/bluetooth/le/CharacteristicActivity.java
  class CharacteristicActivity (line 26) | public class CharacteristicActivity extends Activity {
    method onClick (line 34) | @Override
    method onReceive (line 63) | @Override
    method onCreate (line 112) | @Override
    method onCreateOptionsMenu (line 162) | @Override
    method onOptionsItemSelected (line 170) | @Override
    method onResume (line 182) | @Override
    method onPanelClosed (line 188) | @Override

FILE: BluetoothLeGatt/src/com/example/bluetooth/le/DeviceControlActivity.java
  class DeviceControlActivity (line 94) | public class DeviceControlActivity extends Activity {
    method onReceive (line 121) | @Override
    method onChildClick (line 148) | @Override
    method clearUI (line 170) | private void clearUI() {
    method onCreate (line 174) | @Override
    method onResume (line 195) | @Override
    method onPause (line 205) | @Override
    method onDestroy (line 211) | @Override
    method onCreateOptionsMenu (line 219) | @Override
    method onOptionsItemSelected (line 232) | @Override
    method updateConnectionState (line 249) | private void updateConnectionState(final int resourceId) {
    method displayGattServices (line 263) | private void displayGattServices(List<BleGattService> gattServices) {
    method onDeviceDisconnected (line 318) | private void onDeviceDisconnected() {

FILE: BluetoothLeGatt/src/com/example/bluetooth/le/DeviceScanActivity.java
  class DeviceScanActivity (line 91) | public class DeviceScanActivity extends ListActivity {
    method onReceive (line 103) | @Override
    method onCreate (line 141) | @Override
    method onCreateOptionsMenu (line 148) | @Override
    method onOptionsItemSelected (line 164) | @Override
    method onResume (line 178) | @Override
    method onActivityResult (line 199) | @Override
    method onPause (line 210) | @Override
    method onListItemClick (line 218) | @Override
    method scanLeDevice (line 234) | private void scanLeDevice(final boolean enable) {
    class LeDeviceListAdapter (line 267) | private class LeDeviceListAdapter extends BaseAdapter {
      method LeDeviceListAdapter (line 271) | public LeDeviceListAdapter() {
      method addDevice (line 277) | public void addDevice(BluetoothDevice device) {
      method getDevice (line 283) | public BluetoothDevice getDevice(int position) {
      method clear (line 287) | public void clear() {
      method getCount (line 291) | @Override
      method getItem (line 296) | @Override
      method getItemId (line 301) | @Override
      method getView (line 306) | @Override
    class ViewHolder (line 334) | static class ViewHolder {

FILE: BluetoothLeGatt/src/com/example/bluetooth/le/Utils.java
  class Utils (line 6) | public class Utils {
    method Utils (line 119) | private Utils() {}
    method getInstance (line 121) | public static Utils getInstance() {
Condensed preview — 47 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (186K chars).
[
  {
    "path": ".gitignore",
    "chars": 271,
    "preview": "# 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\nbi"
  },
  {
    "path": "BleLibrary/.classpath",
    "chars": 466,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<classpath>\n\t<classpathentry kind=\"src\" path=\"src\"/>\n\t<classpathentry kind=\"src\" "
  },
  {
    "path": "BleLibrary/.project",
    "chars": 813,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>BleLibrary</name>\n\t<comment></comment>\n\t<projects>\n\t<"
  },
  {
    "path": "BleLibrary/AndroidManifest.xml",
    "chars": 470,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.xtremeprog.sdk.ble\"\n    android:ve"
  },
  {
    "path": "BleLibrary/proguard-project.txt",
    "chars": 781,
    "preview": "# To enable ProGuard in your project, edit project.properties\n# to define the proguard.config property as described in t"
  },
  {
    "path": "BleLibrary/proguard.pro",
    "chars": 1142,
    "preview": "-injars bin/blelibrary.jar\n-outjars bin/blelibrary-0.1.jar\n\n-libraryjars /Users/teamx/bin/adt-bundle-mac-x86_64-20130917"
  },
  {
    "path": "BleLibrary/project.properties",
    "chars": 584,
    "preview": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# T"
  },
  {
    "path": "BleLibrary/res/values/strings.xml",
    "chars": 75,
    "preview": "<resources>\n\n    <string name=\"app_name\">BleLibrary</string>\n\n</resources>\n"
  },
  {
    "path": "BleLibrary/res/values/styles.xml",
    "chars": 680,
    "preview": "<resources>\n\n    <!--\n        Base application theme, dependent on API level. This theme is replaced\n        by AppBaseT"
  },
  {
    "path": "BleLibrary/res/values-v11/styles.xml",
    "chars": 324,
    "preview": "<resources>\n\n    <!--\n        Base application theme for API 11+. This theme completely replaces\n        AppBaseTheme fr"
  },
  {
    "path": "BleLibrary/res/values-v14/styles.xml",
    "chars": 381,
    "preview": "<resources>\n\n    <!--\n        Base application theme for API 14+. This theme completely replaces\n        AppBaseTheme fr"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/AndroidBle.java",
    "chars": 15065,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BleGattCharacteristic.java",
    "chars": 10202,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BleGattService.java",
    "chars": 6078,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BleRequest.java",
    "chars": 4100,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BleService.java",
    "chars": 20621,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/BroadcomBle.java",
    "chars": 12797,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/IBle.java",
    "chars": 6743,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/IBleRequestHandler.java",
    "chars": 3488,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BleLibrary/src/com/xtremeprog/sdk/ble/SamsungBle.java",
    "chars": 13691,
    "preview": "/**\n * This XPG software is supplied to you by Xtreme Programming Group, Inc.\n * (\"XPG\") in consideration of your agreem"
  },
  {
    "path": "BluetoothLeGatt/.classpath",
    "chars": 466,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<classpath>\n\t<classpathentry kind=\"con\" path=\"com.android.ide.eclipse.adt.ANDROID"
  },
  {
    "path": "BluetoothLeGatt/.project",
    "chars": 821,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>DeviceScanActivity</name>\n\t<comment></comment>\n\t<proj"
  },
  {
    "path": "BluetoothLeGatt/AndroidManifest.xml",
    "chars": 2553,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\nCopyright (C) 2013 The Android Open Source Project\n\nLicensed under the Apach"
  },
  {
    "path": "BluetoothLeGatt/project.properties",
    "chars": 605,
    "preview": "# This file is automatically generated by Android Tools.\n# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n#\n# T"
  },
  {
    "path": "BluetoothLeGatt/res/layout/actionbar_indeterminate_progress.xml",
    "chars": 942,
    "preview": "<!--\n  Copyright 2013 Google Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use t"
  },
  {
    "path": "BluetoothLeGatt/res/layout/activity_characteristic.xml",
    "chars": 3170,
    "preview": "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/too"
  },
  {
    "path": "BluetoothLeGatt/res/layout/gatt_services_characteristics.xml",
    "chars": 2570,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n     Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under"
  },
  {
    "path": "BluetoothLeGatt/res/layout/listitem_device.xml",
    "chars": 1266,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under the "
  },
  {
    "path": "BluetoothLeGatt/res/menu/characteristic.xml",
    "chars": 373,
    "preview": "<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    "
  },
  {
    "path": "BluetoothLeGatt/res/menu/gatt_services.xml",
    "chars": 1265,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under the "
  },
  {
    "path": "BluetoothLeGatt/res/menu/main.xml",
    "chars": 1247,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under the "
  },
  {
    "path": "BluetoothLeGatt/res/values/dimens.xml",
    "chars": 213,
    "preview": "<resources>\n\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizonta"
  },
  {
    "path": "BluetoothLeGatt/res/values/strings.xml",
    "chars": 1855,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n     Copyright (C) 2013 The Android Open Source Project\n\n     Licensed under"
  },
  {
    "path": "BluetoothLeGatt/res/values-w820dp/dimens.xml",
    "chars": 373,
    "preview": "<resources>\n\n    <!--\n         Example customization of dimensions originally defined in res/values/dimens.xml\n         "
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/BleApplication.java",
    "chars": 1118,
    "preview": "package com.example.bluetooth.le;\n\nimport android.app.Application;\nimport android.content.ComponentName;\nimport android."
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/CharacteristicActivity.java",
    "chars": 6523,
    "preview": "package com.example.bluetooth.le;\n\nimport java.util.UUID;\n\nimport org.apache.commons.codec.DecoderException;\nimport org."
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/DeviceControlActivity.java",
    "chars": 12908,
    "preview": "/*\n * Copyright (C) 2013 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/DeviceScanActivity.java",
    "chars": 10818,
    "preview": "/*\n * Copyright (C) 2013 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"Lice"
  },
  {
    "path": "BluetoothLeGatt/src/com/example/bluetooth/le/Utils.java",
    "chars": 9518,
    "preview": "package com.example.bluetooth.le;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class Utils {\n\tpublic static "
  },
  {
    "path": "LICENSE",
    "chars": 11323,
    "preview": "Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licens"
  },
  {
    "path": "README.md",
    "chars": 2535,
    "preview": "GizwitsBLE\n==========\n\nGizwitsBLE solves the compatibility and reliability issues that have troubled developers. First, "
  }
]

// ... and 6 more files (download for full content)

About this extraction

This page contains the full source code of the xpg/GizwitsBLE GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 47 files (167.2 KB), approximately 42.6k tokens, and a symbol index with 231 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!