Android应用蓝牙低功耗

时间:2015-02-25 12:21:54

标签: android bluetooth

美好的一天!我对Android应用程序开发很新。我正在BLE中制作一个简单的项目,我正在开发一个应用程序,当我按下BLE设备按钮时,它会自动发送短信。我已经完成了发送SMSmessage部分代码的工作。我唯一的问题是,当按钮从0推送到1时,如何扫描我的BLE设备并获得该特性的值?按下按钮时,我只需要获得该值。

/ **  *由戴夫史密斯创作  * Double Encore,Inc。  * 主要活动  * /

/ *这是我尝试编辑的代码,只是为了在按下按钮时从HUMIDITY_DATA_CHAR获取值1。 抱歉很长的代码只是为了通过按下按钮获得一个简单的1值。 * /

public class MainActivity extends Activity implements BluetoothAdapter.LeScanCallback {
private static final String TAG = "BluetoothGattActivity";

private static final String DEVICE_NAME = "Light";


private static final UUID HUMIDITY_SERVICE = UUID.fromString("29e70001-9227-e097-3473-09a5cc69a43a");
private static final UUID HUMIDITY_DATA_CHAR = UUID.fromString("29e70002-9227-e097-3473-09a5cc69a43a");

/* Client Configuration Descriptor */
private static final UUID CONFIG_DESCRIPTOR = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb");


private BluetoothAdapter mBluetoothAdapter;
private SparseArray<BluetoothDevice> mDevices;

private BluetoothGatt mConnectedGatt;

private TextView mTemperature, mHumidity, mPressure;

private ProgressDialog mProgress;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setContentView(R.layout.activity_main);
    setProgressBarIndeterminate(true);

    /*
     * We are going to display the results in some text fields
     */
    mTemperature = (TextView) findViewById(R.id.text_temperature);
    mHumidity = (TextView) findViewById(R.id.text_humidity);
    mPressure = (TextView) findViewById(R.id.text_pressure);

    /*
     * Bluetooth in Android 4.3 is accessed via the BluetoothManager, rather than
     * the old static BluetoothAdapter.getInstance()
     */
    BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
    mBluetoothAdapter = manager.getAdapter();

    mDevices = new SparseArray<BluetoothDevice>();

    /*
     * A progress dialog will be needed while the connection process is
     * taking place
     */
    mProgress = new ProgressDialog(this);
    mProgress.setIndeterminate(true);
    mProgress.setCancelable(false);
}

@Override
protected void onResume() {
    super.onResume();
    /*
     * We need to enforce that Bluetooth is first enabled, and take the
     * user to settings to enable it if they have not done so.
     */
    if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
        //Bluetooth is disabled
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivity(enableBtIntent);
        finish();
        return;
    }

    /*
     * Check for Bluetooth LE Support.  In production, our manifest entry will keep this
     * from installing on these devices, but this will allow test devices or other
     * sideloads to report whether or not the feature exists.
     */
    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
        Toast.makeText(this, "No LE Support.", Toast.LENGTH_SHORT).show();
        finish();
        return;
    }

    clearDisplayValues();
}

@Override
protected void onPause() {
    super.onPause();
    //Make sure dialog is hidden
    mProgress.dismiss();
    //Cancel any scans in progress
    mHandler.removeCallbacks(mStopRunnable);
    mHandler.removeCallbacks(mStartRunnable);
    mBluetoothAdapter.stopLeScan(this);
}

@Override
protected void onStop() {
    super.onStop();
    //Disconnect from any active tag connection
    if (mConnectedGatt != null) {
        mConnectedGatt.disconnect();
        mConnectedGatt = null;
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Add the "scan" option to the menu
    getMenuInflater().inflate(R.menu.main, menu);
    //Add any device elements we've discovered to the overflow menu
    for (int i=0; i < mDevices.size(); i++) {
        BluetoothDevice device = mDevices.valueAt(i);
        menu.add(0, mDevices.keyAt(i), 0, device.getName());
    }

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_scan:
            mDevices.clear();
            startScan();
            return true;
        default:
            //Obtain the discovered device to connect with
            BluetoothDevice device = mDevices.get(item.getItemId());
            Log.i(TAG, "Connecting to "+device.getName());
            /*
             * Make a connection with the device using the special LE-specific
             * connectGatt() method, passing in a callback for GATT events
             */
            mConnectedGatt = device.connectGatt(this, false, mGattCallback);
            //Display progress UI
            mHandler.sendMessage(Message.obtain(null, MSG_PROGRESS, "Connecting to "+device.getName()+"..."));
            return super.onOptionsItemSelected(item);
    }
}

private void clearDisplayValues() {
    mTemperature.setText("---");
    mHumidity.setText("---");
    mPressure.setText("---");
}


