SDK安卓工具开发
拿到CC2640后,没想到最近事情变得这么忙,目前主要是看视频和阅读代码,因为时间问题,所以就反着来先读APP的代码和SDK流程,因为最近也在调试动态心率,目前是用的官方的APP再截取log,好麻烦,心想着如果能有一个测试APP保存自己想要的log的话,该多好。所以这个项目完成后,可能就会考虑自己搞一个可以采数据的APP,刚好CC2640里面有相关的例程,然后结合之前一些经验,分享一下目前的学习经验。
另一方面由于公司的电脑加密,所以固件那边只能看看代码和视频,一改内容编译就会出错,同时因为CC2640的资源不适合做手环所以只能在家里调试玩玩,完成一些透传的功能。不过从SDK里面固件的架构来说,非常适合一些简单的开发,非常方便,流程也非常大致一样,但是前提是得看视频,不看视频下手会感觉很乱,看了之后就会看懂框架之后开发就很容易了。
第一份家庭作业,先调试了一下安卓,后面再写固件相关的文档。
学习安卓APP的话,建议有空看下“第一行代码”,我觉得比较适合新手学习,可以指导大家一步步上手,具体就不多说了,编译时候遇到的问题和ble相关的流程吧。
file:///C:\DOCUME~1\x110809\LOCALS~1\Temp\ksohtml\wps1021.tmp.jpg
官方的SDK里面含有安卓,用andriod studio打开后,刚开始可能我的编译器版本太老了,所以编译不通过。升级后还是报错,然后通过错误信息百度了一下
需要将gradle.properties下的org.gradle.jvmargs=-Xmx1536m改成org.gradle.jvmargs=-Xmx153m就可以解决此问题。
解决上述两个问题
接下来就是代码部分,首先APP的效果如下:
APP方便使用,可以查看广播信息,收发数据,同时还可以实现一拖多的功能,不过有一点不方便的是因为只加了官方的UUID。有些自定义的UUID可能会识别不到。
file:///C:\DOCUME~1\x110809\LOCALS~1\Temp\ksohtml\wps1023.tmp.jpg file:///C:\DOCUME~1\x110809\LOCALS~1\Temp\ksohtml\wps1024.tmp.jpg file:///C:\DOCUME~1\x110809\LOCALS~1\Temp\ksohtml\wps1025.tmp.jpg
我们主要看代码部分蓝牙相关:
1、权限申请 在androidManifest.xml
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
2检查手机是否支持蓝牙 在MainActivity的活动创建时,如果不支持则弹出不支持蓝牙信息
private void checkBLEFeature() {
检查当前手机是否支持ble 蓝牙,如果不支持退出程序
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
// 初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
}
}
3、检查是否开启蓝牙,在创建活动后,不过没打开蓝牙,则会弹出某个应用想开启蓝牙信息
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
4、扫描
创建一个listAdapter来显示搜索到的蓝牙信息
mLeDeviceListAdapter = new LeDeviceListAdapter();
获取到一个蓝牙服务连接的适配器
BluetoothManager bm = (BluetoothManager) getActivity().getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bm.getAdapter();
在listView里面设置item点击和长按的监听,点击事件响应连接,长按事件响应显示广播信息
listView.setOnItemClickListener(mOnItemClickListener);
listView.setOnItemLongClickListener(mOnItemLongClickListener);
扫描设备
mBluetoothAdapter.startLeScan(mLeScanCallback);
扫描事件回调,创建线程刷新扫描到的设备
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLeDeviceListAdapter
.addDevice(new LeDevice(device.getName(), device.getAddress(), rssi, scanRecord));
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
长按显示广播信息,主要是mac地址,广播数据,相关的UUID等一些信息
private void showAdvDetailsDialog(LeDevice device)
LeScanRecord record = device.getLeScanRecord();
5、连接
单击相应的listview,链接相关设备,mLeProxy是一个自定义蓝牙相关事件处理的一个类,第二个参数选择是否自动链接。
mLeProxy.connect(device.getAddress(), false);
在LeProxy类里的蓝牙服务连接
mBleService.connect(address, autoConnect);
在 BleCallBack()回调下面有响应链接成功的回调函数 onConnected(String address)
6、获取服务
连接后获取服务,一般是在获取到链接事件后直接处理获取服务的,但是在这个APP上是在mainActivy下绑定拿到BleService的引用,从而可以引用其内部的方法和变量
bindService(new Intent(this, BleService.class), mConnection, BIND_AUTO_CREATE);
然后再在调用获取服务的回调函数
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.w(TAG, "onServiceDisconnected()");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
LeProxy.getInstance().setBleService(service);
}
};
mBleService = ((BleService.LocalBinder) binder).getService(mBleCallBack);
获取服务后,做的操作,感觉这种操作比较复杂,都是直接获取服务的,但是用这种机制感觉会更加稳定
public void onServicesDiscovered(String address) {
//!检索服务成功,到这一步才可以与从机进行数据交互,有些手机可能需要延时几百毫秒才能数据交互
Log.i(TAG, "onServicesDiscovered() - " + address);
new Timer().schedule(new ServicesDiscoveredTask(address), 300, 100);
}
这里是直接获取到官方服务,但是如果有自定义服务的话,会有一个查询自定义服务的过程类似于gatt.getService();来获取响应数据通道的服务
//打开模组默认的数据接收通道【0x1002】,这一步成功才能保证APP收到数据
boolean success = enableNotification(address, BleUUIDS.PRIMARY_SERVICE, BleUUIDS.CHARACTERS[1]);
Log.i(TAG, "Enable 0x1002 notification: " + success);
break;
7、获取到服务之后,获取相应的数据通道character,并使能
BluetoothGattCharacteristic c = GattUtil.getGattCharacteristic(gatt, serUuid, charUuid);
setCharacteristicNotification(gatt, c, true);
这样数据通道基本打通了,接下来是收发数据
在mBleCallBack回调里面有一个函数onCharacteristicChanged,这个函数是通知charaterist里面有事件发生,此时就可以读取到相应character所获取的设备上传的数据
public void onCharacteristicChanged(String address, BluetoothGattCharacteristic characteristic) {
Log.i(TAG, "onCharacteristicChanged() - " + address + " uuid=" + characteristic.getUuid().toString()
+ "\n len=" + characteristic.getValue().length
+ " [" + DataUtil.byteArrayToHex(characteristic.getValue()) + ']');
updateBroadcast(address, characteristic);
}
发送数据,不过在发送数据是注意data的数据转换
mLeProxy.send(mSelectedAddresses.get(i), data, mBoxEncrypt.isChecked());
以上就是在学习蓝牙4.0安卓相关和CC2640SDK里面提供的andriod 相关接口时的一些积累,如果有错误的地方还请指点,因为我也只是刚刚开始学习,了解一些app的蓝牙流程对蓝牙开发也是挺好的,愿你我共同进步。APP亲测非常稳定,作为一位嵌入式学习andriod的新手来说来说,很多东西值得学习。