需要将gradle.proper
ties下的
org.gradle.jvmargs=
-Xmx1536m改成org.gradle.jvmargs=
-Xmx153m就可以解决此问题。
解决上述两个问题
接下来就是代码部分,首先APP的效果如下:
APP方便使用,可以查看广播信息,收发数据,同时还可以实现一拖多的功能,不过有一点不方便的是因为只加了官方的UUID。有些自定义的UUID可能会识别不到。
我们主要看代码部分蓝牙相关:
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的新手来说来说,很多东西值得学习。