Android之BLE编程

写在前面:
作为一个程序员,各种苦逼啊,作为一个Android程序员,苦逼死了。
Android手机可以使用WIFI、蓝牙和数据网络进行网络通信,那作为Android程序员,就必须得会这些了。如果不会,都不好意思给别人说你是21世纪的屌丝程序员。
通过WIFI和数据网络通信的Socket编程(基于IP的TCP、UDP、HTTP通信 )相信大家都是驾轻就熟了。而现阶段,随着物联网的发展和蓝牙的BLE低功耗方案的成熟,BLE设备应用越来越广泛,尤其是智能穿戴设备。
那么BLE编程是和怎么回事呢?到底难不难呢?网上已经很多关于BLE的文章了,有些写的很好,有些真的没有什么毛用,完全是官方的Demo。
由于项目需要,最近一直在研究BLE编程,现在做好了,就做一下总结,与大家分享,能力有限,大牛莫笑!


一、什么是BLE
蓝牙低能耗(BLE)技术是低成本、短距离、可互操作的鲁棒性无线技术,工作在免许可的2.4GHz ISM射频频段。它从一开始就设计为超低功耗(ULP)无线技术。它利用许多智能手段最大限度地降低功耗。蓝牙低能耗技术采用可变连接时间间隔,这个间隔根据具体应用可以设置为几毫秒到几秒不等。另外,因为BLE技术采用非常快速的连接方式,因此平时可以处于“非连接”状态(节省能源),此时链路两端相互间只是知晓对方,只有在必要时才开启链路,然后在尽可能短的时间内关闭链路。
其实就是蓝牙的一种新技术而已,特点就是低功耗,连接速度快,但是只能传输小数据。


二、一些关于BLE的概念
Generic Attribute Profile (GATT)
通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。
 
Attribute Protocol (ATT)
GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。


Characteristic
Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。


Descriptor
对Characteristic的描述,例如范围、计量单位等。


Service
Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement"的Characteristic。


请记住:一个BLE设备可以有多个Service,一个Service可以有多个Chracteristic,一个Chracteristic有一个Value和多个Descriptor,一个Descriptor包含一个Value。


三、关于BLE的一个API
BluetoothGatt
继承BluetoothProfile,通过BluetoothGatt可以连接设备(connect),发现服务(discoverServices),并把相应地属性返回到BluetoothGattCallback 
 
BluetoothGattCharacteristic
相当于一个数据类型,它包括一个value和0~n个value的描述(BluetoothGattDescriptor)
 
BluetoothGattDescriptor
描述符,对Characteristic的描述,包括范围、计量单位等
 
BluetoothGattService
服务,Characteristic的集合。
 
BluetoothProfile
 一个通用的规范,按照这个规范来收发数据。
 
BluetoothManager
通过BluetoothManager来获取BluetoothAdapter
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);


BluetoothAdapter
一个Android系统只有一个BluetoothAdapter ,通过BluetoothManager 获取
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();


BluetoothGattCallback
private BluetoothGattCallback GattCallback = new BluetoothGattCallback() {
    // 这里有9个要实现的方法,看情况要实现那些,用到那些就实现那些
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState){};
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){};
};


BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
BluetoothGatt gatt = device.connectGatt(this, false, mGattCallback);


:notification对应onCharacteristicChanged;
 
gatt.setCharacteristicNotification(characteristic, true);
:readCharacteristic对应onCharacteristicRead;
 
gatt.readCharacteristic(characteristic);
: writeCharacteristic对应onCharacteristicWrite;
 
gatt.wirteCharacteristic(mCurrentcharacteristic);
:连接蓝牙或者断开蓝牙 对应 onConnectionStateChange;
 
:readDescriptor对应onDescriptorRead;
 
:writeDescriptor对应onDescriptorWrite;
 
gatt.writeDescriptor(descriptor);
:readRemoteRssi对应onReadRemoteRssi;
 
gatt.readRemoteRssi()
:executeReliableWrite对应onReliableWriteCompleted;
 
:discoverServices对应onServicesDiscovered。
 
gatt.discoverServices()
BluetoothDevice