private Runnable mStopRunnable = new Runnable() {
    @Override
    public void run() {
        stopScan();
    }
};
private Runnable mStartRunnable = new Runnable() {
    @Override
    public void run() {
        startScan();
    }
};

private void startScan() {
    mBluetoothAdapter.startLeScan(this);
    setProgressBarIndeterminateVisibility(true);

    mHandler.postDelayed(mStopRunnable, 2500);
}

private void stopScan() {
    mBluetoothAdapter.stopLeScan(this);
    setProgressBarIndeterminateVisibility(false);
}

/* BluetoothAdapter.LeScanCallback */

@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
    Log.i(TAG, "New LE Device: " + device.getName() + " @ " + rssi);
    /*
     * We are looking for SensorTag devices only, so validate the name
     * that each device reports before adding it to our collection
     */
    if (DEVICE_NAME.equals(device.getName())) {
        mDevices.put(device.hashCode(), device);
        //Update the overflow menu
        invalidateOptionsMenu();
    }
}

/*
 * In this callback, we've created a bit of a state machine to enforce that only
 * one characteristic be read or written at a time until all of our sensors
 * are enabled and we are registered to get notifications.
 */

private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

    /* State Machine Tracking */
    private int mState = 0;

    private void reset() { mState = 0; }

    private void advance() { mState++; }

    /*
     * Send an enable command to each sensor by writing a configuration
     * characteristic.  This is specific to the SensorTag to keep power
     * low by disabling sensors you aren't using.
     */

    private void enableNextSensor(BluetoothGatt gatt) {
        BluetoothGattCharacteristic characteristic;
        switch (mState) {
    //        case 0:
    //            Log.d(TAG, "Enabling pressure cal");
    //            characteristic = gatt.getService(PRESSURE_SERVICE)
    //                    .getCharacteristic(PRESSURE_CONFIG_CHAR);
    //            characteristic.setValue(new byte[] {0x00});
    //            break;
    //        case 1:
    //            Log.d(TAG, "Enabling pressure");
    //            characteristic = gatt.getService(PRESSURE_SERVICE)
    //                    .getCharacteristic(PRESSURE_CONFIG_CHAR);
    //            characteristic.setValue(new byte[] {0x00});
    //            break;
            case 0:
                Log.d(TAG, "Enabling humidity");
                characteristic = gatt.getService(HUMIDITY_SERVICE)
                        .getCharacteristic(HUMIDITY_CONFIG_CHAR);
                characteristic.setValue(new byte[] {0x00});
                break;
            default:
                mHandler.sendEmptyMessage(MSG_DISMISS);
                Log.i(TAG, "All Sensors Enabled");
                return;
        }

        gatt.writeCharacteristic(characteristic);
    }

    /*
     * Read the data characteristic's value for each sensor explicitly
     */
    private void readNextSensor(BluetoothGatt gatt) {
        BluetoothGattCharacteristic characteristic;
        switch (mState) {
    //        case 0:
    //            Log.d(TAG, "Reading pressure cal");
    //            characteristic = gatt.getService(PRESSURE_SERVICE)
    //                    .getCharacteristic(PRESSURE_CAL_CHAR);
    //            break;
    //        case 1:
    //            Log.d(TAG, "Reading pressure");
    //            characteristic = gatt.getService(PRESSURE_SERVICE)
    //                    .getCharacteristic(PRESSURE_DATA_CHAR);
    //            break;
            case 0:
                Log.d(TAG, "Reading humidity");
                characteristic = gatt.getService(HUMIDITY_SERVICE)
                        .getCharacteristic(HUMIDITY_DATA_CHAR);
                break;
            default:
                mHandler.sendEmptyMessage(MSG_DISMISS);
                Log.i(TAG, "All Sensors Enabled");
                return;
        }
        gatt.readCharacteristic(characteristic);
    }

    /*
     * Enable notification of changes on the data characteristic for each sensor
     * by writing the ENABLE_NOTIFICATION_VALUE flag to that characteristic's
     * configuration descriptor.
     */
    private void setNotifyNextSensor(BluetoothGatt gatt) {
        BluetoothGattCharacteristic characteristic;
        switch (mState) {
    //        case 0:
    //            Log.d(TAG, "Set notify pressure cal");
    //            characteristic = gatt.getService(PRESSURE_SERVICE)
    //                    .getCharacteristic(PRESSURE_CAL_CHAR);
    //            break;
    //        case 1:
    //            Log.d(TAG, "Set notify pressure");
    //            characteristic = gatt.getService(PRESSURE_SERVICE)
    //                    .getCharacteristic(PRESSURE_DATA_CHAR);
    //            break;
            case 0:
                Log.d(TAG, "Set notify humidity");
                characteristic = gatt.getService(HUMIDITY_SERVICE)
                        .getCharacteristic(HUMIDITY_DATA_CHAR);
                break;
            default:
                mHandler.sendEmptyMessage(MSG_DISMISS);
                Log.i(TAG, "All Sensors Enabled");
                return;
        }

        //Enable local notifications
        gatt.setCharacteristicNotification(characteristic, true);
        //Enabled remote notifications
        BluetoothGattDescriptor desc = characteristic.getDescriptor(CONFIG_DESCRIPTOR);
        desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        gatt.writeDescriptor(desc);
    }


    ////////////////////////
    /* OK NO NEED TO ALTER*/
    ///////////////////////
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        Log.d(TAG, "Connection State Change: "+status+" -> "+connectionState(newState));
        if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
            /*
             * Once successfully connected, we must next discover all the services on the
             * device before we can read and write their characteristics.
             */
            gatt.discoverServices();
            mHandler.sendMessage(Message.obtain(null, MSG_PROGRESS, "Discovering Services..."));
        } else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED) {
            /*
             * If at any point we disconnect, send a message to clear the weather values
             * out of the UI
             */
            mHandler.sendEmptyMessage(MSG_CLEAR);
        } else if (status != BluetoothGatt.GATT_SUCCESS) {
            /*
             * If there is a failure at any stage, simply disconnect
             */
            gatt.disconnect();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        Log.d(TAG, "Services Discovered: "+status);
        mHandler.sendMessage(Message.obtain(null, MSG_PROGRESS, "Enabling Sensors..."));
        /*
         * With services discovered, we are going to reset our state machine and start
         * working through the sensors we need to enable
         */
        BluetoothGattCharacteristic characteristic;
        characteristic = gatt.getService(HUMIDITY_SERVICE).getCharacteristic(HUMIDITY_DATA_CHAR);
        mHumidity.setText(String.valueOf(characteristic));
        reset();
     //  enableNextSensor(gatt);
    //fake      readNextSensor(gatt);
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        //For each read, pass the data up to the UI thread to update the display
        if (HUMIDITY_DATA_CHAR.equals(characteristic.getUuid())) {
            mHandler.sendMessage(Message.obtain(null, MSG_HUMIDITY, characteristic));
        }

        //After reading the initial value, next we enable notifications
        setNotifyNextSensor(gatt);
    }

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        //After writing the enable flag, next we read the initial value
    //    readNextSensor(gatt);
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        /*
         * After notifications are enabled, all updates from the device on characteristic
         * value changes will be posted here.  Similar to read, we hand these up to the
         * UI thread to update the display.
         */

        if (HUMIDITY_DATA_CHAR.equals(characteristic.getUuid())) {
            mHandler.sendMessage(Message.obtain(null, MSG_HUMIDITY, characteristic));
        }

    }

    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        //Once notifications are enabled, we move to the next sensor and start over with enable
        advance();
         readNextSensor(gatt);
    }

    @Override
    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
        Log.d(TAG, "Remote RSSI: "+rssi);
    }

    private String connectionState(int status) {
        switch (status) {
            case BluetoothProfile.STATE_CONNECTED:
                return "Connected";
            case BluetoothProfile.STATE_DISCONNECTED:
                return "Disconnected";
            case BluetoothProfile.STATE_CONNECTING:
                return "Connecting";
            case BluetoothProfile.STATE_DISCONNECTING:
                return "Disconnecting";
            default:
                return String.valueOf(status);
        }
    }
};

