Java Android Studio Ble Gatt连接将数据写入自定义服务特性

Java Android Studio Ble Gatt连接将数据写入自定义服务特性,java,android-studio,bluetooth,bluetooth-lowenergy,gatt,Java,Android Studio,Bluetooth,Bluetooth Lowenergy,Gatt,我正在尝试将一些自定义数据写入带有自定义服务的BLE设备。我遵循了这个教程:它来自android 我可以查看带有数据的自定义服务。还可以通过另一个应用程序(NRF connect)将数据写入此自定义服务。因此,我知道可以将数据写入服务 我遇到的问题是如何使用BluetoothGatt将数据写入定制服务的其他示例,而这段代码似乎使用BluetoothLeService。这是一个问题,因为文档似乎没有BluetoothLeService的读取API。所以我不能使用mbluetothgatt.read

我正在尝试将一些自定义数据写入带有自定义服务的BLE设备。我遵循了这个教程:它来自android

我可以查看带有数据的自定义服务。还可以通过另一个应用程序(NRF connect)将数据写入此自定义服务。因此,我知道可以将数据写入服务

我遇到的问题是如何使用BluetoothGatt将数据写入定制服务的其他示例,而这段代码似乎使用BluetoothLeService。这是一个问题,因为文档似乎没有BluetoothLeService的读取API。所以我不能使用mbluetothgatt.readCharacteristic(mReadCharacteristic)之类的东西

我怎样才能创建一个函数,将一个值(整数)写入函数。 我的服务UUID是:“f3641400-00b0-4240-ba50-05ca45bf8abc”

我的特性UUID是:“f3641401-00b0-4240-ba50-05ca45bf8abc”

我的代码如下,以供参考:

public class DeviceControlActivity extends Activity {
private final static String TAG = 
DeviceControlActivity.class.getSimpleName();

public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";

private TextView mConnectionState;
private TextView mDataField;
private EditText Command_string;
private BluetoothGatt mGatt;
private Button btn_gatt_connect;
private Button btn_live,btn_command;
private String mDeviceName;
private String mDeviceAddress;
private String User_data;
private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
        new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;

private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
private String Switch_case ="Connect";
private boolean Write_ble_command = true;

// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder service) {
        mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
        if (!mBluetoothLeService.initialize()) {
            Log.e(TAG, "Unable to initialize Bluetooth");
            finish();
        }
        // Automatically connects to the device upon successful start-up initialization.
        mBluetoothLeService.connect(mDeviceAddress);
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        mBluetoothLeService = null;
    }
};

// Handles various events fired by the Service.
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device.  This can be a result of read
//                        or notification operations.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
            mConnected = true;
            updateConnectionState(R.string.connected);
            invalidateOptionsMenu();
        } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
            mConnected = false;
            updateConnectionState(R.string.disconnected);
            invalidateOptionsMenu();
            clearUI();
        } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
            // Show all the supported services and characteristics on the user interface.
            displayGattServices(mBluetoothLeService.getSupportedGattServices());
        } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
            displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
        }
    }
};
// If a given GATT characteristic is selected, check for supported features.  This sample
// demonstrates 'Read' and 'Notify' features.  See
// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
// list of supported characteristic features.
private final ExpandableListView.OnChildClickListener servicesListClickListner =
        new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
                                        int childPosition, long id) {
                if (mGattCharacteristics != null) {
                    final BluetoothGattCharacteristic characteristic =
                            mGattCharacteristics.get(groupPosition).get(childPosition);
                    final int charaProp = characteristic.getProperties();
                    if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                        // If there is an active notification on a characteristic, clear
                        // it first so it doesn't update the data field on the user interface.
                        if (mNotifyCharacteristic != null) {
                            mBluetoothLeService.setCharacteristicNotification(
                                    mNotifyCharacteristic, false);
                            mNotifyCharacteristic = null;
                        }
                        mBluetoothLeService.readCharacteristic(characteristic);
                    }
                    if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                        mNotifyCharacteristic = characteristic;
                        mBluetoothLeService.setCharacteristicNotification(
                                characteristic, true);
                    }
                    return true;
                }
                return false;
            }
        };