四、开始上代码
代码主要实现功能:首先进入BLEActivity,然后即可扫描BLE设备,选择你想要连接的BLE设备,点击,程序会开启BLEService,BLEService将开始与设备建立GATT连接,并根据UUID或取相应的Service和相应的Chracteristic然后就可以进行数据读写了。
本程序,我留出了三个接口函数(均在BLEService中)
一个是self(),用于获得BLEService的实例
一个是writeToBle(byte[]),可以通过此方法接口向BLE设备写数据
一个是readFromBle(),通过此函数从BLE设备读取数据


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.study.blestudy"
    android:versionCode="1"
    android:versionName="1.0" >


    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />


    <!-- 添加蓝牙权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- 添加BLE特征 -->
    <uses-feature
        android:name="android.hardware.bluetooth_le"
        android:required="false" />


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".BLEActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- BLE服务 -->
        <service android:name=".BLEService" />
    </application>


</manifest>


BLEActivity.java

package com.study.blestudy;


import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;


@SuppressLint("NewApi")
public class BLEActivity extends Activity {
private static Context mContext;// 上下文
private static final String TAG = BLEActivity.class.getSimpleName();// 标志


private SharedPreferences sp = null;


private BluetoothAdapter mBluetoothAdapter = null;// 本地蓝牙设备


private Handler mHandler = null;// 用于postDelay
private boolean mScanning = false;// 循环标志位


private static final long SCAN_PERIOD = 10000;// 扫描10s
private static final int REQUEST_ENABLE_BT = 1;// 请求码


private ListView mListView = null;
private BLEAdapter mAdapter = null;


@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ble);
if (!checkBluetooth()) {
finish();
}
init();
}


@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
// 为了确保设备上蓝牙能使用, 如果当前蓝牙设备没启用,弹出对话框向用户要求授予权限来启用
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
mAdapter = new BLEAdapter(mContext);
mListView.setAdapter(mAdapter);
if (mBluetoothAdapter.isEnabled()) {
scanLeDevice(true);
}
}


@Override
protected void onPause() {
super.onPause();
scanLeDevice(false);
mAdapter.clear();
}


@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
suiside();
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
if (requestCode == REQUEST_ENABLE_BT
&& resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}


@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:
mAdapter.clear();
scanLeDevice(true);
break;
case R.id.menu_stop:
scanLeDevice(false);
break;
}
return true;
}


/**
* 判断是否支持蓝牙和BLE

* @return
*/
private boolean checkBluetooth() {
// 判断是否支持BLE
if (!getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE)) {
toast("ble not supported");
return false;
}


// 初始化BluetoothAdapter
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();


// 检查设备上是否支持蓝牙不支 持就退出程序
if (mBluetoothAdapter == null) {
toast("bluetooth not supported");
return false;
}


return true;
}


/**
* 初始化数据
*/
private void init() {
mContext = this;
mHandler = new Handler();
sp = getSharedPreferences(Constant.SP_NAME, Context.MODE_PRIVATE);
mListView = (ListView) findViewById(R.id.lv_device_ble);
mListView.setOnItemClickListener(mItemClickListener);
}


/**
* 列表单击事件
*/
private OnItemClickListener mItemClickListener = new OnItemClickListener() {


@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
// TODO Auto-generated method stub
/**
* 跳转到BLEService 传递一个参数 一个地址 并把名字和地址保存起来
*/
BluetoothDevice mDevice = mAdapter.getDevice(position);
toast(mDevice.getAddress());
saveDeviceAddress(mDevice.getAddress());
startTheService();
finish();
}
};


/**
* 启动BLE通信服务
*/
private void startTheService() {
Intent service = new Intent();
service.setClass(mContext, BLEService.class);
startService(service);
}


/**
* 把地址保存起来 以便服务可以使用

* @param address
*/
private void saveDeviceAddress(String address) {
Editor editor = sp.edit();
editor.putString(Constant.KEY_DEVICE_ADDRESS, address);
editor.commit();
}


/**
* 吐丝

* @param text
*/
private void toast(String text) {
Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
}


/**
* 扫描BLE设备

* @param enable
*/
private void scanLeDevice(final boolean enable) {
if (enable) {
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();
}


/**
* BLE扫描回调函数,设备保存在remoteDevice里面
*/
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {


@Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.addDevice(device);
mAdapter.notifyDataSetChanged();
}
});
}
};


/**
* 自杀
*/
private void suiside() {
scanLeDevice(false);
sp = null;
}
}


BLEAdapter.java
package com.study.blestudy;


import java.util.ArrayList;


import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;


/**
 * @date 2015-07-22
 * @detail 设备列表适配器
 * @author Leo
 * 
 */
@SuppressLint("InflateParams")
public class BLEAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflater;