/*
 * We have a Handler to process event results on the main thread
 */
private static final int MSG_HUMIDITY = 101;
private static final int MSG_PROGRESS = 201;
private static final int MSG_DISMISS = 202;
private static final int MSG_CLEAR = 301;
private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        BluetoothGattCharacteristic characteristic;
        switch (msg.what) {
            case MSG_HUMIDITY:
                characteristic = (BluetoothGattCharacteristic) msg.obj;
                if (characteristic.getValue() == null) {
                    Log.w(TAG, "Error obtaining humidity value");
                    return;
                }
                updateHumidityValues(characteristic);
                break;
            case MSG_PROGRESS:
                mProgress.setMessage((String) msg.obj);
                if (!mProgress.isShowing()) {
                    mProgress.show();
                }
                break;
            case MSG_DISMISS:
                mProgress.hide();
                break;
            case MSG_CLEAR:
                clearDisplayValues();
                break;
        }
    }
};

/* Methods to extract sensor data and update the UI */

//放什么?

private void updateHumidityValues(BluetoothGattCharacteristic characteristic) {
  double humidity = SensorTagData.extractHumidity(characteristic);
  mHumidity.setText(String.valueOf(characteristic));

   mHumidity.setText(String.format("%.0f%%", humidity));
 }

}

0 个答案:

没有答案