Android和BLE模块连接通信
首先,进行一下科普:
1.BLE(Bluetooth Low Energy),蓝牙4.0核心profile,主要特点是快速搜索,快速连接,超低功耗保持连接和数据传输,缺点:数据传输速率低,由于其具有低功耗特点,故而经常用在可穿戴设备之中。Android4.3才开始支持BLE api。
2.关于BLE数据传输:
a.profile可以理解为一种规范,一个标准的通信协议,其存在于手机中,蓝牙组织规定了一些标准的profile:HID OVER GATT ,防丢器等,每个profile中包含了多个service。
b.service 可以理解为一个服务,在BLE从机中有多个服务,电量信息,系统服务信息等,每一个service中包含了多个characteristic特征值,每一个具体的characteristic特征值才是BLE通信的主题。
举个例子吧:从机当前的电量是80%,从机会借由电量的characteristic特征值将这个信息储存于从机的profile中,主机可以通过该characteristic来读取80%这个数据。
c.characteristic特征值:BLE主机从机通信均是通过characteristic进行,可以将其理解为一个标签,通过该标签可以读取或写入相关信息。
d. UUID(统一标识码):service和characteristic均需要这个唯一的UUID进行标识
/****************************************************************************************/
科普结束,首先上效果图:
这个就是实现后的效果,我用的BLE模块是:MicrodunioBT4.0
/*********************************************************分隔符********************************************************************************/
BLE设备和Android应用进行通信,首先要做的就是让Android应用找到BLE设备(代码分析部分,只对关键点进行注释)
package com.TANK.temperature.BT; import java.util.List; import com.TANK.temperature.R;
import com.TANK.temperature.BT.BluetoothLeClass.OnDataAvailableListener;
import com.TANK.temperature.BT.BluetoothLeClass.OnServiceDiscoverListener; import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.net.wifi.WifiConfiguration.Status;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast; public class DeviceScanActivity extends Activity {
private final static String TAG = DeviceScanActivity.class.getSimpleName();
private final static String UUID_KEY_DATA = "0000fff6-0000-1000-8000-00805f9b34fb";
private Handler mHandler;
private static final long SCAN_PERIOD = 10000; /** 搜索BLE终端 */
private BluetoothAdapter mBluetoothAdapter;
private BluetoothLeClass mBLE;
private boolean mScanning;
private BluetoothDevice BTtoLink = null;
private String BTtoFind = "Microduino"; private TextView BT_find, BT_info, BT_link;//三个textview分别表示:设备是否找到,BLE模块传输的信息,连接状态
private String S_BT_info = "null", info = "111"; @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState); setContentView(R.layout.temperature);
mHandler = new Handler(); BT_find = (TextView) findViewById(R.id.BT_find);
BT_info = (TextView) findViewById(R.id.BT_info);
BT_link = (TextView) findViewById(R.id.BT_link);
Typeface typeface = Typeface.createFromAsset(getAssets(),
"fonts/maozedong.ttf");//设置显示字体
BT_find.setTypeface(typeface);
BT_info.setTypeface(typeface);
BT_link.setTypeface(typeface); BT_find.setText("查找中");
BT_info.setText("null");
BT_link.setText("未连接"); if (!getPackageManager().hasSystemFeature( //判断主机是否支BLE牙设备
PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, "BLE is not supported", Toast.LENGTH_SHORT)
.show();
finish(); }
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);//获得Android设备中的bluetoothmanager
mBluetoothAdapter = bluetoothManager.getAdapter();//获得bluetoothadapter
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth not supported", Toast.LENGTH_SHORT)
.show();
finish();
return;
}
mBluetoothAdapter.enable(); //强制使能Bluetoothadapter,打开Android设备蓝牙
mBLE = new BluetoothLeClass(this); //BLuetoothLeClass类
if (!mBLE.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish(); } // 发现BLE终端的Service时回调
mBLE.setOnServiceDiscoverListener(mOnServiceDiscover); // 收到BLE终端数据交互的事件
mBLE.setOnDataAvailableListener(mOnDataAvailable); } @Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
scanLeDevice(true);//搜索BLE设备
} @Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
scanLeDevice(false);
mBLE.disconnect();
} @Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
mBLE.close();
} private void scanLeDevice(final boolean enable) {
// TODO Auto-generated method stub
if (enable) { mHandler.postDelayed(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback); }
}, SCAN_PERIOD);//在搜索时间内,关闭搜索标志,不对搜索回调函数进行响应
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback); } else { mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback); } } /**
* 搜索到BLE终端服务的事件
*/
private BluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = new OnServiceDiscoverListener() { @Override
public void onServiceDiscover(BluetoothGatt gatt) { displayGattServices(mBLE.getSupportedGattService());
} }; /**
* 收到BLE终端数据交互的事件
*/
private BluetoothLeClass.OnDataAvailableListener mOnDataAvailable = new OnDataAvailableListener() { /**
* BLE终端数据写入的事件
*/
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS)
Log.e(TAG,
"onCharRead "
+ gatt.getDevice().getName()
+ " read "
+ characteristic.getUuid().toString()
+ " -> "
+ Utils.bytesToHexString(characteristic
.getValue())); } /**
* 对BLE终端读取数据
*/
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
info = new String(characteristic.getValue());//对得到的byte数组进行解码,构造新的string
Log.e(TAG, "onCharWrite " + gatt.getDevice().getName() + " write "
+ characteristic.getUuid().toString() + " -> " + info);
if (!S_BT_info.equals(info)) {//判断读取的数据是否发生变化,如果变化,更新UI
DeviceScanActivity.this.runOnUiThread(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
BT_link.setText("已连接");
StringBuilder sb = new StringBuilder();//详情参见:http://blog.csdn.net/rmn190/article/details/1492013
sb.append(info);
sb.append("度");
BT_info.setText(sb.toString());
sb = null; }
}); } }
}; private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {//搜索回调函数:
String BT_name = null; @Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() { @Override
public void run() {
// TODO Auto-generated method stub
BT_name = device.getName();
if (BT_name.equals(BTtoFind)) { //如果是要找的设备,更新UI上信息,设置搜索标志,停止响应搜索回调函数,连接BLE设备
/** 连接事件 */
BT_find.setText("已找到设备!");
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mBLE.connect(device.getAddress()); } }
}); }
}; private void displayGattServices(BluetoothGattService bluetoothGattService) { if (bluetoothGattService == null)
return; // -----Service的字段信息-----//
int type = bluetoothGattService.getType();
Log.e(TAG, "-->service type:" + Utils.getServiceType(type));
Log.e(TAG, "-->includedServices size:"
+ bluetoothGattService.getIncludedServices().size());
Log.e(TAG, "-->service uuid:" + bluetoothGattService.getUuid()); // -----Characteristics的字段信息-----//
List<BluetoothGattCharacteristic> gattCharacteristics = bluetoothGattService
.getCharacteristics();
for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
Log.e(TAG, "---->char uuid:" + gattCharacteristic.getUuid()); int permission = gattCharacteristic.getPermissions();
Log.e(TAG,
"---->char permission:"
+ Utils.getCharPermission(permission)); int property = gattCharacteristic.getProperties();
Log.e(TAG, "---->char property:" + Utils.getCharPropertie(property)); byte[] data = gattCharacteristic.getValue();
if (data != null && data.length > 0) {
Log.e(TAG, "---->char value:" + new String(data));
} // UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic
if (gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA)) {
// 测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mBLE.readCharacteristic(gattCharacteristic);
}
}, 500); // 接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
mBLE.setCharacteristicNotification(gattCharacteristic, true);
// 设置数据内容
gattCharacteristic.setValue("send data->");
// 往蓝牙模块写入数据
mBLE.writeCharacteristic(gattCharacteristic);
} // -----Descriptors的字段信息-----//
List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic
.getDescriptors();
for (BluetoothGattDescriptor gattDescriptor : gattDescriptors) {
Log.e(TAG, "-------->desc uuid:" + gattDescriptor.getUuid());
int descPermission = gattDescriptor.getPermissions();
Log.e(TAG,
"-------->desc permission:"
+ Utils.getDescPermission(descPermission)); byte[] desData = gattDescriptor.getValue();
if (desData != null && desData.length > 0) {
Log.e(TAG, "-------->desc value:" + new String(desData));
}
} } } }
package com.TANK.temperature.BT; import java.util.UUID; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log; public class BluetoothLeClass{
private final static String TAG = BluetoothLeClass.class.getSimpleName(); private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
private BluetoothGatt mBluetoothGatt; public interface OnConnectListener {
public void onConnect(BluetoothGatt gatt);
}
public interface OnDisconnectListener {
public void onDisconnect(BluetoothGatt gatt);
}
public interface OnServiceDiscoverListener {
public void onServiceDiscover(BluetoothGatt gatt);
}
public interface OnDataAvailableListener {
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status);
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic);
} private OnConnectListener mOnConnectListener;
private OnDisconnectListener mOnDisconnectListener;
private OnServiceDiscoverListener mOnServiceDiscoverListener;
private OnDataAvailableListener mOnDataAvailableListener;
private Context mContext;
public void setOnConnectListener(OnConnectListener l){
mOnConnectListener = l;
}
public void setOnDisconnectListener(OnDisconnectListener l){
mOnDisconnectListener = l;
}
public void setOnServiceDiscoverListener(OnServiceDiscoverListener l){
mOnServiceDiscoverListener = l;
}
public void setOnDataAvailableListener(OnDataAvailableListener l){
mOnDataAvailableListener = l;
} public BluetoothLeClass(Context c){
mContext = c;
} // 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) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
if(mOnConnectListener!=null)
mOnConnectListener.onConnect(gatt);
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) {
if(mOnDisconnectListener!=null)
mOnDisconnectListener.onDisconnect(gatt);
Log.i(TAG, "Disconnected from GATT server.");
}
} @Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS && mOnServiceDiscoverListener!=null) {
mOnServiceDiscoverListener.onServiceDiscover(gatt);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
} @Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (mOnDataAvailableListener!=null)
mOnDataAvailableListener.onCharacteristicRead(gatt, characteristic, status);
} @Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
if (mOnDataAvailableListener!=null)
mOnDataAvailableListener.onCharacteristicWrite(gatt, characteristic);
}
}; /**
* 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) mContext.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()) {
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(mContext, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
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);
} public void writeCharacteristic(BluetoothGattCharacteristic characteristic){
mBluetoothGatt.writeCharacteristic(characteristic);
}
/**
* 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 BluetoothGattService getSupportedGattService() {//根据service的UUID来获取service
if (mBluetoothGatt == null) return null; return mBluetoothGatt.getService(UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb"));
}
}
public class Utils { private static HashMap<Integer, String> serviceTypes = new HashMap();
static {
// Sample Services.
serviceTypes.put(BluetoothGattService.SERVICE_TYPE_PRIMARY, "PRIMARY");
serviceTypes.put(BluetoothGattService.SERVICE_TYPE_SECONDARY, "SECONDARY");
} public static String getServiceType(int type){
return serviceTypes.get(type);
} //-------------------------------------------
private static HashMap<Integer, String> charPermissions = new HashMap();
static {
charPermissions.put(0, "UNKNOW");
charPermissions.put(BluetoothGattCharacteristic.PERMISSION_READ, "READ");
charPermissions.put(BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED, "READ_ENCRYPTED");
charPermissions.put(BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED_MITM, "READ_ENCRYPTED_MITM");
charPermissions.put(BluetoothGattCharacteristic.PERMISSION_WRITE, "WRITE");
charPermissions.put(BluetoothGattCharacteristic.PERMISSION_WRITE_ENCRYPTED, "WRITE_ENCRYPTED");
charPermissions.put(BluetoothGattCharacteristic.PERMISSION_WRITE_ENCRYPTED_MITM, "WRITE_ENCRYPTED_MITM");
charPermissions.put(BluetoothGattCharacteristic.PERMISSION_WRITE_SIGNED, "WRITE_SIGNED");
charPermissions.put(BluetoothGattCharacteristic.PERMISSION_WRITE_SIGNED_MITM, "WRITE_SIGNED_MITM");
} public static String getCharPermission(int permission){
return getHashMapValue(charPermissions,permission);
}
//-------------------------------------------
private static HashMap<Integer, String> charProperties = new HashMap();
static { charProperties.put(BluetoothGattCharacteristic.PROPERTY_BROADCAST, "BROADCAST");
charProperties.put(BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS, "EXTENDED_PROPS");
charProperties.put(BluetoothGattCharacteristic.PROPERTY_INDICATE, "INDICATE");
charProperties.put(BluetoothGattCharacteristic.PROPERTY_NOTIFY, "NOTIFY");
charProperties.put(BluetoothGattCharacteristic.PROPERTY_READ, "READ");
charProperties.put(BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE, "SIGNED_WRITE");
charProperties.put(BluetoothGattCharacteristic.PROPERTY_WRITE, "WRITE");
charProperties.put(BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE, "WRITE_NO_RESPONSE");
} public static String getCharPropertie(int property){
return getHashMapValue(charProperties,property);
} //--------------------------------------------------------------------------
private static HashMap<Integer, String> descPermissions = new HashMap();
static {
descPermissions.put(0, "UNKNOW");
descPermissions.put(BluetoothGattDescriptor.PERMISSION_READ, "READ");
descPermissions.put(BluetoothGattDescriptor.PERMISSION_READ_ENCRYPTED, "READ_ENCRYPTED");
descPermissions.put(BluetoothGattDescriptor.PERMISSION_READ_ENCRYPTED_MITM, "READ_ENCRYPTED_MITM");
descPermissions.put(BluetoothGattDescriptor.PERMISSION_WRITE, "WRITE");
descPermissions.put(BluetoothGattDescriptor.PERMISSION_WRITE_ENCRYPTED, "WRITE_ENCRYPTED");
descPermissions.put(BluetoothGattDescriptor.PERMISSION_WRITE_ENCRYPTED_MITM, "WRITE_ENCRYPTED_MITM");
descPermissions.put(BluetoothGattDescriptor.PERMISSION_WRITE_SIGNED, "WRITE_SIGNED");
descPermissions.put(BluetoothGattDescriptor.PERMISSION_WRITE_SIGNED_MITM, "WRITE_SIGNED_MITM");
} public static String getDescPermission(int property){
return getHashMapValue(descPermissions,property);
} //这段代码没看明白,欢迎大神指教
private static String getHashMapValue(HashMap<Integer, String> hashMap,int number){
String result =hashMap.get(number);
if(TextUtils.isEmpty(result)){
List<Integer> numbers = getElement(number);
result="";
for(int i=0;i<numbers.size();i++){
result+=hashMap.get(numbers.get(i))+"|";
}
}
return result;
} /**
* 位运算结果的反推函数10 -> 2 | 8;
*/
static private List<Integer> getElement(int number){
List<Integer> result = new ArrayList<Integer>();
for (int i = 0; i < 32; i++){
int b = 1 << i;
if ((number & b) > 0)
result.add(b);
} return result;
} public static String bytesToHexString(byte[] src){
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
}
Android和BLE模块连接通信的更多相关文章
- Android BLE与终端通信(二)——Android Bluetooth基础科普以及搜索蓝牙设备显示列表
Android BLE与终端通信(二)--Android Bluetooth基础搜索蓝牙设备显示列表 摘要 第一篇算是个热身,这一片开始来写些硬菜了,这篇就是实际和蓝牙打交道了,所以要用到真机调试哟, ...
- 【转】android蓝牙开发---与蓝牙模块进行通信--不错
原文网址:http://www.cnblogs.com/wenjiang/p/3200138.html 近半个月来一直在搞android蓝牙这方面,主要是项目需要与蓝牙模块进行通信.开头的进展很顺利, ...
- Android BLE与终端通信(五)——Google API BLE4.0低功耗蓝牙文档解读之案例初探
Android BLE与终端通信(五)--Google API BLE4.0低功耗蓝牙文档解读之案例初探 算下来很久没有写BLE的博文了,上家的技术都快忘记了,所以赶紧读了一遍Google的API顺便 ...
- Android BLE与终端通信(四)——实现服务器与客户端即时通讯功能
Android BLE与终端通信(四)--实现服务器与客户端即时通讯功能 前面几篇一直在讲一些基础,其实说实话,蓝牙主要为多的还是一些概念性的东西,当你把概念都熟悉了之后,你会很简单的就可以实现一些逻 ...
- Android BLE与终端通信(三)——客户端与服务端通信过程以及实现数据通信
Android BLE与终端通信(三)--客户端与服务端通信过程以及实现数据通信 前面的终究只是小知识点,上不了台面,也只能算是起到一个科普的作用,而同步到实际的开发上去,今天就来延续前两篇实现蓝牙主 ...
- Android BLE与终端通信(一)——Android Bluetooth基础API以及简单使用获取本地蓝牙名称地址
Android BLE与终端通信(一)--Android Bluetooth基础API以及简单使用获取本地蓝牙名称地址 Hello,工作需要,也必须开始向BLE方向学习了,公司的核心技术就是BLE终端 ...
- Android蓝牙BLE开发,扫描、连接、发送和读取信息;
1.BLE开发权限 Android蓝牙BLE开发须打开蓝牙权限和6.0位置权限: <uses-permission android:name="android.permission.B ...
- Android BLE设备蓝牙通信框架BluetoothKit
BluetoothKit是一款功能强大的Android蓝牙通信框架,支持低功耗蓝牙设备的连接通信.蓝牙广播扫描及Beacon解析. 关于该项目的详细文档请关注:https://github.com/d ...
- android蓝牙开发---与蓝牙模块进行通信
近半个月来一直在搞android蓝牙这方面,主要是项目需要与蓝牙模块进行通信.开头的进展很顺利,但因为蓝牙模块不在我这里,所以只能用手机测试.一开头就发现手机的蓝牙不能用,为了证明这点,我刷了四次不同 ...
随机推荐
- Unity3D项目优化(转)
前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...
- js表单提交,判断文本框,用户名密码是否为空,JS表单检测!
当表单提交时先触发验证的js代码,当验证表单的方法返回true时才会提交表单返回false则不提交数据<script type="text/javascript">fu ...
- Spring的事务传播机制
1.事务传播类型 新建事务 required required_new - 挂起当前 非事务方式运行 supports not_supported - 挂起当前 never ...
- 在 Linux 系统中安装Load Generator ,并在windows 调用方法
在 Linux 系统中安装Load Generator ,并在windows 调用 由于公司需要测试系统的最大用户承受能力,所以需要学习使用loadrunner.在安装的时候碰到了不少问题,所以写下此 ...
- zendstudio的安装与配置
<微信公众平台应用开发实战>第1章搭建开发环境和相关技术介绍,本章会先介绍微信公众平台的一些基本概念和公众平台的开发模式:然后讲解如何搭建开发环境—AppServ和zendstudio:然 ...
- Mysql 随机查询数据
SELECT * FROM tablename ORDER BY RAND() LIMIT 10
- Attrib命令,可以让文件夹彻底的隐藏起来
Attrib命令,可以让文件夹彻底的隐藏起来,就算是在文件夹选项中设置了显示隐藏文件夹,也无法显示出来的.只能通过路径访问的方式打开文件夹.如上图,就是attrib命令的隐藏文件夹和显示文件夹的两条命 ...
- 修改sqlserver的数据库排序规则语句
alter database SOETMS collate Chinese_PRC_CI_AS
- 简单的划分数问题<划分问题>
将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法. 思路: 动态规 ...
- Android EditText的设置(转)
1.输入法Enter键图标的设置: 软件盘的界面替换只有一个属性android:imeOptions,这个属性的可以取的值有normal,actionUnspecified,actionNone,ac ...