微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > SDK安卓工具开发

SDK安卓工具开发

时间:10-02 整理:3721RD 点击:

拿到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的新手来说来说,很多东西值得学习。


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top