onCharacteristicChanged()从未调用过

时间:2016-02-26 19:03:37

标签: android bluetooth bluetooth-lowenergy texas-instruments

我正在尝试从德州传感器标签接收数据,但到目前为止,我只是设法连接并向其写入特征。

这是我的setCharacteristicNotification(); 下面评论的部分不起作用,我没有设法使用它。

    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
                                              boolean enabled) {
        if(bluetoothAdapter == null || bluetoothGatt == null) return;

        bluetoothGatt.setCharacteristicNotification(characteristic, enabled);

        if(GattUUIDs.containsUuid(characteristic.getUuid())) {
//            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
//                    UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
            BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(
                    GattUUIDs.UUID_CLIENT_CHAR_CONFIG, BluetoothGattDescriptor.PERMISSION_WRITE |
                    BluetoothGattDescriptor.PERMISSION_READ);

            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            bluetoothGatt.writeDescriptor(descriptor);

        }
    }

当我尝试调用注释块时,这就是我收到的内容:

  

java.lang.NullPointerException:尝试调用虚方法   'boolean android.bluetooth.BluetoothGattDescriptor.setValue(byte [])'   在空对象引用上

这是我的客户端特性配置UUID:

public static final UUID UUID_CLIENT_CHAR_CONFIG =
         UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG);
public static String CLIENT_CHARACTERISTIC_CONFIG = "f0002902-0451-4000-b000-000000000000";

我认为它在我的描述符中存在某种问题,因为我可以注册它,但我从来没有得到它的回调。

如果有帮助,这是我的服务:

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import java.util.List;
import java.util.UUID;


/**
 * Created by alan on 2/23/16.
 */
public class DeviceService extends Service {

    private final static String TAG = DeviceService.class.getSimpleName();

    private BluetoothGatt bluetoothGatt;
    private String deviceAddress;
    private BluetoothManager bluetoothManager;
    private BluetoothAdapter bluetoothAdapter;
    private int connectionState = STATE_DISCONNECTED;

    public final IBinder binder = new LocalBinder();
    public static final int STATE_DISCONNECTED = 0;
    public static final int STATE_CONNECTING   = 1;
    public static final int STATE_CONNECTED    = 2;

