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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-15 18:13:09

Android之BLE编程的相关文章

BLE简介和Android BLE编程

一.BLE和BT区别 其实我知道许多程序员不太喜欢阅读除了代码以外的文档,因为有时这些过于冗长的文档对编程并没有更多的好处,有了协议,接口,demo差不多很多人就能写出很好质量的代码了.但其实更深入的编程是少了阅读的,阅读文档可以解决很多编程中遇到的困难,比如在大数据大流量情况下,很多正常的程序会表现出不可靠的一面,这已经不是够编程能解决的了,硬件的配置,服务器带宽,使用的数据库,调用的接口都有可能是瓶颈.比如BLE,同样的蓝牙,但却有着本质区别,一个表现就是不是所有蓝牙设备都支持BLE,编程如

Android中多线程编程(四)AsyncTask类的详细解释(附源码)

Android中多线程编程中AsyncTask类的详细解释 1.Android单线程模型 2.耗时操作放在非主线程中执行 Android主线程和子线程之间的通信封装类:AsyncTask类 1.子线程中更新UI 2.封装.简化异步操作. 3.AsyncTask机制:底层是通过线程池来工作的,当一个线程没有执行完毕,后边的线程是无法执行的.必须等前边的线程执行完毕后,后边的线程才能执行. AsyncTask类使用注意事项: 1.在UI线程中创建AsyncTask的实例 2.必须在UI线程中调用As

Android 的网络编程

android的网络编程分为2种:基于socket的,和基于http协议的. 基于socket的用法 服务器端: 先启动一个服务器端的socket     ServerSocket svr = new ServerSocket(8989); 开始侦听请求 Socket s = svr.accept(); 取得输入和输出 DataInputStream dis = new DataInputStream(s.getInputStream()); DataOutputStream dos = new

Android开发经典书籍下载——《Android 4高级编程》《疯狂Android讲义》《Android应用开发详解(郭宏志)》《Android应用案例开发大全》《Android 3D游戏开发技术》

这是我收集的关于android开发方面的经典书籍,高清PDF电子版,可以在我的百度网盘免费下载,希望对需要的朋友有帮助. 目录: <Android 4高级编程>(附完整源代码) <疯狂Android讲义> <Android应用开发详解(郭宏志)> <Android应用案例开发大全> <Android 3D游戏开发技术> <Android内核剖析 柯元旦> <深入理解Android  卷1> <深入理解Android

超全Android JNI&NDK编程总结

由于网上关于JNI/NDK相关的知识点介绍的比较零散而且不具备参照性,所以写了这篇JNI/NDK学习笔记,便于作为随时查阅的工具类型的文章,本文主要的介绍了在平时项目中常用的命令.JNI数据类型.签名等,便于查阅相关资料.文末相关参考资料比较适合刚接触或者不熟悉Android NDK开发的朋友参阅. 常用命令 javac 编译java源文件生成.class文件 由于JNI对应的头文件由javah工具根据对应的.class文件生成,所以在进行JNI编程之前,写好Java代码后需要先编译,在使用ja

Android平台BLE应用程序开发指南

从Android 4.3开始,BLE(Bluetooth Low Energy)在Android平台上被支持了.但是目前Android上BLE应用程序稀少,尤其是中文应用程序,希望本文对有兴趣开发BLE应用程序的开发者有所帮助.本文主要是对目前已有的Andriod BLE开发相关资料进行整理,给出一个开发资料的索引.(本文会根据大家的问题,不断完善) 基本参考资料 最基本的学习资料是这篇Android官方文档:<Bluetooth Low Energy>.该文档对BLE涉及的基本概念进行了介绍

android 命令行编程

如果你想了解android上开发一个应用程序所需要的所有环节,在命令行上将这个过程操作一遍是最好的方法,下面你可以扔掉哪个慢腾腾的eclipse,然后建立如下一个auto.cmd文件,运行一下auto.cmd,你的电脑d:\work\njh1文件夹下就会产生一个SNjh.apk文件,该文件会自动安装到你手机上,并自动运行,这需要13个步骤,当然所用的环境为JDK1.7,ADT22.3,SDK API-17,d:盘建立文件夹work,当这些环境配好后就可以正常工作了,并且在系统环境中的path变量

android L BLE Central(Scanner)牛刀小试

转载请表明作者:http://blog.csdn.net/lansefeiyang08/article/details/46482073 昨天写了android L BLE Peripheral的简单使用,今天讲一下BLE Central的更新. 搞过android4.4的人肯定对BluetoothAdapter的startLeScan函数不会陌生,但是在android L已经弃用此接口,但是为了兼容以前的版本,这个接口还是可以使用的.但是谷歌已经单独拿出来android.bluetooth.l

Android C++高级编程

简介 <Android C++高级编程--使用NDK>提供了Java原生接口(JNI)的概述.Bionic API.POSIX 线程和套接字.C++支持.原生图形和声音API以及NEON/SIMD优化.   本文将记录主要知识点. 详解 1.深入了解Android NDK Android NDK不是一个独有的工具:它是一个包含API.交叉编译器.链接程序.调试器.构建工具.文档和实例应用程序的综合工具集.组件如下:ARM.x86和MIPS交叉编译器构建系统JAVA原生接口头文件C库Math库P