public BLEAdapter(Context context) {
mLeDevices = new ArrayList<BluetoothDevice>();
mInflater = LayoutInflater.from(context);
}


@Override
public int getCount() {
// TODO Auto-generated method stub
return mLeDevices.size();
}


@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
if (mLeDevices.size() <= arg0) {
return null;
}
return mLeDevices.get(arg0);
}


@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}


@Override
public View getView(int position, View view, ViewGroup arg2) {
// TODO Auto-generated method stub
ViewHolder viewHolder;


if (null == view) {
viewHolder = new ViewHolder();


view = mInflater.inflate(R.layout.item_ble, null);
viewHolder.deviceName = (TextView) view
.findViewById(R.id.device_name);


view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}


BluetoothDevice device = mLeDevices.get(position);


final String deviceName = device.getName();
if (deviceName != null && deviceName.length() > 0)
viewHolder.deviceName.setText(deviceName);
else
viewHolder.deviceName.setText("unknown name");


return view;
}


/**
* 列表显示控件类

* @author Leo

*/
private class ViewHolder {
public TextView deviceName;
}


/**
* 设置数据源

* @param mDevices
*/
public void setData(ArrayList<BluetoothDevice> mDevices) {
this.mLeDevices = mDevices;
}


/**
* 添加设备

* @param mDevice
*/
public void addDevice(BluetoothDevice mDevice) {
if (!mLeDevices.contains(mDevice)) {
mLeDevices.add(mDevice);
}
}


/**
* 得到设备

* @param position
* @return
*/
public BluetoothDevice getDevice(int position) {
if (mLeDevices.size() <= position) {
return null;
}
return mLeDevices.get(position);
}


/**
* 清空设备
*/
public void clear() {
mLeDevices.clear();
}


}


BLEService.java
package com.study.blestudy;


import java.util.List;


import android.annotation.SuppressLint;
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.content.SharedPreferences;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;


/**
 * @date 2015-07-22
 * @detail BLE连接通信
 * @author Leo
 * 
 */
@SuppressLint("NewApi")
public class BLEService extends Service {
private static byte[] testData = { 1, 2, 3 };


private static Context mContext;// 上下文
private static final String TAG = BLEService.class.getSimpleName();// TAG


private BluetoothManager mBluetoothManager = null;// 蓝牙管理器
private BluetoothAdapter mBluetoothAdapter = null;// 本地设备
private String mBluetoothDeviceAddress = null;// 远程设备地址
private BluetoothGatt mBluetoothGatt = null;// GATT通信
private BluetoothGattCharacteristic mCharacteristic = null;// 可读写可通知的


private SharedPreferences sp = null;


private static final boolean AUTO_CONNECT = true;// 是否自动连接
private static final boolean NOTIFICATION_ENABLED = true;


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;// 已连接


@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}


@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
init();
}


@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
suiside();
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
// 如果地址不为空就尝试连接 如果为空就跳到BLEActivity让用户去选择BLE设备
if (mBluetoothDeviceAddress != null) {
if (connect(mBluetoothDeviceAddress)) {
} else {
}
} else {
Intent bleIntent = new Intent();
bleIntent.setClass(mContext, BLEActivity.class);
bleIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(bleIntent);
}
// return super.onStartCommand(intent, flags, startId);
return Service.START_STICKY;
}


/**
* 各种初始化信息
*/
private void init() {
mContext = this;
if (!initBluetooth()) {
stopSelf();
}
sp = getSharedPreferences(Constant.SP_NAME, Context.MODE_PRIVATE);
mBluetoothDeviceAddress = sp.getString(Constant.KEY_DEVICE_ADDRESS,
null);
}


/**
* 吐丝
*/
private void toast(String text) {
Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
}


/**
* 初始化BluetoothManager和BluetoothAdapter

* @return
*/
private boolean initBluetooth() {
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
return false;
}
}


mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
return false;
}


return true;
}


/**
* 自殺
*/
private void suiside() {
disconnect();
close();
try {
if (mBluetoothAdapter != null) {
mBluetoothAdapter.disable();
mBluetoothAdapter = null;
mBluetoothManager = null;
sp = null;
}
} catch (Exception e) {
toast("关闭蓝牙失败,请手动关闭");
}
}


/**
* 关闭通信
*/
private void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
}


/**
* 建立通信連接

* @param address
* @return
*/
private boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
return false;
}


if (mBluetoothDeviceAddress != null
&& address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}