    public static final String ACTION_GATT_SERVICES_DISCOVERED = "action_gatt_services_discovered";
    public static final String ACTION_GATT_DISCONNECTED        = "action_gatt_disconnected";
    public static final String ACTION_GATT_CONNECTED           = "action_gatt_connected";
    public static final String ACTION_DATA_AVAILABLE           = "action_data_available";
    public static final String ACTION_DATA_NOTIFY              = "action_data_notify";
    public static final String ACTION_DATA_WRITE               = "action_data_write";
    public static final String ACTION_DATA_READ                = "action_data_read";
    public static final String EXTRA_DATA                      = "extra_data";


    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        close();
        return super.onUnbind(intent);
    }

    public boolean initialize() {
        if(bluetoothManager == null) {
            bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
            if(bluetoothManager == null) {
                Log.e(TAG,"CANNOT INITIALIZE BLUETOOTH");
                return false;
            }
        }bluetoothAdapter = bluetoothManager.getAdapter();
        if(bluetoothAdapter == null) {
            Log.e(TAG,"CANNOT FIND AN ADAPTER");
            return false;
        }return true;
    }

    public boolean connect(final String address) {
        Log.w(TAG,"CONNECT PROCESS INITIALIZED");
        if(bluetoothAdapter == null || address == null) {
            Log.e(TAG,"ADAPTER NOT INITIALIZED");
            return false;
        }
        //previously connected device, attempt to reconnect
        if(deviceAddress != null && deviceAddress.equals(address)
                &&bluetoothGatt != null) {
            Log.d(TAG, "TRYING TO USE EXISTING GATT");
            if(bluetoothGatt.connect()) {
                connectionState = STATE_CONNECTING;
                bluetoothGatt.connect();
                return true;
            } else
                return false;
        }

        final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
        if(device == null) {
            Log.e(TAG, "DEVICE NOT FOUND");
            return false;
        }
        bluetoothGatt = device.connectGatt(this, false, gattCallback);
        deviceAddress = address;
        connectionState = STATE_CONNECTING;
        return true;
    }

    public void disconnect() {
        if(bluetoothAdapter == null || bluetoothGatt == null) {
            Log.w(TAG, "BLUETOOTH NOT INITIALIZED");
            return;
        }
        bluetoothGatt.disconnect();
    }

    public void close() {
        if(bluetoothGatt == null)
            return;
        bluetoothGatt.close();
        bluetoothGatt = null;
    }

    public class LocalBinder extends Binder {
        DeviceService getService() {
          return DeviceService.this;
        }
    }

    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if(newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                connectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG,"CONNECTED TO GATT SERVER!");
                bluetoothGatt.discoverServices();
            } else if(newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                connectionState = STATE_DISCONNECTED;
                Log.i(TAG,"DISCONNECTED FROM GATT SERVER");
                broadcastUpdate(intentAction);
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            Log.e(TAG,"STATUS: " + String.valueOf(status));
            if (status == BluetoothGatt.GATT_SUCCESS)
                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {

            if (status == BluetoothGatt.GATT_SUCCESS)
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            Log.e(TAG,"CHAR CHANGED \n" + gatt.toString() + "\n" + characteristic.getUuid().toString() + "\n");
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                                          BluetoothGattCharacteristic characteristic,
                                          int status) {
            Log.e(TAG,"CHAR WROTE" + gatt.toString() + "\n" + characteristic.getUuid().toString() + "\n");
            if(status == BluetoothGatt.GATT_SUCCESS)
                broadcastUpdate(ACTION_DATA_WRITE, characteristic);
        }
    };

    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if(bluetoothAdapter == null || bluetoothGatt == null) {
            Log.e(TAG, "ADAPTER NOT INITIALIZED");
            return;
        }
        bluetoothGatt.readCharacteristic(characteristic);
    }

    public void writeCharacteristic(BluetoothGattCharacteristic characteristic, byte[] value) {
        if(bluetoothAdapter == null || bluetoothGatt == null) {
            Log.e(TAG, "ADAPTER NOT INITIALIZED");
            return;
        }
        characteristic.setValue(value);
        characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
        bluetoothGatt.writeCharacteristic(characteristic);
        System.out.println("Write value: " + value[0] + " on UUID: " + characteristic.getUuid().toString());
    }

    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
                                              boolean enabled) {
        if(bluetoothAdapter == null || bluetoothGatt == null) return;

        bluetoothGatt.setCharacteristicNotification(characteristic, enabled);

        if(GattUUIDs.containsUuid(characteristic.getUuid())) {
            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                    UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
//            BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(
//                    GattUUIDs.UUID_CLIENT_CHAR_CONFIG, BluetoothGattDescriptor.PERMISSION_WRITE |
//                    BluetoothGattDescriptor.PERMISSION_READ);

            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            bluetoothGatt.writeDescriptor(descriptor);

        }
    }

    public void setCharacteristicIndication(BluetoothGattCharacteristic characteristic,
                                            boolean enabled) {
        if(bluetoothAdapter ==null || bluetoothGatt == null) return;

        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
        bluetoothGatt.writeDescriptor(descriptor);

        bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    }

    private void broadcastUpdate(final String action) {
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    private void broadcastUpdate(final String action,
                                 final BluetoothGattCharacteristic characteristic) {
        final Intent intent = new Intent(action);
        final UUID uuid = characteristic.getUuid();
        Log.w(TAG,"BROADCAST UPDATE WITH ACTION: " + action);
        if(GattUUIDs.containsUuid(uuid)) {
            Log.e(TAG,"PASSOU AQUI");
            int flag = characteristic.getProperties();
            int format;

            if((flag & 0x01) != 0)
                format = BluetoothGattCharacteristic.FORMAT_UINT16;
            else
                format = BluetoothGattCharacteristic.FORMAT_UINT8;

            byte[] data = characteristic.getValue();

            if (GattUUIDs.UUID_IR_TEMPERATURE_MEASUREMENT.equals(uuid)) {
                float objectTemperature  = ((((float)data[1] * 256 + (float)data[0]) / (float)4)) * (float)0.03125;
                float ambientTemperature = ((((float)data[3] * 256 + (float)data[2]) / (float)4)) * (float)0.03125;

//                final int temp_data = characteristic.getIntValue(format, 1);
                intent.putExtra(EXTRA_DATA, String.format("%.2f %.2f", objectTemperature, ambientTemperature));
            } else if (GattUUIDs.UUID_IR_TEMPERATURE_CONFIG.equals(uuid)) {
                if (data[0] == 0)
                    intent.putExtra(EXTRA_DATA, "IR DISABLED");
                else
                    intent.putExtra(EXTRA_DATA, "IR ENABLED");
            } else if (GattUUIDs.UUID_IR_TEMPERATURE_PERIOD.equals(uuid))
                intent.putExtra(EXTRA_DATA, String.format("%d",data[0]*10));

            else if (GattUUIDs.UUID_OPTICAL_MEASUREMENT.equals(uuid)) {
                int m = (data[1] * 256 + data[0]) & 0x0FFF;
                int e = ((data[1] * 256 + data[0]) & 0xF000) >> 12;
                double lux = m * 0.01 * Math.pow(2.0,e);
                intent.putExtra(EXTRA_DATA, String.format("%.2f",lux));
            } else if (GattUUIDs.UUID_OPTICAL_CONFIG.equals(uuid)) {
                if(data[0] == 0)
                    intent.putExtra(EXTRA_DATA, "OPTICAL DISABLED");
                else
                    intent.putExtra(EXTRA_DATA, "OPTICAL ENABLED");
            } else if (GattUUIDs.UUID_OPTICAL_PERIOD.equals(uuid))
                intent.putExtra(EXTRA_DATA, String.format("%d",data[0] * 10));

            else if (GattUUIDs.UUID_MOVEMENT_MEASUREMENT.equals(uuid))
                intent.putExtra(EXTRA_DATA, String.format("%d %d %d %d %d %d %d %d %d",
                        (data[0] + data[1]*256),
                        (data[2] + data[3]*256),
                        (data[4] + data[5]*256),
                        (data[6] + data[7]*256),
                        (data[8] + data[9]*256),
                        (data[10] + data[11]*256),
                        (data[12] + data[13]*256),
                        (data[14] + data[15]*256),
                        (data[16] + data[17]*256)));
            else if (GattUUIDs.UUID_MOVEMENT_CONFIG.equals(uuid)) {
                if (data[0] == 0)
                    intent.putExtra(EXTRA_DATA, "MOVEMENT DISABLED");
                else
                    intent.putExtra(EXTRA_DATA, "MOVEMENT ENABLEd");
            } else if (GattUUIDs.UUID_MOVEMENT_PERIOD.equals(uuid))
                intent.putExtra(EXTRA_DATA, String.format("%d",data[0] * 10));

            else {
                if (data != null && data.length > 0) {
                    final StringBuilder stringBuilder = new StringBuilder(data.length);
                    for(byte byteChar : data)
                        stringBuilder.append(String.format("%02X ",byteChar));
                    intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
                }
            }
        }
        sendBroadcast(intent);
    }

    public List<BluetoothGattService> getSupportedGattServices() {
        if(bluetoothGatt == null) return null;

        return bluetoothGatt.getServices();
    }
}

