@ -0,0 +1,10 @@ |
|||||
|
*.iml |
||||
|
.gradle |
||||
|
/local.properties |
||||
|
/.idea/workspace.xml |
||||
|
/.idea/libraries |
||||
|
.DS_Store |
||||
|
/build |
||||
|
/captures |
||||
|
.externalNativeBuild |
||||
|
Application/build |
||||
@ -0,0 +1,18 @@ |
|||||
|
|
||||
|
# GOOGLE SAMPLE PACKAGING DATA |
||||
|
# |
||||
|
# This file is used by Google as part of our samples packaging process. |
||||
|
# End users may safely ignore this file. It has no relevance to other systems. |
||||
|
--- |
||||
|
status: PUBLISHED |
||||
|
technologies: [Android] |
||||
|
categories: [Connectivity] |
||||
|
languages: [Java] |
||||
|
solutions: [Mobile] |
||||
|
github: android-BluetoothLeGatt |
||||
|
level: ADVANCED |
||||
|
icon: screenshots/icon-web.png |
||||
|
apiRefs: |
||||
|
- android:android.app.Service |
||||
|
- android:android.bluetooth.BluetoothGattService |
||||
|
license: apache2 |
||||
@ -0,0 +1,22 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project version="4"> |
||||
|
<component name="CompilerConfiguration"> |
||||
|
<resourceExtensions /> |
||||
|
<wildcardResourcePatterns> |
||||
|
<entry name="!?*.java" /> |
||||
|
<entry name="!?*.form" /> |
||||
|
<entry name="!?*.class" /> |
||||
|
<entry name="!?*.groovy" /> |
||||
|
<entry name="!?*.scala" /> |
||||
|
<entry name="!?*.flex" /> |
||||
|
<entry name="!?*.kt" /> |
||||
|
<entry name="!?*.clj" /> |
||||
|
<entry name="!?*.aj" /> |
||||
|
</wildcardResourcePatterns> |
||||
|
<annotationProcessing> |
||||
|
<profile default="true" name="Default" enabled="false"> |
||||
|
<processorPath useClasspath="true" /> |
||||
|
</profile> |
||||
|
</annotationProcessing> |
||||
|
</component> |
||||
|
</project> |
||||
@ -0,0 +1,3 @@ |
|||||
|
<component name="CopyrightManager"> |
||||
|
<settings default="" /> |
||||
|
</component> |
||||
@ -0,0 +1,18 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project version="4"> |
||||
|
<component name="GradleSettings"> |
||||
|
<option name="linkedExternalProjectsSettings"> |
||||
|
<GradleProjectSettings> |
||||
|
<option name="distributionType" value="DEFAULT_WRAPPED" /> |
||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" /> |
||||
|
<option name="modules"> |
||||
|
<set> |
||||
|
<option value="$PROJECT_DIR$" /> |
||||
|
<option value="$PROJECT_DIR$/Application" /> |
||||
|
</set> |
||||
|
</option> |
||||
|
<option name="resolveModulePerSourceSet" value="false" /> |
||||
|
</GradleProjectSettings> |
||||
|
</option> |
||||
|
</component> |
||||
|
</project> |
||||
@ -0,0 +1,46 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project version="4"> |
||||
|
<component name="EntryPointsManager"> |
||||
|
<entry_points version="2.0" /> |
||||
|
</component> |
||||
|
<component name="NullableNotNullManager"> |
||||
|
<option name="myDefaultNullable" value="android.support.annotation.Nullable" /> |
||||
|
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" /> |
||||
|
<option name="myNullables"> |
||||
|
<value> |
||||
|
<list size="4"> |
||||
|
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" /> |
||||
|
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" /> |
||||
|
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" /> |
||||
|
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" /> |
||||
|
</list> |
||||
|
</value> |
||||
|
</option> |
||||
|
<option name="myNotNulls"> |
||||
|
<value> |
||||
|
<list size="4"> |
||||
|
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" /> |
||||
|
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" /> |
||||
|
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" /> |
||||
|
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" /> |
||||
|
</list> |
||||
|
</value> |
||||
|
</option> |
||||
|
</component> |
||||
|
<component name="ProjectLevelVcsManager" settingsEditedManually="false"> |
||||
|
<OptionsSetting value="true" id="Add" /> |
||||
|
<OptionsSetting value="true" id="Remove" /> |
||||
|
<OptionsSetting value="true" id="Checkout" /> |
||||
|
<OptionsSetting value="true" id="Update" /> |
||||
|
<OptionsSetting value="true" id="Status" /> |
||||
|
<OptionsSetting value="true" id="Edit" /> |
||||
|
<ConfirmationsSetting value="0" id="Add" /> |
||||
|
<ConfirmationsSetting value="0" id="Remove" /> |
||||
|
</component> |
||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="JDK" project-jdk-type="JavaSDK"> |
||||
|
<output url="file://$PROJECT_DIR$/build/classes" /> |
||||
|
</component> |
||||
|
<component name="ProjectType"> |
||||
|
<option name="id" value="Android" /> |
||||
|
</component> |
||||
|
</project> |
||||
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project version="4"> |
||||
|
<component name="ProjectModuleManager"> |
||||
|
<modules> |
||||
|
<module fileurl="file://$PROJECT_DIR$/Application/Application.iml" filepath="$PROJECT_DIR$/Application/Application.iml" /> |
||||
|
<module fileurl="file://$PROJECT_DIR$/android-BluetoothLeGatt.iml" filepath="$PROJECT_DIR$/android-BluetoothLeGatt.iml" /> |
||||
|
</modules> |
||||
|
</component> |
||||
|
</project> |
||||
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project version="4"> |
||||
|
<component name="RunConfigurationProducerService"> |
||||
|
<option name="ignoredProducers"> |
||||
|
<set> |
||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" /> |
||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" /> |
||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" /> |
||||
|
</set> |
||||
|
</option> |
||||
|
</component> |
||||
|
</project> |
||||
@ -0,0 +1,6 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project version="4"> |
||||
|
<component name="VcsDirectoryMappings"> |
||||
|
<mapping directory="" vcs="Git" /> |
||||
|
</component> |
||||
|
</project> |
||||
@ -0,0 +1,59 @@ |
|||||
|
|
||||
|
buildscript { |
||||
|
repositories { |
||||
|
jcenter() |
||||
|
} |
||||
|
|
||||
|
dependencies { |
||||
|
classpath 'com.android.tools.build:gradle:2.3.2' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
apply plugin: 'com.android.application' |
||||
|
|
||||
|
repositories { |
||||
|
jcenter() |
||||
|
} |
||||
|
|
||||
|
dependencies { |
||||
|
compile "com.android.support:support-v4:25.0.1" |
||||
|
compile "com.android.support:support-v13:25.0.1" |
||||
|
compile "com.android.support:cardview-v7:25.0.1" |
||||
|
compile "com.android.support:appcompat-v7:25.0.1" |
||||
|
} |
||||
|
|
||||
|
// The sample build uses multiple directories to |
||||
|
// keep boilerplate and common code separate from |
||||
|
// the main sample code. |
||||
|
List<String> dirs = [ |
||||
|
'main', // main sample code; look here for the interesting stuff. |
||||
|
'common', // components that are reused by multiple samples |
||||
|
'template'] // boilerplate code that is generated by the sample template process |
||||
|
|
||||
|
android { |
||||
|
compileSdkVersion 25 |
||||
|
buildToolsVersion "25.0.2" |
||||
|
|
||||
|
defaultConfig { |
||||
|
minSdkVersion 18 |
||||
|
targetSdkVersion 25 |
||||
|
} |
||||
|
|
||||
|
compileOptions { |
||||
|
sourceCompatibility JavaVersion.VERSION_1_7 |
||||
|
targetCompatibility JavaVersion.VERSION_1_7 |
||||
|
} |
||||
|
|
||||
|
sourceSets { |
||||
|
main { |
||||
|
dirs.each { dir -> |
||||
|
java.srcDirs "src/${dir}/java" |
||||
|
res.srcDirs "src/${dir}/res" |
||||
|
} |
||||
|
} |
||||
|
androidTest.setRoot('tests') |
||||
|
androidTest.java.srcDirs = ['tests/src'] |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,51 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!-- |
||||
|
Copyright 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.android.bluetoothlegatt" |
||||
|
android:versionCode="1" |
||||
|
android:versionName="1.0"> |
||||
|
|
||||
|
<!-- Min/target SDK versions (<uses-sdk>) managed by build.gradle --> |
||||
|
|
||||
|
<!-- 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.ACCESS_COARSE_LOCATION"/> |
||||
|
|
||||
|
<application android:label="@string/app_name" |
||||
|
android:icon="@drawable/ic_launcher" |
||||
|
android:theme="@android:style/Theme.Holo.Light"> |
||||
|
<activity android:name=".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=".DeviceControlActivity"/> |
||||
|
<service android:name=".BluetoothLeService" android:enabled="true"/> |
||||
|
</application> |
||||
|
|
||||
|
</manifest> |
||||
@ -0,0 +1,319 @@ |
|||||
|
/* |
||||
|
* Copyright (C) 2013 The Android Open Source Project |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
|
||||
|
package com.example.android.bluetoothlegatt; |
||||
|
|
||||
|
import android.app.Service; |
||||
|
import android.bluetooth.BluetoothAdapter; |
||||
|
import android.bluetooth.BluetoothDevice; |
||||
|
import android.bluetooth.BluetoothGatt; |
||||
|
import android.bluetooth.BluetoothGattCallback; |
||||
|
import android.bluetooth.BluetoothGattCharacteristic; |
||||
|
import android.bluetooth.BluetoothGattDescriptor; |
||||
|
import android.bluetooth.BluetoothGattService; |
||||
|
import android.bluetooth.BluetoothManager; |
||||
|
import android.bluetooth.BluetoothProfile; |
||||
|
import android.content.Context; |
||||
|
import android.content.Intent; |
||||
|
import android.os.Binder; |
||||
|
import android.os.IBinder; |
||||
|
import android.util.Log; |
||||
|
|
||||
|
import java.util.List; |
||||
|
import java.util.UUID; |
||||
|
|
||||
|
/** |
||||
|
* Service for managing connection and data communication with a GATT server hosted on a |
||||
|
* given Bluetooth LE device. |
||||
|
*/ |
||||
|
public class BluetoothLeService extends Service { |
||||
|
private final static String TAG = BluetoothLeService.class.getSimpleName(); |
||||
|
|
||||
|
private BluetoothManager mBluetoothManager; |
||||
|
private BluetoothAdapter mBluetoothAdapter; |
||||
|
private String mBluetoothDeviceAddress; |
||||
|
private BluetoothGatt mBluetoothGatt; |
||||
|
private int mConnectionState = STATE_DISCONNECTED; |
||||
|
|
||||
|
private static final int STATE_DISCONNECTED = 0; |
||||
|
private static final int STATE_CONNECTING = 1; |
||||
|
private static final int STATE_CONNECTED = 2; |
||||
|
|
||||
|
public final static String ACTION_GATT_CONNECTED = |
||||
|
"com.example.bluetooth.le.ACTION_GATT_CONNECTED"; |
||||
|
public final static String ACTION_GATT_DISCONNECTED = |
||||
|
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; |
||||
|
public final static String ACTION_GATT_SERVICES_DISCOVERED = |
||||
|
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED"; |
||||
|
public final static String ACTION_DATA_AVAILABLE = |
||||
|
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE"; |
||||
|
public final static String EXTRA_DATA = |
||||
|
"com.example.bluetooth.le.EXTRA_DATA"; |
||||
|
|
||||
|
public final static UUID UUID_HEART_RATE_MEASUREMENT = |
||||
|
UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT); |
||||
|
|
||||
|
// Implements callback methods for GATT events that the app cares about. For example,
|
||||
|
// connection change and services discovered.
|
||||
|
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { |
||||
|
@Override |
||||
|
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { |
||||
|
String intentAction; |
||||
|
if (newState == BluetoothProfile.STATE_CONNECTED) { |
||||
|
intentAction = ACTION_GATT_CONNECTED; |
||||
|
mConnectionState = STATE_CONNECTED; |
||||
|
broadcastUpdate(intentAction); |
||||
|
Log.i(TAG, "Connected to GATT server."); |
||||
|
// Attempts to discover services after successful connection.
|
||||
|
Log.i(TAG, "Attempting to start service discovery:" + |
||||
|
mBluetoothGatt.discoverServices()); |
||||
|
|
||||
|
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { |
||||
|
intentAction = ACTION_GATT_DISCONNECTED; |
||||
|
mConnectionState = STATE_DISCONNECTED; |
||||
|
Log.i(TAG, "Disconnected from GATT server."); |
||||
|
broadcastUpdate(intentAction); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onServicesDiscovered(BluetoothGatt gatt, int status) { |
||||
|
if (status == BluetoothGatt.GATT_SUCCESS) { |
||||
|
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); |
||||
|
} else { |
||||
|
Log.w(TAG, "onServicesDiscovered received: " + status); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onCharacteristicRead(BluetoothGatt gatt, |
||||
|
BluetoothGattCharacteristic characteristic, |
||||
|
int status) { |
||||
|
if (status == BluetoothGatt.GATT_SUCCESS) { |
||||
|
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onCharacteristicChanged(BluetoothGatt gatt, |
||||
|
BluetoothGattCharacteristic characteristic) { |
||||
|
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
private void broadcastUpdate(final String action) { |
||||
|
final Intent intent = new Intent(action); |
||||
|
sendBroadcast(intent); |
||||
|
} |
||||
|
|
||||
|
private void broadcastUpdate(final String action, |
||||
|
final BluetoothGattCharacteristic characteristic) { |
||||
|
final Intent intent = new Intent(action); |
||||
|
|
||||
|
// This is special handling for the Heart Rate Measurement profile. Data parsing is
|
||||
|
// carried out as per profile specifications:
|
||||
|
// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
|
||||
|
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { |
||||
|
int flag = characteristic.getProperties(); |
||||
|
int format = -1; |
||||
|
if ((flag & 0x01) != 0) { |
||||
|
format = BluetoothGattCharacteristic.FORMAT_UINT16; |
||||
|
Log.d(TAG, "Heart rate format UINT16."); |
||||
|
} else { |
||||
|
format = BluetoothGattCharacteristic.FORMAT_UINT8; |
||||
|
Log.d(TAG, "Heart rate format UINT8."); |
||||
|
} |
||||
|
final int heartRate = characteristic.getIntValue(format, 1); |
||||
|
Log.d(TAG, String.format("Received heart rate: %d", heartRate)); |
||||
|
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate)); |
||||
|
} else { |
||||
|
// For all other profiles, writes the data formatted in HEX.
|
||||
|
final byte[] data = characteristic.getValue(); |
||||
|
if (data != null && data.length > 0) { |
||||
|
final StringBuilder stringBuilder = new StringBuilder(data.length); |
||||
|
for(byte byteChar : data) |
||||
|
stringBuilder.append(String.format("%02X ", byteChar)); |
||||
|
intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString()); |
||||
|
} |
||||
|
} |
||||
|
sendBroadcast(intent); |
||||
|
} |
||||
|
|
||||
|
public class LocalBinder extends Binder { |
||||
|
BluetoothLeService getService() { |
||||
|
return BluetoothLeService.this; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public IBinder onBind(Intent intent) { |
||||
|
return mBinder; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean onUnbind(Intent intent) { |
||||
|
// After using a given device, you should make sure that BluetoothGatt.close() is called
|
||||
|
// such that resources are cleaned up properly. In this particular example, close() is
|
||||
|
// invoked when the UI is disconnected from the Service.
|
||||
|
close(); |
||||
|
return super.onUnbind(intent); |
||||
|
} |
||||
|
|
||||
|
private final IBinder mBinder = new LocalBinder(); |
||||
|
|
||||
|
/** |
||||
|
* Initializes a reference to the local Bluetooth adapter. |
||||
|
* |
||||
|
* @return Return true if the initialization is successful. |
||||
|
*/ |
||||
|
public boolean initialize() { |
||||
|
// For API level 18 and above, get a reference to BluetoothAdapter through
|
||||
|
// BluetoothManager.
|
||||
|
if (mBluetoothManager == null) { |
||||
|
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); |
||||
|
if (mBluetoothManager == null) { |
||||
|
Log.e(TAG, "Unable to initialize BluetoothManager."); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
mBluetoothAdapter = mBluetoothManager.getAdapter(); |
||||
|
if (mBluetoothAdapter == null) { |
||||
|
Log.e(TAG, "Unable to obtain a BluetoothAdapter."); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Connects to the GATT server hosted on the Bluetooth LE device. |
||||
|
* |
||||
|
* @param address The device address of the destination device. |
||||
|
* |
||||
|
* @return Return true if the connection is initiated successfully. The connection result |
||||
|
* is reported asynchronously through the |
||||
|
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} |
||||
|
* callback. |
||||
|
*/ |
||||
|
public boolean connect(final String address) { |
||||
|
if (mBluetoothAdapter == null || address == null) { |
||||
|
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// Previously connected device. Try to reconnect.
|
||||
|
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) |
||||
|
&& mBluetoothGatt != null) { |
||||
|
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection."); |
||||
|
if (mBluetoothGatt.connect()) { |
||||
|
mConnectionState = STATE_CONNECTING; |
||||
|
return true; |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); |
||||
|
if (device == null) { |
||||
|
Log.w(TAG, "Device not found. Unable to connect."); |
||||
|
return false; |
||||
|
} |
||||
|
// We want to directly connect to the device, so we are setting the autoConnect
|
||||
|
// parameter to false.
|
||||
|
mBluetoothGatt = device.connectGatt(this, false, mGattCallback); |
||||
|
Log.d(TAG, "Trying to create a new connection."); |
||||
|
mBluetoothDeviceAddress = address; |
||||
|
mConnectionState = STATE_CONNECTING; |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Disconnects an existing connection or cancel a pending connection. The disconnection result |
||||
|
* is reported asynchronously through the |
||||
|
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} |
||||
|
* callback. |
||||
|
*/ |
||||
|
public void disconnect() { |
||||
|
if (mBluetoothAdapter == null || mBluetoothGatt == null) { |
||||
|
Log.w(TAG, "BluetoothAdapter not initialized"); |
||||
|
return; |
||||
|
} |
||||
|
mBluetoothGatt.disconnect(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* After using a given BLE device, the app must call this method to ensure resources are |
||||
|
* released properly. |
||||
|
*/ |
||||
|
public void close() { |
||||
|
if (mBluetoothGatt == null) { |
||||
|
return; |
||||
|
} |
||||
|
mBluetoothGatt.close(); |
||||
|
mBluetoothGatt = null; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported |
||||
|
* asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} |
||||
|
* callback. |
||||
|
* |
||||
|
* @param characteristic The characteristic to read from. |
||||
|
*/ |
||||
|
public void readCharacteristic(BluetoothGattCharacteristic characteristic) { |
||||
|
if (mBluetoothAdapter == null || mBluetoothGatt == null) { |
||||
|
Log.w(TAG, "BluetoothAdapter not initialized"); |
||||
|
return; |
||||
|
} |
||||
|
mBluetoothGatt.readCharacteristic(characteristic); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Enables or disables notification on a give characteristic. |
||||
|
* |
||||
|
* @param characteristic Characteristic to act on. |
||||
|
* @param enabled If true, enable notification. False otherwise. |
||||
|
*/ |
||||
|
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, |
||||
|
boolean enabled) { |
||||
|
if (mBluetoothAdapter == null || mBluetoothGatt == null) { |
||||
|
Log.w(TAG, "BluetoothAdapter not initialized"); |
||||
|
return; |
||||
|
} |
||||
|
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); |
||||
|
|
||||
|
// This is specific to Heart Rate Measurement.
|
||||
|
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { |
||||
|
BluetoothGattDescriptor descriptor = characteristic.getDescriptor( |
||||
|
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG)); |
||||
|
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); |
||||
|
mBluetoothGatt.writeDescriptor(descriptor); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Retrieves a list of supported GATT services on the connected device. This should be |
||||
|
* invoked only after {@code BluetoothGatt#discoverServices()} completes successfully. |
||||
|
* |
||||
|
* @return A {@code List} of supported services. |
||||
|
*/ |
||||
|
public List<BluetoothGattService> getSupportedGattServices() { |
||||
|
if (mBluetoothGatt == null) return null; |
||||
|
|
||||
|
return mBluetoothGatt.getServices(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,309 @@ |
|||||
|
/* |
||||
|
* Copyright (C) 2013 The Android Open Source Project |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
|
||||
|
package com.example.android.bluetoothlegatt; |
||||
|
|
||||
|
import android.app.Activity; |
||||
|
import android.bluetooth.BluetoothGattCharacteristic; |
||||
|
import android.bluetooth.BluetoothGattService; |
||||
|
import android.content.BroadcastReceiver; |
||||
|
import android.content.ComponentName; |
||||
|
import android.content.Context; |
||||
|
import android.content.Intent; |
||||
|
import android.content.IntentFilter; |
||||
|
import android.content.ServiceConnection; |
||||
|
import android.os.Bundle; |
||||
|
import android.os.IBinder; |
||||
|
import android.util.Log; |
||||
|
import android.view.Menu; |
||||
|
import android.view.MenuItem; |
||||
|
import android.view.View; |
||||
|
import android.widget.ExpandableListView; |
||||
|
import android.widget.SimpleExpandableListAdapter; |
||||
|
import android.widget.TextView; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 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 TextView mDataField; |
||||
|
private String mDeviceName; |
||||
|
private String mDeviceAddress; |
||||
|
private ExpandableListView mGattServicesList; |
||||
|
private BluetoothLeService mBluetoothLeService; |
||||
|
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = |
||||
|
new ArrayList<ArrayList<BluetoothGattCharacteristic>>(); |
||||
|
private boolean mConnected = false; |
||||
|
private BluetoothGattCharacteristic mNotifyCharacteristic; |
||||
|
|
||||
|
private final String LIST_NAME = "NAME"; |
||||
|
private final String LIST_UUID = "UUID"; |
||||
|
|
||||
|
// Code to manage Service lifecycle.
|
||||
|
private final ServiceConnection mServiceConnection = new ServiceConnection() { |
||||
|
|
||||
|
@Override |
||||
|
public void onServiceConnected(ComponentName componentName, IBinder service) { |
||||
|
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); |
||||
|
if (!mBluetoothLeService.initialize()) { |
||||
|
Log.e(TAG, "Unable to initialize Bluetooth"); |
||||
|
finish(); |
||||
|
} |
||||
|
// Automatically connects to the device upon successful start-up initialization.
|
||||
|
mBluetoothLeService.connect(mDeviceAddress); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void onServiceDisconnected(ComponentName componentName) { |
||||
|
mBluetoothLeService = null; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// Handles various events fired by the Service.
|
||||
|
// ACTION_GATT_CONNECTED: connected to a GATT server.
|
||||
|
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
|
||||
|
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
|
||||
|
// ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read
|
||||
|
// or notification operations.
|
||||
|
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { |
||||
|
@Override |
||||
|
public void onReceive(Context context, Intent intent) { |
||||
|
final String action = intent.getAction(); |
||||
|
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { |
||||
|
mConnected = true; |
||||
|
updateConnectionState(R.string.connected); |
||||
|
invalidateOptionsMenu(); |
||||
|
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { |
||||
|
mConnected = false; |
||||
|
updateConnectionState(R.string.disconnected); |
||||
|
invalidateOptionsMenu(); |
||||
|
clearUI(); |
||||
|
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { |
||||
|
// Show all the supported services and characteristics on the user interface.
|
||||
|
displayGattServices(mBluetoothLeService.getSupportedGattServices()); |
||||
|
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { |
||||
|
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// If a given GATT characteristic is selected, check for supported features. This sample
|
||||
|
// demonstrates 'Read' and 'Notify' features. See
|
||||
|
// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
|
||||
|
// list of supported characteristic features.
|
||||
|
private final ExpandableListView.OnChildClickListener servicesListClickListner = |
||||
|
new ExpandableListView.OnChildClickListener() { |
||||
|
@Override |
||||
|
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, |
||||
|
int childPosition, long id) { |
||||
|
if (mGattCharacteristics != null) { |
||||
|
final BluetoothGattCharacteristic characteristic = |
||||
|
mGattCharacteristics.get(groupPosition).get(childPosition); |
||||
|
final int charaProp = characteristic.getProperties(); |
||||
|
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) { |
||||
|
// If there is an active notification on a characteristic, clear
|
||||
|
// it first so it doesn't update the data field on the user interface.
|
||||
|
if (mNotifyCharacteristic != null) { |
||||
|
mBluetoothLeService.setCharacteristicNotification( |
||||
|
mNotifyCharacteristic, false); |
||||
|
mNotifyCharacteristic = null; |
||||
|
} |
||||
|
mBluetoothLeService.readCharacteristic(characteristic); |
||||
|
} |
||||
|
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { |
||||
|
mNotifyCharacteristic = characteristic; |
||||
|
mBluetoothLeService.setCharacteristicNotification( |
||||
|
characteristic, true); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
private void clearUI() { |
||||
|
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null); |
||||
|
mDataField.setText(R.string.no_data); |
||||
|
} |
||||
|
|
||||
|
@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); |
||||
|
mDataField = (TextView) findViewById(R.id.data_value); |
||||
|
|
||||
|
getActionBar().setTitle(mDeviceName); |
||||
|
getActionBar().setDisplayHomeAsUpEnabled(true); |
||||
|
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); |
||||
|
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onResume() { |
||||
|
super.onResume(); |
||||
|
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); |
||||
|
if (mBluetoothLeService != null) { |
||||
|
final boolean result = mBluetoothLeService.connect(mDeviceAddress); |
||||
|
Log.d(TAG, "Connect request result=" + result); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onPause() { |
||||
|
super.onPause(); |
||||
|
unregisterReceiver(mGattUpdateReceiver); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void onDestroy() { |
||||
|
super.onDestroy(); |
||||
|
unbindService(mServiceConnection); |
||||
|
mBluetoothLeService = null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean onCreateOptionsMenu(Menu menu) { |
||||
|
getMenuInflater().inflate(R.menu.gatt_services, menu); |
||||
|
if (mConnected) { |
||||
|
menu.findItem(R.id.menu_connect).setVisible(false); |
||||
|
menu.findItem(R.id.menu_disconnect).setVisible(true); |
||||
|
} else { |
||||
|
menu.findItem(R.id.menu_connect).setVisible(true); |
||||
|
menu.findItem(R.id.menu_disconnect).setVisible(false); |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean onOptionsItemSelected(MenuItem item) { |
||||
|
switch(item.getItemId()) { |
||||
|
case R.id.menu_connect: |
||||
|
mBluetoothLeService.connect(mDeviceAddress); |
||||
|
return true; |
||||
|
case R.id.menu_disconnect: |
||||
|
mBluetoothLeService.disconnect(); |
||||
|
return true; |
||||
|
case android.R.id.home: |
||||
|
onBackPressed(); |
||||
|
return true; |
||||
|
} |
||||
|
return super.onOptionsItemSelected(item); |
||||
|
} |
||||
|
|
||||
|
private void updateConnectionState(final int resourceId) { |
||||
|
runOnUiThread(new Runnable() { |
||||
|
@Override |
||||
|
public void run() { |
||||
|
mConnectionState.setText(resourceId); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
private void displayData(String data) { |
||||
|
if (data != null) { |
||||
|
mDataField.setText(data); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Demonstrates how to iterate through the supported GATT Services/Characteristics.
|
||||
|
// In this sample, we populate the data structure that is bound to the ExpandableListView
|
||||
|
// on the UI.
|
||||
|
private void displayGattServices(List<BluetoothGattService> 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<BluetoothGattCharacteristic>>(); |
||||
|
|
||||
|
// Loops through available GATT Services.
|
||||
|
for (BluetoothGattService gattService : gattServices) { |
||||
|
HashMap<String, String> currentServiceData = new HashMap<String, String>(); |
||||
|
uuid = gattService.getUuid().toString(); |
||||
|
currentServiceData.put( |
||||
|
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString)); |
||||
|
currentServiceData.put(LIST_UUID, uuid); |
||||
|
gattServiceData.add(currentServiceData); |
||||
|
|
||||
|
ArrayList<HashMap<String, String>> gattCharacteristicGroupData = |
||||
|
new ArrayList<HashMap<String, String>>(); |
||||
|
List<BluetoothGattCharacteristic> gattCharacteristics = |
||||
|
gattService.getCharacteristics(); |
||||
|
ArrayList<BluetoothGattCharacteristic> charas = |
||||
|
new ArrayList<BluetoothGattCharacteristic>(); |
||||
|
|
||||
|
// Loops through available Characteristics.
|
||||
|
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) { |
||||
|
charas.add(gattCharacteristic); |
||||
|
HashMap<String, String> currentCharaData = new HashMap<String, String>(); |
||||
|
uuid = gattCharacteristic.getUuid().toString(); |
||||
|
currentCharaData.put( |
||||
|
LIST_NAME, SampleGattAttributes.lookup(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 static IntentFilter makeGattUpdateIntentFilter() { |
||||
|
final IntentFilter intentFilter = new IntentFilter(); |
||||
|
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED); |
||||
|
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED); |
||||
|
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED); |
||||
|
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE); |
||||
|
return intentFilter; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,300 @@ |
|||||
|
/* |
||||
|
* Copyright (C) 2013 The Android Open Source Project |
||||
|
* Copyright (C) 2017 Louis-Guillaume Dubois |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
|
||||
|
package com.example.android.bluetoothlegatt; |
||||
|
|
||||
|
import android.Manifest; |
||||
|
import android.app.Activity; |
||||
|
import android.app.ListActivity; |
||||
|
import android.bluetooth.BluetoothAdapter; |
||||
|
import android.bluetooth.BluetoothDevice; |
||||
|
import android.bluetooth.BluetoothManager; |
||||
|
import android.content.Context; |
||||
|
import android.content.Intent; |
||||
|
import android.content.pm.PackageManager; |
||||
|
import android.os.Bundle; |
||||
|
import android.os.Handler; |
||||
|
import android.support.v4.app.ActivityCompat; |
||||
|
import android.support.v4.content.ContextCompat; |
||||
|
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 java.util.ArrayList; |
||||
|
|
||||
|
/** |
||||
|
* Activity for scanning and displaying available Bluetooth LE devices. |
||||
|
*/ |
||||
|
public class DeviceScanActivity extends ListActivity { |
||||
|
private LeDeviceListAdapter mLeDeviceListAdapter; |
||||
|
private BluetoothAdapter mBluetoothAdapter; |
||||
|
private boolean mScanning; |
||||
|
private Handler mHandler; |
||||
|
|
||||
|
private static final int REQUEST_ENABLE_COARSE_LOCATION = 2; |
||||
|
private static final int REQUEST_ENABLE_BT = 1; |
||||
|
// Stops scanning after 10 seconds.
|
||||
|
private static final long SCAN_PERIOD = 10000; |
||||
|
|
||||
|
@Override |
||||
|
public void onCreate(Bundle savedInstanceState) { |
||||
|
super.onCreate(savedInstanceState); |
||||
|
getActionBar().setTitle(R.string.title_devices); |
||||
|
mHandler = new Handler(); |
||||
|
|
||||
|
// Use this check to determine whether BLE is supported on the device. Then you can
|
||||
|
// selectively disable BLE-related features.
|
||||
|
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { |
||||
|
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); |
||||
|
finish(); |
||||
|
} |
||||
|
|
||||
|
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
|
||||
|
// BluetoothAdapter through BluetoothManager.
|
||||
|
final BluetoothManager bluetoothManager = |
||||
|
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); |
||||
|
mBluetoothAdapter = bluetoothManager.getAdapter(); |
||||
|
|
||||
|
// Checks if Bluetooth is supported on the device.
|
||||
|
if (mBluetoothAdapter == null) { |
||||
|
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show(); |
||||
|
finish(); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// demande des permissions au cas où
|
||||
|
if (ContextCompat.checkSelfPermission(this, |
||||
|
Manifest.permission.ACCESS_COARSE_LOCATION) |
||||
|
!= PackageManager.PERMISSION_GRANTED) { |
||||
|
|
||||
|
// Should we show an explanation?
|
||||
|
if (ActivityCompat.shouldShowRequestPermissionRationale(this, |
||||
|
Manifest.permission.ACCESS_COARSE_LOCATION)) { |
||||
|
|
||||
|
// Show an explanation to the user *asynchronously* -- don't block
|
||||
|
// this thread waiting for the user's response! After the user
|
||||
|
// sees the explanation, try again to request the permission.
|
||||
|
|
||||
|
} else { |
||||
|
|
||||
|
// No explanation needed, we can request the permission.
|
||||
|
|
||||
|
ActivityCompat.requestPermissions(this, |
||||
|
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, |
||||
|
REQUEST_ENABLE_COARSE_LOCATION); |
||||
|
|
||||
|
// REQUEST_ENABLE_ACCESS_COARSE_LOCATION is an
|
||||
|
// app-defined int constant. The callback method gets the
|
||||
|
// result of the request.
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@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(); |
||||
|
|
||||
|
// 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 (!mBluetoothAdapter.isEnabled()) { |
||||
|
if (!mBluetoothAdapter.isEnabled()) { |
||||
|
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(); |
||||
|
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 (mScanning) { |
||||
|
mBluetoothAdapter.stopLeScan(mLeScanCallback); |
||||
|
mScanning = false; |
||||
|
} |
||||
|
startActivity(intent); |
||||
|
} |
||||
|
|
||||
|
private void scanLeDevice(final boolean enable) { |
||||
|
if (enable) { |
||||
|
// Stops scanning after a pre-defined scan period.
|
||||
|
mHandler.postDelayed(new Runnable() { |
||||
|
@Override |
||||
|
public void run() { |
||||
|
mScanning = false; |
||||
|
mBluetoothAdapter.stopLeScan(mLeScanCallback); |
||||
|
invalidateOptionsMenu(); |
||||
|
} |
||||
|
}, SCAN_PERIOD); |
||||
|
|
||||
|
mScanning = true; |
||||
|
mBluetoothAdapter.startLeScan(mLeScanCallback); |
||||
|
} else { |
||||
|
mScanning = false; |
||||
|
mBluetoothAdapter.stopLeScan(mLeScanCallback); |
||||
|
} |
||||
|
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; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Device scan callback.
|
||||
|
private BluetoothAdapter.LeScanCallback mLeScanCallback = |
||||
|
new BluetoothAdapter.LeScanCallback() { |
||||
|
|
||||
|
@Override |
||||
|
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { |
||||
|
runOnUiThread(new Runnable() { |
||||
|
@Override |
||||
|
public void run() { |
||||
|
mLeDeviceListAdapter.addDevice(device); |
||||
|
mLeDeviceListAdapter.notifyDataSetChanged(); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
static class ViewHolder { |
||||
|
TextView deviceName; |
||||
|
TextView deviceAddress; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
/* |
||||
|
* Copyright (C) 2013 The Android Open Source Project |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
|
||||
|
package com.example.android.bluetoothlegatt; |
||||
|
|
||||
|
import java.util.HashMap; |
||||
|
|
||||
|
/** |
||||
|
* This class includes a small subset of standard GATT attributes for demonstration purposes. |
||||
|
*/ |
||||
|
public class SampleGattAttributes { |
||||
|
private static HashMap<String, String> attributes = new HashMap(); |
||||
|
public static String HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb"; |
||||
|
public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb"; |
||||
|
|
||||
|
static { |
||||
|
// Sample Services.
|
||||
|
attributes.put("0000180d-0000-1000-8000-00805f9b34fb", "Heart Rate Service"); |
||||
|
attributes.put("0000180a-0000-1000-8000-00805f9b34fb", "Device Information Service"); |
||||
|
// Sample Characteristics.
|
||||
|
attributes.put(HEART_RATE_MEASUREMENT, "Heart Rate Measurement"); |
||||
|
attributes.put("00002a29-0000-1000-8000-00805f9b34fb", "Manufacturer Name String"); |
||||
|
} |
||||
|
|
||||
|
public static String lookup(String uuid, String defaultName) { |
||||
|
String name = attributes.get(uuid); |
||||
|
return name == null ? defaultName : name; |
||||
|
} |
||||
|
} |
||||
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 196 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,23 @@ |
|||||
|
<!-- |
||||
|
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> |
||||
@ -0,0 +1,71 @@ |
|||||
|
<?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" |
||||
|
android:layout_margin="10dp"> |
||||
|
<LinearLayout android:orientation="horizontal" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_margin="10dp"> |
||||
|
<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:orientation="horizontal" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_margin="10dp"> |
||||
|
<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> |
||||
|
<LinearLayout android:orientation="horizontal" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:layout_margin="10dp"> |
||||
|
<TextView android:layout_width="wrap_content" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:text="@string/label_data" |
||||
|
android:textSize="18sp"/> |
||||
|
<Space android:layout_width="5dp" |
||||
|
android:layout_height="wrap_content"/> |
||||
|
<TextView android:id="@+id/data_value" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content" |
||||
|
android:text="@string/no_data" |
||||
|
android:textSize="18sp"/> |
||||
|
</LinearLayout> |
||||
|
<ExpandableListView android:id="@+id/gatt_services_list" |
||||
|
android:layout_width="match_parent" |
||||
|
android:layout_height="wrap_content"/> |
||||
|
</LinearLayout> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<?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> |
||||
@ -0,0 +1,29 @@ |
|||||
|
<?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> |
||||
@ -0,0 +1,29 @@ |
|||||
|
<?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> |
||||
@ -0,0 +1,24 @@ |
|||||
|
<!-- |
||||
|
Copyright 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> |
||||
|
|
||||
|
<!-- Semantic definitions --> |
||||
|
|
||||
|
<dimen name="horizontal_page_margin">@dimen/margin_huge</dimen> |
||||
|
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen> |
||||
|
|
||||
|
</resources> |
||||
@ -0,0 +1,25 @@ |
|||||
|
<!-- |
||||
|
Copyright 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> |
||||
|
|
||||
|
<style name="Widget.SampleMessage"> |
||||
|
<item name="android:textAppearance">?android:textAppearanceLarge</item> |
||||
|
<item name="android:lineSpacingMultiplier">1.2</item> |
||||
|
<item name="android:shadowDy">-6.5</item> |
||||
|
</style> |
||||
|
|
||||
|
</resources> |
||||
@ -0,0 +1,22 @@ |
|||||
|
<!-- |
||||
|
Copyright 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> |
||||
|
|
||||
|
<!-- Activity themes --> |
||||
|
<style name="Theme.Base" parent="android:Theme.Holo.Light" /> |
||||
|
|
||||
|
</resources> |
||||
@ -0,0 +1,21 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!-- |
||||
|
Copyright 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> |
||||
|
|
||||
|
|
||||
|
</resources> |
||||
@ -0,0 +1,24 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!-- |
||||
|
Copyright 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> |
||||
|
|
||||
|
<!-- Activity themes --> |
||||
|
<style name="Theme.Base" parent="android:Theme.Material.Light"> |
||||
|
</style> |
||||
|
|
||||
|
</resources> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!-- |
||||
|
Copyright 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">BluetoothLeGatt</string> |
||||
|
<string name="intro_message"> |
||||
|
<![CDATA[ |
||||
|
|
||||
|
|
||||
|
This sample demonstrates how to use the Bluetooth LE Generic Attribute Profile (GATT) |
||||
|
to transmit arbitrary data between devices. |
||||
|
|
||||
|
|
||||
|
]]> |
||||
|
</string> |
||||
|
</resources> |
||||
@ -0,0 +1,36 @@ |
|||||
|
<?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="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> |
||||
|
</resources> |
||||
@ -0,0 +1,32 @@ |
|||||
|
<!-- |
||||
|
Copyright 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> |
||||
|
|
||||
|
<!-- Define standard dimensions to comply with Holo-style grids and rhythm. --> |
||||
|
|
||||
|
<dimen name="margin_tiny">4dp</dimen> |
||||
|
<dimen name="margin_small">8dp</dimen> |
||||
|
<dimen name="margin_medium">16dp</dimen> |
||||
|
<dimen name="margin_large">32dp</dimen> |
||||
|
<dimen name="margin_huge">64dp</dimen> |
||||
|
|
||||
|
<!-- Semantic definitions --> |
||||
|
|
||||
|
<dimen name="horizontal_page_margin">@dimen/margin_medium</dimen> |
||||
|
<dimen name="vertical_page_margin">@dimen/margin_medium</dimen> |
||||
|
|
||||
|
</resources> |
||||
@ -0,0 +1,42 @@ |
|||||
|
<!-- |
||||
|
Copyright 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> |
||||
|
|
||||
|
<!-- Activity themes --> |
||||
|
|
||||
|
<style name="Theme.Base" parent="android:Theme.Light" /> |
||||
|
|
||||
|
<style name="Theme.Sample" parent="Theme.Base" /> |
||||
|
|
||||
|
<style name="AppTheme" parent="Theme.Sample" /> |
||||
|
<!-- Widget styling --> |
||||
|
|
||||
|
<style name="Widget" /> |
||||
|
|
||||
|
<style name="Widget.SampleMessage"> |
||||
|
<item name="android:textAppearance">?android:textAppearanceMedium</item> |
||||
|
<item name="android:lineSpacingMultiplier">1.1</item> |
||||
|
</style> |
||||
|
|
||||
|
<style name="Widget.SampleMessageTile"> |
||||
|
<item name="android:background">@drawable/tile</item> |
||||
|
<item name="android:shadowColor">#7F000000</item> |
||||
|
<item name="android:shadowDy">-3.5</item> |
||||
|
<item name="android:shadowRadius">2</item> |
||||
|
</style> |
||||
|
|
||||
|
</resources> |
||||
@ -0,0 +1,647 @@ |
|||||
|
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. |
||||
|
|
||||
|
All image and audio files (including *.png, *.jpg, *.svg, *.mp3, *.wav |
||||
|
and *.ogg) are licensed under the CC-BY-NC license. All other files are |
||||
|
licensed under the Apache 2 license. |
||||
|
|
||||
|
CC-BY-NC License |
||||
|
---------------- |
||||
|
|
||||
|
Attribution-NonCommercial-ShareAlike 4.0 International |
||||
|
|
||||
|
======================================================================= |
||||
|
|
||||
|
Creative Commons Corporation ("Creative Commons") is not a law firm and |
||||
|
does not provide legal services or legal advice. Distribution of |
||||
|
Creative Commons public licenses does not create a lawyer-client or |
||||
|
other relationship. Creative Commons makes its licenses and related |
||||
|
information available on an "as-is" basis. Creative Commons gives no |
||||
|
warranties regarding its licenses, any material licensed under their |
||||
|
terms and conditions, or any related information. Creative Commons |
||||
|
disclaims all liability for damages resulting from their use to the |
||||
|
fullest extent possible. |
||||
|
|
||||
|
Using Creative Commons Public Licenses |
||||
|
|
||||
|
Creative Commons public licenses provide a standard set of terms and |
||||
|
conditions that creators and other rights holders may use to share |
||||
|
original works of authorship and other material subject to copyright |
||||
|
and certain other rights specified in the public license below. The |
||||
|
following considerations are for informational purposes only, are not |
||||
|
exhaustive, and do not form part of our licenses. |
||||
|
|
||||
|
Considerations for licensors: Our public licenses are |
||||
|
intended for use by those authorized to give the public |
||||
|
permission to use material in ways otherwise restricted by |
||||
|
copyright and certain other rights. Our licenses are |
||||
|
irrevocable. Licensors should read and understand the terms |
||||
|
and conditions of the license they choose before applying it. |
||||
|
Licensors should also secure all rights necessary before |
||||
|
applying our licenses so that the public can reuse the |
||||
|
material as expected. Licensors should clearly mark any |
||||
|
material not subject to the license. This includes other CC- |
||||
|
licensed material, or material used under an exception or |
||||
|
limitation to copyright. More considerations for licensors: |
||||
|
wiki.creativecommons.org/Considerations_for_licensors |
||||
|
|
||||
|
Considerations for the public: By using one of our public |
||||
|
licenses, a licensor grants the public permission to use the |
||||
|
licensed material under specified terms and conditions. If |
||||
|
the licensor's permission is not necessary for any reason--for |
||||
|
example, because of any applicable exception or limitation to |
||||
|
copyright--then that use is not regulated by the license. Our |
||||
|
licenses grant only permissions under copyright and certain |
||||
|
other rights that a licensor has authority to grant. Use of |
||||
|
the licensed material may still be restricted for other |
||||
|
reasons, including because others have copyright or other |
||||
|
rights in the material. A licensor may make special requests, |
||||
|
such as asking that all changes be marked or described. |
||||
|
Although not required by our licenses, you are encouraged to |
||||
|
respect those requests where reasonable. More_considerations |
||||
|
for the public: |
||||
|
wiki.creativecommons.org/Considerations_for_licensees |
||||
|
|
||||
|
======================================================================= |
||||
|
|
||||
|
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International |
||||
|
Public License |
||||
|
|
||||
|
By exercising the Licensed Rights (defined below), You accept and agree |
||||
|
to be bound by the terms and conditions of this Creative Commons |
||||
|
Attribution-NonCommercial-ShareAlike 4.0 International Public License |
||||
|
("Public License"). To the extent this Public License may be |
||||
|
interpreted as a contract, You are granted the Licensed Rights in |
||||
|
consideration of Your acceptance of these terms and conditions, and the |
||||
|
Licensor grants You such rights in consideration of benefits the |
||||
|
Licensor receives from making the Licensed Material available under |
||||
|
these terms and conditions. |
||||
|
|
||||
|
|
||||
|
Section 1 -- Definitions. |
||||
|
|
||||
|
a. Adapted Material means material subject to Copyright and Similar |
||||
|
Rights that is derived from or based upon the Licensed Material |
||||
|
and in which the Licensed Material is translated, altered, |
||||
|
arranged, transformed, or otherwise modified in a manner requiring |
||||
|
permission under the Copyright and Similar Rights held by the |
||||
|
Licensor. For purposes of this Public License, where the Licensed |
||||
|
Material is a musical work, performance, or sound recording, |
||||
|
Adapted Material is always produced where the Licensed Material is |
||||
|
synched in timed relation with a moving image. |
||||
|
|
||||
|
b. Adapter's License means the license You apply to Your Copyright |
||||
|
and Similar Rights in Your contributions to Adapted Material in |
||||
|
accordance with the terms and conditions of this Public License. |
||||
|
|
||||
|
c. BY-NC-SA Compatible License means a license listed at |
||||
|
creativecommons.org/compatiblelicenses, approved by Creative |
||||
|
Commons as essentially the equivalent of this Public License. |
||||
|
|
||||
|
d. Copyright and Similar Rights means copyright and/or similar rights |
||||
|
closely related to copyright including, without limitation, |
||||
|
performance, broadcast, sound recording, and Sui Generis Database |
||||
|
Rights, without regard to how the rights are labeled or |
||||
|
categorized. For purposes of this Public License, the rights |
||||
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar |
||||
|
Rights. |
||||
|
|
||||
|
e. Effective Technological Measures means those measures that, in the |
||||
|
absence of proper authority, may not be circumvented under laws |
||||
|
fulfilling obligations under Article 11 of the WIPO Copyright |
||||
|
Treaty adopted on December 20, 1996, and/or similar international |
||||
|
agreements. |
||||
|
|
||||
|
f. Exceptions and Limitations means fair use, fair dealing, and/or |
||||
|
any other exception or limitation to Copyright and Similar Rights |
||||
|
that applies to Your use of the Licensed Material. |
||||
|
|
||||
|
g. License Elements means the license attributes listed in the name |
||||
|
of a Creative Commons Public License. The License Elements of this |
||||
|
Public License are Attribution, NonCommercial, and ShareAlike. |
||||
|
|
||||
|
h. Licensed Material means the artistic or literary work, database, |
||||
|
or other material to which the Licensor applied this Public |
||||
|
License. |
||||
|
|
||||
|
i. Licensed Rights means the rights granted to You subject to the |
||||
|
terms and conditions of this Public License, which are limited to |
||||
|
all Copyright and Similar Rights that apply to Your use of the |
||||
|
Licensed Material and that the Licensor has authority to license. |
||||
|
|
||||
|
j. Licensor means the individual(s) or entity(ies) granting rights |
||||
|
under this Public License. |
||||
|
|
||||
|
k. NonCommercial means not primarily intended for or directed towards |
||||
|
commercial advantage or monetary compensation. For purposes of |
||||
|
this Public License, the exchange of the Licensed Material for |
||||
|
other material subject to Copyright and Similar Rights by digital |
||||
|
file-sharing or similar means is NonCommercial provided there is |
||||
|
no payment of monetary compensation in connection with the |
||||
|
exchange. |
||||
|
|
||||
|
l. Share means to provide material to the public by any means or |
||||
|
process that requires permission under the Licensed Rights, such |
||||
|
as reproduction, public display, public performance, distribution, |
||||
|
dissemination, communication, or importation, and to make material |
||||
|
available to the public including in ways that members of the |
||||
|
public may access the material from a place and at a time |
||||
|
individually chosen by them. |
||||
|
|
||||
|
m. Sui Generis Database Rights means rights other than copyright |
||||
|
resulting from Directive 96/9/EC of the European Parliament and of |
||||
|
the Council of 11 March 1996 on the legal protection of databases, |
||||
|
as amended and/or succeeded, as well as other essentially |
||||
|
equivalent rights anywhere in the world. |
||||
|
|
||||
|
n. You means the individual or entity exercising the Licensed Rights |
||||
|
under this Public License. Your has a corresponding meaning. |
||||
|
|
||||
|
|
||||
|
Section 2 -- Scope. |
||||
|
|
||||
|
a. License grant. |
||||
|
|
||||
|
1. Subject to the terms and conditions of this Public License, |
||||
|
the Licensor hereby grants You a worldwide, royalty-free, |
||||
|
non-sublicensable, non-exclusive, irrevocable license to |
||||
|
exercise the Licensed Rights in the Licensed Material to: |
||||
|
|
||||
|
a. reproduce and Share the Licensed Material, in whole or |
||||
|
in part, for NonCommercial purposes only; and |
||||
|
|
||||
|
b. produce, reproduce, and Share Adapted Material for |
||||
|
NonCommercial purposes only. |
||||
|
|
||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where |
||||
|
Exceptions and Limitations apply to Your use, this Public |
||||
|
License does not apply, and You do not need to comply with |
||||
|
its terms and conditions. |
||||
|
|
||||
|
3. Term. The term of this Public License is specified in Section |
||||
|
6(a). |
||||
|
|
||||
|
4. Media and formats; technical modifications allowed. The |
||||
|
Licensor authorizes You to exercise the Licensed Rights in |
||||
|
all media and formats whether now known or hereafter created, |
||||
|
and to make technical modifications necessary to do so. The |
||||
|
Licensor waives and/or agrees not to assert any right or |
||||
|
authority to forbid You from making technical modifications |
||||
|
necessary to exercise the Licensed Rights, including |
||||
|
technical modifications necessary to circumvent Effective |
||||
|
Technological Measures. For purposes of this Public License, |
||||
|
simply making modifications authorized by this Section 2(a) |
||||
|
(4) never produces Adapted Material. |
||||
|
|
||||
|
5. Downstream recipients. |
||||
|
|
||||
|
a. Offer from the Licensor -- Licensed Material. Every |
||||
|
recipient of the Licensed Material automatically |
||||
|
receives an offer from the Licensor to exercise the |
||||
|
Licensed Rights under the terms and conditions of this |
||||
|
Public License. |
||||
|
|
||||
|
b. Additional offer from the Licensor -- Adapted Material. |
||||
|
Every recipient of Adapted Material from You |
||||
|
automatically receives an offer from the Licensor to |
||||
|
exercise the Licensed Rights in the Adapted Material |
||||
|
under the conditions of the Adapter's License You apply. |
||||
|
|
||||
|
c. No downstream restrictions. You may not offer or impose |
||||
|
any additional or different terms or conditions on, or |
||||
|
apply any Effective Technological Measures to, the |
||||
|
Licensed Material if doing so restricts exercise of the |
||||
|
Licensed Rights by any recipient of the Licensed |
||||
|
Material. |
||||
|
|
||||
|
6. No endorsement. Nothing in this Public License constitutes or |
||||
|
may be construed as permission to assert or imply that You |
||||
|
are, or that Your use of the Licensed Material is, connected |
||||
|
with, or sponsored, endorsed, or granted official status by, |
||||
|
the Licensor or others designated to receive attribution as |
||||
|
provided in Section 3(a)(1)(A)(i). |
||||
|
|
||||
|
b. Other rights. |
||||
|
|
||||
|
1. Moral rights, such as the right of integrity, are not |
||||
|
licensed under this Public License, nor are publicity, |
||||
|
privacy, and/or other similar personality rights; however, to |
||||
|
the extent possible, the Licensor waives and/or agrees not to |
||||
|
assert any such rights held by the Licensor to the limited |
||||
|
extent necessary to allow You to exercise the Licensed |
||||
|
Rights, but not otherwise. |
||||
|
|
||||
|
2. Patent and trademark rights are not licensed under this |
||||
|
Public License. |
||||
|
|
||||
|
3. To the extent possible, the Licensor waives any right to |
||||
|
collect royalties from You for the exercise of the Licensed |
||||
|
Rights, whether directly or through a collecting society |
||||
|
under any voluntary or waivable statutory or compulsory |
||||
|
licensing scheme. In all other cases the Licensor expressly |
||||
|
reserves any right to collect such royalties, including when |
||||
|
the Licensed Material is used other than for NonCommercial |
||||
|
purposes. |
||||
|
|
||||
|
|
||||
|
Section 3 -- License Conditions. |
||||
|
|
||||
|
Your exercise of the Licensed Rights is expressly made subject to the |
||||
|
following conditions. |
||||
|
|
||||
|
a. Attribution. |
||||
|
|
||||
|
1. If You Share the Licensed Material (including in modified |
||||
|
form), You must: |
||||
|
|
||||
|
a. retain the following if it is supplied by the Licensor |
||||
|
with the Licensed Material: |
||||
|
|
||||
|
i. identification of the creator(s) of the Licensed |
||||
|
Material and any others designated to receive |
||||
|
attribution, in any reasonable manner requested by |
||||
|
the Licensor (including by pseudonym if |
||||
|
designated); |
||||
|
|
||||
|
ii. a copyright notice; |
||||
|
|
||||
|
iii. a notice that refers to this Public License; |
||||
|
|
||||
|
iv. a notice that refers to the disclaimer of |
||||
|
warranties; |
||||
|
|
||||
|
v. a URI or hyperlink to the Licensed Material to the |
||||
|
extent reasonably practicable; |
||||
|
|
||||
|
b. indicate if You modified the Licensed Material and |
||||
|
retain an indication of any previous modifications; and |
||||
|
|
||||
|
c. indicate the Licensed Material is licensed under this |
||||
|
Public License, and include the text of, or the URI or |
||||
|
hyperlink to, this Public License. |
||||
|
|
||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any |
||||
|
reasonable manner based on the medium, means, and context in |
||||
|
which You Share the Licensed Material. For example, it may be |
||||
|
reasonable to satisfy the conditions by providing a URI or |
||||
|
hyperlink to a resource that includes the required |
||||
|
information. |
||||
|
3. If requested by the Licensor, You must remove any of the |
||||
|
information required by Section 3(a)(1)(A) to the extent |
||||
|
reasonably practicable. |
||||
|
|
||||
|
b. ShareAlike. |
||||
|
|
||||
|
In addition to the conditions in Section 3(a), if You Share |
||||
|
Adapted Material You produce, the following conditions also apply. |
||||
|
|
||||
|
1. The Adapter's License You apply must be a Creative Commons |
||||
|
license with the same License Elements, this version or |
||||
|
later, or a BY-NC-SA Compatible License. |
||||
|
|
||||
|
2. You must include the text of, or the URI or hyperlink to, the |
||||
|
Adapter's License You apply. You may satisfy this condition |
||||
|
in any reasonable manner based on the medium, means, and |
||||
|
context in which You Share Adapted Material. |
||||
|
|
||||
|
3. You may not offer or impose any additional or different terms |
||||
|
or conditions on, or apply any Effective Technological |
||||
|
Measures to, Adapted Material that restrict exercise of the |
||||
|
rights granted under the Adapter's License You apply. |
||||
|
|
||||
|
|
||||
|
Section 4 -- Sui Generis Database Rights. |
||||
|
|
||||
|
Where the Licensed Rights include Sui Generis Database Rights that |
||||
|
apply to Your use of the Licensed Material: |
||||
|
|
||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right |
||||
|
to extract, reuse, reproduce, and Share all or a substantial |
||||
|
portion of the contents of the database for NonCommercial purposes |
||||
|
only; |
||||
|
|
||||
|
b. if You include all or a substantial portion of the database |
||||
|
contents in a database in which You have Sui Generis Database |
||||
|
Rights, then the database in which You have Sui Generis Database |
||||
|
Rights (but not its individual contents) is Adapted Material, |
||||
|
including for purposes of Section 3(b); and |
||||
|
|
||||
|
c. You must comply with the conditions in Section 3(a) if You Share |
||||
|
all or a substantial portion of the contents of the database. |
||||
|
|
||||
|
For the avoidance of doubt, this Section 4 supplements and does not |
||||
|
replace Your obligations under this Public License where the Licensed |
||||
|
Rights include other Copyright and Similar Rights. |
||||
|
|
||||
|
|
||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability. |
||||
|
|
||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE |
||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS |
||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF |
||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, |
||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, |
||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR |
||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, |
||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT |
||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT |
||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. |
||||
|
|
||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE |
||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, |
||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, |
||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, |
||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR |
||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN |
||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR |
||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR |
||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. |
||||
|
|
||||
|
c. The disclaimer of warranties and limitation of liability provided |
||||
|
above shall be interpreted in a manner that, to the extent |
||||
|
possible, most closely approximates an absolute disclaimer and |
||||
|
waiver of all liability. |
||||
|
|
||||
|
|
||||
|
Section 6 -- Term and Termination. |
||||
|
|
||||
|
a. This Public License applies for the term of the Copyright and |
||||
|
Similar Rights licensed here. However, if You fail to comply with |
||||
|
this Public License, then Your rights under this Public License |
||||
|
terminate automatically. |
||||
|
|
||||
|
b. Where Your right to use the Licensed Material has terminated under |
||||
|
Section 6(a), it reinstates: |
||||
|
|
||||
|
1. automatically as of the date the violation is cured, provided |
||||
|
it is cured within 30 days of Your discovery of the |
||||
|
violation; or |
||||
|
|
||||
|
2. upon express reinstatement by the Licensor. |
||||
|
|
||||
|
For the avoidance of doubt, this Section 6(b) does not affect any |
||||
|
right the Licensor may have to seek remedies for Your violations |
||||
|
of this Public License. |
||||
|
|
||||
|
c. For the avoidance of doubt, the Licensor may also offer the |
||||
|
Licensed Material under separate terms or conditions or stop |
||||
|
distributing the Licensed Material at any time; however, doing so |
||||
|
will not terminate this Public License. |
||||
|
|
||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public |
||||
|
License. |
||||
|
|
||||
|
|
||||
|
Section 7 -- Other Terms and Conditions. |
||||
|
|
||||
|
a. The Licensor shall not be bound by any additional or different |
||||
|
terms or conditions communicated by You unless expressly agreed. |
||||
|
|
||||
|
b. Any arrangements, understandings, or agreements regarding the |
||||
|
Licensed Material not stated herein are separate from and |
||||
|
independent of the terms and conditions of this Public License. |
||||
|
|
||||
|
|
||||
|
Section 8 -- Interpretation. |
||||
|
|
||||
|
a. For the avoidance of doubt, this Public License does not, and |
||||
|
shall not be interpreted to, reduce, limit, restrict, or impose |
||||
|
conditions on any use of the Licensed Material that could lawfully |
||||
|
be made without permission under this Public License. |
||||
|
|
||||
|
b. To the extent possible, if any provision of this Public License is |
||||
|
deemed unenforceable, it shall be automatically reformed to the |
||||
|
minimum extent necessary to make it enforceable. If the provision |
||||
|
cannot be reformed, it shall be severed from this Public License |
||||
|
without affecting the enforceability of the remaining terms and |
||||
|
conditions. |
||||
|
|
||||
|
c. No term or condition of this Public License will be waived and no |
||||
|
failure to comply consented to unless expressly agreed to by the |
||||
|
Licensor. |
||||
|
|
||||
|
d. Nothing in this Public License constitutes or may be interpreted |
||||
|
as a limitation upon, or waiver of, any privileges and immunities |
||||
|
that apply to the Licensor or You, including from the legal |
||||
|
processes of any jurisdiction or authority. |
||||
|
|
||||
|
======================================================================= |
||||
|
|
||||
|
Creative Commons is not a party to its public licenses. |
||||
|
Notwithstanding, Creative Commons may elect to apply one of its public |
||||
|
licenses to material it publishes and in those instances will be |
||||
|
considered the "Licensor." Except for the limited purpose of indicating |
||||
|
that material is shared under a Creative Commons public license or as |
||||
|
otherwise permitted by the Creative Commons policies published at |
||||
|
creativecommons.org/policies, Creative Commons does not authorize the |
||||
|
use of the trademark "Creative Commons" or any other trademark or logo |
||||
|
of Creative Commons without its prior written consent including, |
||||
|
without limitation, in connection with any unauthorized modifications |
||||
|
to any of its public licenses or any other arrangements, |
||||
|
understandings, or agreements concerning use of licensed material. For |
||||
|
the avoidance of doubt, this paragraph does not form part of the public |
||||
|
licenses. |
||||
|
|
||||
|
Creative Commons may be contacted at creativecommons.org. |
||||
|
|
||||
@ -0,0 +1,71 @@ |
|||||
|
|
||||
|
Android BluetoothLeGatt Sample |
||||
|
=================================== |
||||
|
|
||||
|
This sample demonstrates how to use the Bluetooth LE Generic Attribute Profile (GATT) |
||||
|
to transmit arbitrary data between devices. |
||||
|
|
||||
|
Introduction |
||||
|
------------ |
||||
|
|
||||
|
This sample shows a list of available Bluetooth LE devices and provides |
||||
|
an interface to connect, display data and display GATT services and |
||||
|
characteristics supported by the devices. |
||||
|
|
||||
|
It creates a [Service][1] for managing connection and data communication with a GATT server |
||||
|
hosted on a given Bluetooth LE device. |
||||
|
|
||||
|
The Activities communicate with the Service, which in turn interacts with the [Bluetooth LE API][2]. |
||||
|
|
||||
|
[1]:http://developer.android.com/reference/android/app/Service.html |
||||
|
[2]:https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html |
||||
|
|
||||
|
Pre-requisites |
||||
|
-------------- |
||||
|
|
||||
|
- Android SDK 25 |
||||
|
- Android Build Tools v25.0.2 |
||||
|
- Android Support Repository |
||||
|
|
||||
|
Screenshots |
||||
|
------------- |
||||
|
|
||||
|
<img src="screenshots/1-main.png" height="400" alt="Screenshot"/> <img src="screenshots/2-detail.png" height="400" alt="Screenshot"/> |
||||
|
|
||||
|
Getting Started |
||||
|
--------------- |
||||
|
|
||||
|
This sample uses the Gradle build system. To build this project, use the |
||||
|
"gradlew build" command or use "Import Project" in Android Studio. |
||||
|
|
||||
|
Support |
||||
|
------- |
||||
|
|
||||
|
- Google+ Community: https://plus.google.com/communities/105153134372062985968 |
||||
|
- Stack Overflow: http://stackoverflow.com/questions/tagged/android |
||||
|
|
||||
|
If you've found an error in this sample, please file an issue: |
||||
|
https://github.com/googlesamples/android-BluetoothLeGatt |
||||
|
|
||||
|
Patches are encouraged, and may be submitted by forking this project and |
||||
|
submitting a pull request through GitHub. Please see CONTRIBUTING.md for more details. |
||||
|
|
||||
|
License |
||||
|
------- |
||||
|
|
||||
|
Copyright 2016 The Android Open Source Project, Inc. |
||||
|
|
||||
|
Licensed to the Apache Software Foundation (ASF) under one or more contributor |
||||
|
license agreements. See the NOTICE file distributed with this work for |
||||
|
additional information regarding copyright ownership. The ASF licenses this |
||||
|
file to you 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. |
||||
@ -0,0 +1,10 @@ |
|||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
@ -0,0 +1,6 @@ |
|||||
|
#Wed May 10 11:57:35 CEST 2017 |
||||
|
distributionBase=GRADLE_USER_HOME |
||||
|
distributionPath=wrapper/dists |
||||
|
zipStoreBase=GRADLE_USER_HOME |
||||
|
zipStorePath=wrapper/dists |
||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip |
||||
@ -0,0 +1,164 @@ |
|||||
|
#!/usr/bin/env bash |
||||
|
|
||||
|
############################################################################## |
||||
|
## |
||||
|
## Gradle start up script for UN*X |
||||
|
## |
||||
|
############################################################################## |
||||
|
|
||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||
|
DEFAULT_JVM_OPTS="" |
||||
|
|
||||
|
APP_NAME="Gradle" |
||||
|
APP_BASE_NAME=`basename "$0"` |
||||
|
|
||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value. |
||||
|
MAX_FD="maximum" |
||||
|
|
||||
|
warn ( ) { |
||||
|
echo "$*" |
||||
|
} |
||||
|
|
||||
|
die ( ) { |
||||
|
echo |
||||
|
echo "$*" |
||||
|
echo |
||||
|
exit 1 |
||||
|
} |
||||
|
|
||||
|
# OS specific support (must be 'true' or 'false'). |
||||
|
cygwin=false |
||||
|
msys=false |
||||
|
darwin=false |
||||
|
case "`uname`" in |
||||
|
CYGWIN* ) |
||||
|
cygwin=true |
||||
|
;; |
||||
|
Darwin* ) |
||||
|
darwin=true |
||||
|
;; |
||||
|
MINGW* ) |
||||
|
msys=true |
||||
|
;; |
||||
|
esac |
||||
|
|
||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched. |
||||
|
if $cygwin ; then |
||||
|
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` |
||||
|
fi |
||||
|
|
||||
|
# Attempt to set APP_HOME |
||||
|
# Resolve links: $0 may be a link |
||||
|
PRG="$0" |
||||
|
# Need this for relative symlinks. |
||||
|
while [ -h "$PRG" ] ; do |
||||
|
ls=`ls -ld "$PRG"` |
||||
|
link=`expr "$ls" : '.*-> \(.*\)$'` |
||||
|
if expr "$link" : '/.*' > /dev/null; then |
||||
|
PRG="$link" |
||||
|
else |
||||
|
PRG=`dirname "$PRG"`"/$link" |
||||
|
fi |
||||
|
done |
||||
|
SAVED="`pwd`" |
||||
|
cd "`dirname \"$PRG\"`/" >&- |
||||
|
APP_HOME="`pwd -P`" |
||||
|
cd "$SAVED" >&- |
||||
|
|
||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar |
||||
|
|
||||
|
# Determine the Java command to use to start the JVM. |
||||
|
if [ -n "$JAVA_HOME" ] ; then |
||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
||||
|
# IBM's JDK on AIX uses strange locations for the executables |
||||
|
JAVACMD="$JAVA_HOME/jre/sh/java" |
||||
|
else |
||||
|
JAVACMD="$JAVA_HOME/bin/java" |
||||
|
fi |
||||
|
if [ ! -x "$JAVACMD" ] ; then |
||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME |
||||
|
|
||||
|
Please set the JAVA_HOME variable in your environment to match the |
||||
|
location of your Java installation." |
||||
|
fi |
||||
|
else |
||||
|
JAVACMD="java" |
||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||
|
|
||||
|
Please set the JAVA_HOME variable in your environment to match the |
||||
|
location of your Java installation." |
||||
|
fi |
||||
|
|
||||
|
# Increase the maximum file descriptors if we can. |
||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then |
||||
|
MAX_FD_LIMIT=`ulimit -H -n` |
||||
|
if [ $? -eq 0 ] ; then |
||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then |
||||
|
MAX_FD="$MAX_FD_LIMIT" |
||||
|
fi |
||||
|
ulimit -n $MAX_FD |
||||
|
if [ $? -ne 0 ] ; then |
||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD" |
||||
|
fi |
||||
|
else |
||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
# For Darwin, add options to specify how the application appears in the dock |
||||
|
if $darwin; then |
||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" |
||||
|
fi |
||||
|
|
||||
|
# For Cygwin, switch paths to Windows format before running java |
||||
|
if $cygwin ; then |
||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"` |
||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` |
||||
|
|
||||
|
# We build the pattern for arguments to be converted via cygpath |
||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` |
||||
|
SEP="" |
||||
|
for dir in $ROOTDIRSRAW ; do |
||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir" |
||||
|
SEP="|" |
||||
|
done |
||||
|
OURCYGPATTERN="(^($ROOTDIRS))" |
||||
|
# Add a user-defined pattern to the cygpath arguments |
||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then |
||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" |
||||
|
fi |
||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh |
||||
|
i=0 |
||||
|
for arg in "$@" ; do |
||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` |
||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option |
||||
|
|
||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition |
||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` |
||||
|
else |
||||
|
eval `echo args$i`="\"$arg\"" |
||||
|
fi |
||||
|
i=$((i+1)) |
||||
|
done |
||||
|
case $i in |
||||
|
(0) set -- ;; |
||||
|
(1) set -- "$args0" ;; |
||||
|
(2) set -- "$args0" "$args1" ;; |
||||
|
(3) set -- "$args0" "$args1" "$args2" ;; |
||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; |
||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; |
||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; |
||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; |
||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; |
||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; |
||||
|
esac |
||||
|
fi |
||||
|
|
||||
|
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules |
||||
|
function splitJvmOpts() { |
||||
|
JVM_OPTS=("$@") |
||||
|
} |
||||
|
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS |
||||
|
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" |
||||
|
|
||||
|
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" |
||||
@ -0,0 +1,90 @@ |
|||||
|
@if "%DEBUG%" == "" @echo off |
||||
|
@rem ########################################################################## |
||||
|
@rem |
||||
|
@rem Gradle startup script for Windows |
||||
|
@rem |
||||
|
@rem ########################################################################## |
||||
|
|
||||
|
@rem Set local scope for the variables with windows NT shell |
||||
|
if "%OS%"=="Windows_NT" setlocal |
||||
|
|
||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||
|
set DEFAULT_JVM_OPTS= |
||||
|
|
||||
|
set DIRNAME=%~dp0 |
||||
|
if "%DIRNAME%" == "" set DIRNAME=. |
||||
|
set APP_BASE_NAME=%~n0 |
||||
|
set APP_HOME=%DIRNAME% |
||||
|
|
||||
|
@rem Find java.exe |
||||
|
if defined JAVA_HOME goto findJavaFromJavaHome |
||||
|
|
||||
|
set JAVA_EXE=java.exe |
||||
|
%JAVA_EXE% -version >NUL 2>&1 |
||||
|
if "%ERRORLEVEL%" == "0" goto init |
||||
|
|
||||
|
echo. |
||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||
|
echo. |
||||
|
echo Please set the JAVA_HOME variable in your environment to match the |
||||
|
echo location of your Java installation. |
||||
|
|
||||
|
goto fail |
||||
|
|
||||
|
:findJavaFromJavaHome |
||||
|
set JAVA_HOME=%JAVA_HOME:"=% |
||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe |
||||
|
|
||||
|
if exist "%JAVA_EXE%" goto init |
||||
|
|
||||
|
echo. |
||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% |
||||
|
echo. |
||||
|
echo Please set the JAVA_HOME variable in your environment to match the |
||||
|
echo location of your Java installation. |
||||
|
|
||||
|
goto fail |
||||
|
|
||||
|
:init |
||||
|
@rem Get command-line arguments, handling Windowz variants |
||||
|
|
||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args |
||||
|
if "%@eval[2+2]" == "4" goto 4NT_args |
||||
|
|
||||
|
:win9xME_args |
||||
|
@rem Slurp the command line arguments. |
||||
|
set CMD_LINE_ARGS= |
||||
|
set _SKIP=2 |
||||
|
|
||||
|
:win9xME_args_slurp |
||||
|
if "x%~1" == "x" goto execute |
||||
|
|
||||
|
set CMD_LINE_ARGS=%* |
||||
|
goto execute |
||||
|
|
||||
|
:4NT_args |
||||
|
@rem Get arguments from the 4NT Shell from JP Software |
||||
|
set CMD_LINE_ARGS=%$ |
||||
|
|
||||
|
:execute |
||||
|
@rem Setup the command line |
||||
|
|
||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |
||||
|
|
||||
|
@rem Execute Gradle |
||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% |
||||
|
|
||||
|
:end |
||||
|
@rem End local scope for the variables with windows NT shell |
||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd |
||||
|
|
||||
|
:fail |
||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |
||||
|
rem the _cmd.exe /c_ return code! |
||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 |
||||
|
exit /b 1 |
||||
|
|
||||
|
:mainEnd |
||||
|
if "%OS%"=="Windows_NT" endlocal |
||||
|
|
||||
|
:omega |
||||
@ -0,0 +1,15 @@ |
|||||
|
# GOOGLE SAMPLE PACKAGING DATA |
||||
|
# |
||||
|
# This file is used by Google as part of our samples packaging process. |
||||
|
# End users may safely ignore this file. It has no relevance to other systems. |
||||
|
--- |
||||
|
|
||||
|
status: PUBLISHED |
||||
|
technologies: [Android] |
||||
|
categories: [Connectivity] |
||||
|
languages: [Java] |
||||
|
solutions: [Mobile] |
||||
|
github: googlesamples/android-BluetoothLeGatt |
||||
|
level: BEGINNER |
||||
|
icon: BluetoothLeGattSample/src/main/res/drawable-xxhdpi/ic_launcher.png |
||||
|
license: apache2-android |
||||
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 69 KiB |
@ -0,0 +1 @@ |
|||||
|
include 'Application' |
||||