final BluetoothDevice device = mBluetoothAdapter
.getRemoteDevice(address);
if (device == null) {
return false;
}
mBluetoothGatt = device.connectGatt(this, AUTO_CONNECT, mGattCallback);
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}


/**
* 斷開GATT連接
*/
private void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
return;
}
mBluetoothGatt.disconnect();
}


/**
* GATT通信回調函數
*/
@SuppressLint("NewApi")
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {


@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
// TODO Auto-generated method stub
// super.onCharacteristicChanged(gatt, characteristic);
System.out.println("我收到的:" + new String(characteristic.getValue()));
}


@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
// TODO Auto-generated method stub
super.onCharacteristicRead(gatt, characteristic, status);
}


@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
// TODO Auto-generated method stub
super.onCharacteristicWrite(gatt, characteristic, status);
}


@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
// TODO Auto-generated method stub
// super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
if (mBluetoothGatt != null)
mBluetoothGatt.discoverServices();
mConnectionState = STATE_CONNECTED;
System.out.println("state connected");
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
// connect(mBluetoothDeviceAddress);
mConnectionState = STATE_DISCONNECTED;
System.out.println("state disconnected");
}
}


@Override
public void onDescriptorRead(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor, int status) {
// TODO Auto-generated method stub
super.onDescriptorRead(gatt, descriptor, status);
}


@Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor, int status) {
// TODO Auto-generated method stub
super.onDescriptorWrite(gatt, descriptor, status);
}


@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
// TODO Auto-generated method stub
super.onReadRemoteRssi(gatt, rssi, status);
}


@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
// TODO Auto-generated method stub
super.onReliableWriteCompleted(gatt, status);
}


@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// TODO Auto-generated method stub
// super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
if (mBluetoothGatt != null) {
BluetoothGattService mGattService = mBluetoothGatt
.getService(SampleGattAttributes.UUID_SERVICE);
mCharacteristic = mGattService
.getCharacteristic(SampleGattAttributes.UUID_CHARACTERISTIC);
List<BluetoothGattDescriptor> mDescriptors = mCharacteristic
.getDescriptors();
for (BluetoothGattDescriptor mDescriptor : mDescriptors) {
System.out.println(mDescriptor.getUuid().toString());
}


setCharacteristicNotification(mCharacteristic,
NOTIFICATION_ENABLED);


wirteToBLE(testData);
System.out.println(new String(readFromBLE()));
wirteToBLE(testData);
System.out.println(new String(readFromBLE()));
}
}
}


};


/**
* 设置后可以使用通知 设备给手机发送通知时可触发onCharacteristicChanged()

* @param characteristic
* @param enabled
*/


private void setCharacteristicNotification(
BluetoothGattCharacteristic characteristic, boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(SampleGattAttributes.UUID_DESCRIPTOR);
if (descriptor != null) {
descriptor
.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}


/**
* 获取此实例

* @return
*/
public static BLEService self() {
if (mContext != null)
return (BLEService) mContext;
return null;
}


/**
* 通信接口 通过此函数即可向BLE设备写入数据

* @param value
* @return
*/
public boolean wirteToBLE(byte[] value) {


if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return false;
}


mCharacteristic.setValue(value);
boolean isSuccess = mBluetoothGatt.writeCharacteristic(mCharacteristic);
return isSuccess;
}


/**
* 通信接口 从BLE设备读数据

* @return
*/
public byte[] readFromBLE() {
byte[] value = null;


if (mBluetoothAdapter == null || mBluetoothGatt == null) {
return null;
}


boolean isSuccess = mBluetoothGatt.readCharacteristic(mCharacteristic);
if (isSuccess) {
value = mCharacteristic.getValue();
}


return value;
}
}


五、小结
BLE编程,最重要的不是代码,而是理解其工作模式和编程步骤。工作模式呢,其实就是中心设备和外围设备,其次就是他的GATT/ATT通信。
编程步骤呢:
步骤:
1、开始准备(包括:添加权限,判断支持,打开蓝牙)
2、扫描设备(扫描BLE设备)
3、建立连接(能过地址,并建立GATT连接)
4、列举服务(列举BLE设备开启了哪些服务,并找出相关特征)
5、开始通信(读写数据,通知等)
6、关闭连接


可参考:
http://blog.csdn.net/zhaicaixiansheng/article/details/46858967
http://blog.csdn.net/zhaicaixiansheng/article/details/42242369
http://blog.csdn.net/zhaicaixiansheng/article/details/41723615













  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬李先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值