这是我的设备控制:

import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;

import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * Created by alan on 2/23/16.
 */
public class DeviceControl extends AppCompatActivity {

    private final String TAG = DeviceControl.class.getSimpleName();

    private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacterics = new ArrayList<>();
    private BluetoothGattCharacteristic bluetoothGattCharacteristic;
    public static String ADDRESS;
    private DeviceService deviceService;
    private boolean connected = false;
    private TextView dataText;
    private Switch temperatureSwitch,
                   movementSwitch,
                   opticalSwitch;

    private final String LIST_NAME = "NAME";
    private final String LIST_UUID = "UUID";

    private final ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG,"ONSERVICECONNECTED");
            deviceService = ((DeviceService.LocalBinder)service).getService();
            if(!deviceService.initialize())
                finish();
            deviceService.connect(ADDRESS);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            deviceService = null;
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceBundle) {
        super.onCreate(savedInstanceBundle);
        setContentView(R.layout.activity_device_control);

        dataText = (TextView)findViewById(R.id.dataText);
        temperatureSwitch = (Switch)findViewById(R.id.temperatureSwitch);
        movementSwitch    = (Switch)findViewById(R.id.movementSwitch);
        opticalSwitch     = (Switch)findViewById(R.id.opticalSwitch);

        temperatureSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                if(isChecked && connected)
                    writeCharacteristic(GattUUIDs.UUID_IR_TEMPERATURE_CONFIG, true);
                else if(!isChecked && connected)
                    writeCharacteristic(GattUUIDs.UUID_IR_TEMPERATURE_CONFIG, false);
            }
        });

        Bundle extras = getIntent().getExtras();

        if(extras != null) {
            setTitle(extras.getString("title"));
            ADDRESS = extras.getString("address");

            Intent intent = new Intent(this, DeviceService.class);
            bindService(intent, serviceConnection, BIND_AUTO_CREATE);
        }
        registerReceiver(broadcastReceiver, makeIntentFilter());
    }

    public void writeCharacteristic(UUID toFind, boolean read) {
        BluetoothGattCharacteristic gattCharacteristic = null;
        byte[] enable = {(byte)0x01},
                disable = {(byte)0x00};
        for(int i = 0; i < mGattCharacterics.size(); i++) {
            for(int j = 0; j < mGattCharacterics.get(i).size(); j++) {
                if(mGattCharacterics.get(i).get(j).getUuid().equals(toFind))
                    gattCharacteristic = mGattCharacterics.get(i).get(j);
            }
        }
        if(gattCharacteristic != null) {
            if(read)
                deviceService.writeCharacteristic(gattCharacteristic, enable);
            else
                deviceService.writeCharacteristic(gattCharacteristic, disable);
            deviceService.setCharacteristicNotification(gattCharacteristic, true);
        } else
            Log.e(TAG,"NOTHING FOUND");


    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(broadcastReceiver, makeIntentFilter());
        Log.w(TAG,"REGISTER RECEIVER");

        if (deviceService != null) {
            final boolean result = deviceService.connect(ADDRESS);
            Log.d(TAG,"CONNECT RESULT = " + result);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(broadcastReceiver);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        deviceService.disconnect();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
        deviceService = null;
    }

    private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            Log.e(TAG,"BROADCAST ACTION"+action);
            switch (action) {
                case DeviceService.ACTION_GATT_CONNECTED:
                    connected = true;
                    break;
                case DeviceService.ACTION_GATT_DISCONNECTED:
                    connected = false;
                    break;
                case DeviceService.ACTION_GATT_SERVICES_DISCOVERED:
                    getGattServices(deviceService.getSupportedGattServices());
                    break;
                case DeviceService.ACTION_DATA_AVAILABLE:
                    displayData(intent.getStringExtra(DeviceService.EXTRA_DATA));
            }
        }
    };

    private void displayData(String data) {
        if(data != null)
            dataText.setText(data);
    }

    private void getGattServices(List<BluetoothGattService> gattServices) {
        if(gattServices == null) return;
        String uuid = null;
        ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<>();
        ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
                = new ArrayList<>();
        mGattCharacterics = new ArrayList<>();

        for (BluetoothGattService gattService : gattServices) {
            HashMap<String, String> currentServiceData = new HashMap<>();
            uuid = gattService.getUuid().toString();
            currentServiceData.put(LIST_NAME, GattAttributes.lookup(uuid, "UnknownService"));
            currentServiceData.put(LIST_UUID, uuid);
            gattServiceData.add(currentServiceData);

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

            for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                charas.add(gattCharacteristic);
                HashMap<String, String> currentCharaData = new HashMap<>();
                uuid = gattCharacteristic.getUuid().toString();
                currentCharaData.put(LIST_NAME, GattAttributes.lookup(uuid, "UnknownCharacteristic"));
                currentCharaData.put(LIST_UUID, uuid);
                gattCharacteristicGroupData.add(currentCharaData);
                //System.out.println("GATTCHAR\n\n" + gattCharacteristic.toString()+"\n");
            }
            mGattCharacterics.add(charas);
            gattCharacteristicData.add(gattCharacteristicGroupData);
        }
    }

    private static IntentFilter makeIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(DeviceService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(DeviceService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(DeviceService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(DeviceService.ACTION_DATA_AVAILABLE);
        return intentFilter;
    }
}

感谢您的关注。

0 个答案:

没有答案