private void Gatt_Connect()
{
    switch(Switch_case) {
        case "Connect":
            btn_gatt_connect.setText("Disconnect");//Presently connected allow to disconnect
            mBluetoothLeService.connect(mDeviceAddress);
            Switch_case = "Disconnect";
            break;
        case "Disconnect":
            btn_gatt_connect.setText("Connect");//Presently disconnected allow to connect
            mBluetoothLeService.disconnect();
            Switch_case = "Connect";
            break;
    }

}
private void Live_data(){
    //Ensure you are disconnected
    btn_gatt_connect.setText("Connect");//Presently disconnected allow to connect
    mBluetoothLeService.disconnect();//Might only run if connected
    Switch_case = "Connect";
    Intent myIntent = new Intent(DeviceControlActivity.this, MainActivity.class);
    Bundle bundle = new Bundle();
    bundle.putString("User_data", User_data);//Pass through the user's email address to the main activity for display
    myIntent.putExtras(bundle);
    DeviceControlActivity.this.startActivity(myIntent);//Run the main activity}
}
private void clearUI() {
    mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
    mDataField.setText(R.string.no_data);
}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gatt_services_characteristics);

    //Get the extras passed in
    Bundle bundle = getIntent().getExtras();
    mDeviceName = bundle.getString("Device_Name");
    mDeviceAddress = bundle.getString("Device_Address");
    User_data = bundle.getString("User_data");

    // Sets up UI references.
    ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);

    Command_string = (EditText)findViewById(R.id.Command_string);
    btn_gatt_connect = (Button)findViewById(R.id.btn_gatt_connect);
    btn_live = (Button) findViewById(R.id.btn_live);
    btn_command = (Button) findViewById(R.id.btn_command);
    btn_gatt_connect.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Gatt_Connect();
        }
    });

    btn_gatt_connect.setText("Disconnect");//Presently disconnected allow to connect

    btn_live.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Live_data();
        }
    });
    btn_command.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Send_Command();//Sends the command in the text box to the nordic board
        }
    });

    mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);
    mGattServicesList.setOnChildClickListener(servicesListClickListner);
    mConnectionState = (TextView) findViewById(R.id.connection_state);
    mDataField = (TextView) findViewById(R.id.data_value);

    //setTitle(mDeviceAddress);//Change the title to Scanner as the device is no longer being read
    Intent gattServiceIntent = new Intent(DeviceControlActivity.this, BluetoothLeService.class);
    bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onResume() {
    super.onResume();
    registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
    if (mBluetoothLeService != null) {
        final boolean result = mBluetoothLeService.connect(mDeviceAddress);
        Log.d(TAG, "Connect request result=" + result);
    }
}
@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(mGattUpdateReceiver);
}
@Override
protected void onDestroy() {
    super.onDestroy();
    unbindService(mServiceConnection);
    mBluetoothLeService = null;
}

protected void Send_Command()
{
    Write_ble_command = true;//Write command issued on display gatt service
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.gatt_services, menu);
    if (mConnected) {
        menu.findItem(R.id.menu_connect).setVisible(false);
        menu.findItem(R.id.menu_disconnect).setVisible(true);
    } else {
        menu.findItem(R.id.menu_connect).setVisible(true);
        menu.findItem(R.id.menu_disconnect).setVisible(false);
    }
    return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()) {
        case R.id.menu_connect:
            mBluetoothLeService.connect(mDeviceAddress);
            return true;
        case R.id.menu_disconnect:
            mBluetoothLeService.disconnect();
            return true;
        case android.R.id.home:
            onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}
private void updateConnectionState(final int resourceId) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mConnectionState.setText(resourceId);
        }
    });
}
private void displayData(String data) {
    if (data != null) {
        mDataField.setText(data);
    }
}
// Demonstrates how to iterate through the supported GATT Services/Characteristics.
// In this sample, we populate the data structure that is bound to the ExpandableListView
// on the UI.
private void displayGattServices(List<BluetoothGattService> gattServices) {
    if (gattServices == null) return;
    String uuid = null;
    String unknownServiceString = getResources().getString(R.string.unknown_service);
    String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
    ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
    ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
            = new ArrayList<ArrayList<HashMap<String, String>>>();
    mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

    // Loops through available GATT Services.
    for (BluetoothGattService gattService : gattServices) {
        HashMap<String, String> currentServiceData = new HashMap<String, String>();
        uuid = gattService.getUuid().toString();
        currentServiceData.put(
                LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
        currentServiceData.put(LIST_UUID, uuid);
        gattServiceData.add(currentServiceData);

        ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
                new ArrayList<HashMap<String, String>>();
        List<BluetoothGattCharacteristic> gattCharacteristics =
                gattService.getCharacteristics();
        ArrayList<BluetoothGattCharacteristic> charas =
                new ArrayList<BluetoothGattCharacteristic>();

        // Loops through available Characteristics.
        for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
            charas.add(gattCharacteristic);
            HashMap<String, String> currentCharaData = new HashMap<String, String>();
            uuid = gattCharacteristic.getUuid().toString();
            currentCharaData.put(
                    LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
            currentCharaData.put(LIST_UUID, uuid);
            gattCharacteristicGroupData.add(currentCharaData);
        }
        mGattCharacteristics.add(charas);
        gattCharacteristicData.add(gattCharacteristicGroupData);
    }

    SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
            this,
            gattServiceData,
            android.R.layout.simple_expandable_list_item_2,
            new String[] {LIST_NAME, LIST_UUID},
            new int[] { android.R.id.text1, android.R.id.text2 },
            gattCharacteristicData,
            android.R.layout.simple_expandable_list_item_2,
            new String[] {LIST_NAME, LIST_UUID},
            new int[] { android.R.id.text1, android.R.id.text2 }
    );
    mGattServicesList.setAdapter(gattServiceAdapter);

}
private static IntentFilter makeGattUpdateIntentFilter() {
    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
    intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
    return intentFilter;
}
公共类设备ControlActivity扩展活动{
私有最终静态字符串标记=
DeviceControlActivity.class.getSimpleName();
公共静态最终字符串EXTRAS\u DEVICE\u NAME=“DEVICE\u NAME”;
公共静态最终字符串EXTRAS\u DEVICE\u ADDRESS=“DEVICE\u ADDRESS”;
私有文本视图mConnectionState;
私有文本视图mDataField;
私有EditText命令_字符串;
私人蓝牙GATT mGatt;
专用按钮btn_gatt_connect;
专用按钮btn_live,btn_命令;
私有字符串mDeviceName;
私有字符串mDeviceAddress;
私有字符串用户_数据;
私有可扩展列表视图mGattServicesList;
私人蓝牙服务mBluetoothLeService;
私有数组列表特征=
新的ArrayList();
私有布尔值mConnected=false;
私人蓝牙公司的特征性特征;
私有最终字符串列表\u NAME=“NAME”;
私有最终字符串列表\u UUID=“UUID”;
专用字符串开关\u case=“Connect”;
私有布尔写函数命令=true;
//用于管理服务生命周期的代码。
专用最终ServiceConnection mServiceConnection=新ServiceConnection(){
@凌驾
服务连接上的公共无效(组件名称组件名称,IBinder服务){
mBluetoothLeService=((BluetoothLeService.LocalBinder)服务).getService();
如果(!mBluetoothLeService.initialize()){
Log.e(标记“无法初始化蓝牙”);
完成();
}
//成功启动初始化后自动连接到设备。
mBluetoothLeService.connect(mDeviceAddress);
}
@凌驾
ServiceDisconnected上的公共无效(ComponentName ComponentName){
mBluetoothLeService=null;
}
};
//处理服务触发的各种事件。
//操作\u GATT\u已连接:连接到GATT服务器。
//操作\u GATT\u断开连接:从GATT服务器断开连接。
//行动\u GATT\u服务\u发现:发现的GATT服务。
//操作\u数据\u可用:从设备接收数据。这可能是读取的结果
//或通知操作。
private final BroadcastReceiver mGattUpdateReceiver=新的BroadcastReceiver(){
@凌驾
公共void onReceive(上下文、意图){
最后一个字符串action=intent.getAction();
if(蓝牙服务动作\关贸总协定\连接的相等动作){
mConnected=true;
updateConnectionState(R.string.connected);
无效操作菜单();
}else if(蓝牙服务操作\u GATT\u断开连接。等于(操作)){
mConnected=false;
updateConnectionState(R.string.disconnected);
无效操作菜单();
clearUI();
}else if(BluetoothLeService.ACTION\u GATT\u SERVICES\u DISCOVERED.equals(ACTION)){
//在用户界面上显示所有支持的服务和特性。
displayGattServices(mBluetoothLeService.getSupportedGattServices());
}else if(BluetoothLeService.ACTION\u DATA\u AVAILABLE.equals(ACTION)){
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_数据));
}
}
};
//如果选择了给定的GATT特性,请检查支持的特性。此示例
//演示“读取”和“通知”功能。请参阅
// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html 完整地
//支持的特征特性列表。
private final ExpandableListView.OnChildClickListener服务单击列表器=
新的ExpandableListView.OnChildClickListener(){
@凌驾
公共布尔onChildClick(ExpandableListView父视图、视图v、int-groupPosition、,
int子位置,长id){
if(mGattCharacteristics!=null){
最终蓝牙特征=
mGattCharacteristics.get(groupPosition).get(childPosition);
final int charaProp=characteristic.getProperties();
if((charaProp | BluetoothGattCharacteristic.PROPERTY_READ)>0){
//如果特性上存在活动通知,请清除
//它会首先更新,这样就不会更新用户界面上的数据字段。
if(mNotifyCharacteristic!=null){
mBluetoothLeService.setCharacteristicNotification(
mnotify(特征,假);
mNotifyCharacteristic=null;
}
mBluetoothLeService.readCharacteristic(特征);
}
如果((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY)>0){
mNotifyCharacteristic=特征;
mBluetoothLeService.setCharacteristicNotification(
特征
public void writeCharacteristic(int Data) {
    if (mBluetoothAdapter == null || mBluetoothGatt == null) {
        Log.w(TAG, "BluetoothAdapter not initialized");
        return;
    }

    byte[] value = intToByteArray(Data);

    BluetoothGattService mCustomService = mBluetoothGatt.getService(UUID.fromString("f3641400-00b0-4240-ba50-05ca45bf8abc"));
    if(mCustomService == null){
        Log.w(TAG, "Custom BLE Service not found");
        return;
    }
    /*get the read characteristic from the service*/
    BluetoothGattCharacteristic characteristic = mCustomService.getCharacteristic(UUID.fromString("f3641401-00b0-4240-ba50-05ca45bf8abc"));
    characteristic.setValue(value);
    mBluetoothGatt.writeCharacteristic(characteristic);
}