zoukankan      html  css  js  c++  java
  • 蓝牙4.0 简单使用

    1.需要的权限:

     <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
        <uses-permission android:name="android.permission.BLUETOOTH"/>
        <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    View Code

    2.

    package com.hmsoft.bluetooth.le;
    
    import android.app.Activity;
    import android.app.ListActivity;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothManager;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ListView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import java.util.ArrayList;
    
    import com.example.bluetooth.le.R;
    
    /**
     * Activity for scanning and displaying available Bluetooth LE devices.
     */
    public class DeviceScanActivity extends ListActivity {
        private LeDeviceListAdapter mLeDeviceListAdapter;
        private BluetoothAdapter mBluetoothAdapter;
        private boolean mScanning;
    
        private static final int REQUEST_ENABLE_BT = 1;
        // Stops scanning after 10 seconds.
        private static final long SCAN_PERIOD = 10000;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getActionBar().setTitle(R.string.title_devices);
    
            // Use this check to determine whether BLE is supported on the device.  Then you can
            // selectively disable BLE-related features.
            if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
                Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
                finish();
            }
    
            // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
            // BluetoothAdapter through BluetoothManager.
            final BluetoothManager bluetoothManager =
                    (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();
    
            // Checks if Bluetooth is supported on the device.
            if (mBluetoothAdapter == null) {
                Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
                finish();
                return;
            }
            
            //Initializes list view adapter.
            mLeDeviceListAdapter = new LeDeviceListAdapter();
            setListAdapter(mLeDeviceListAdapter);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            if (!mScanning) {
                menu.findItem(R.id.menu_stop).setVisible(false);
                menu.findItem(R.id.menu_scan).setVisible(true);
                menu.findItem(R.id.menu_refresh).setActionView(null);
            } else {
                menu.findItem(R.id.menu_stop).setVisible(true);
                menu.findItem(R.id.menu_scan).setVisible(false);
                menu.findItem(R.id.menu_refresh).setActionView(
                        R.layout.actionbar_indeterminate_progress);
            }
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.menu_scan:
                    mLeDeviceListAdapter.clear();
                    scanLeDevice(true);
                    break;
                case R.id.menu_stop:
                    scanLeDevice(false);
                    break;
            }
            return true;
        }
    
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            // User chose not to enable Bluetooth.
            if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
                finish();
                return;
            }
            super.onActivityResult(requestCode, resultCode, data);
        }
        
        @Override
        protected void onResume() {
            super.onResume();
    
            // Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
            // fire an intent to display a dialog asking the user to grant permission to enable it.
            /*
            if (!mBluetoothAdapter.isEnabled()) {
                if (!mBluetoothAdapter.isEnabled()) {
                    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
                }
            }
            */
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            scanLeDevice(false);
            //mLeDeviceListAdapter.clear();
        }
    
        //打开连接界面
        @Override
        protected void onListItemClick(ListView l, View v, int position, long id) {
            final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
            if (device == null) return;
            final Intent intent = new Intent(this, DeviceControlActivity.class);
            intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
            intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
            if (mScanning) {
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                mScanning = false;
            }
            startActivity(intent);
        }
    
        private void scanLeDevice(final boolean enable) {
            if (enable) {
                // Stops scanning after a pre-defined scan period.
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if(mScanning)
                        {
                            mScanning = false;
                            mBluetoothAdapter.stopLeScan(mLeScanCallback);
                            invalidateOptionsMenu();
                        }
                    }
                }, SCAN_PERIOD);
    
                mScanning = true;
                //F000E0FF-0451-4000-B000-000000000000
                mLeDeviceListAdapter.clear();
                mHandler.sendEmptyMessage(1);
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
            invalidateOptionsMenu();
        }
        
        private static char findHex(byte b) {    
            int t = new Byte(b).intValue();    
            t = t < 0 ? t + 16 : t;    
              
            if ((0 <= t) &&(t <= 9)) {    
            return (char)(t + '0');    
            }    
              
            return (char)(t - 10 + 'A');    
            }  
        
        public static String ByteToString(byte[] bytes) {
              StringBuffer sb = new StringBuffer();
              //for (int i = 0; i < bytes.length && bytes[i] != (byte) 0; i++) {
              for (int i = 0; i < bytes.length; i++) {
               //sb.append((char) (bytes[i]));
               sb.append(findHex((byte)((bytes[i] & 0xf0) >> 4)));
               sb.append(findHex((byte)(bytes[i] & 0x0f)));
               
              }
              return sb.toString();
             }
    
        // Adapter for holding devices found through scanning.
        private class LeDeviceListAdapter extends BaseAdapter {
            private ArrayList<BluetoothDevice> mLeDevices;
            private LayoutInflater mInflator;
    
            public LeDeviceListAdapter() {
                super();
                mLeDevices = new ArrayList<BluetoothDevice>();
                mInflator = DeviceScanActivity.this.getLayoutInflater();
            }
    
            public void addDevice(BluetoothDevice device) {
                if(!mLeDevices.contains(device)) {
                    mLeDevices.add(device);
                }
            }
    
            public BluetoothDevice getDevice(int position) {
                return mLeDevices.get(position);
            }
            
            public void clear() {
                mLeDevices.clear();
            }
    
            @Override
            public int getCount() {
                return mLeDevices.size();
            }
    
            @Override
            public Object getItem(int i) {
                return mLeDevices.get(i);
            }
    
            @Override
            public long getItemId(int i) {
                return i;
            }
    
            @Override
            public View getView(int i, View view, ViewGroup viewGroup) {
                ViewHolder viewHolder;
                // General ListView optimization code.
                if (view == null) {
                    view = mInflator.inflate(R.layout.listitem_device, null);
                    viewHolder = new ViewHolder();
                    viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
                    viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
                    view.setTag(viewHolder);
                } else {
                    viewHolder = (ViewHolder) view.getTag();
                }
    
                BluetoothDevice device = mLeDevices.get(i);
                final String deviceName = device.getName();
                if (deviceName != null && deviceName.length() > 0)
                    viewHolder.deviceName.setText(deviceName);
                else
                    viewHolder.deviceName.setText(R.string.unknown_device);
                
                viewHolder.deviceAddress.setText(device.getAddress());
    
                return view;
            }
        }
    
        // Device scan callback.
        private BluetoothAdapter.LeScanCallback mLeScanCallback =
                new BluetoothAdapter.LeScanCallback() {
    
            @Override
            public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mLeDeviceListAdapter.addDevice(device);
                        mHandler.sendEmptyMessage(1);
                    }
                });
            }
        };
    
        static class ViewHolder {
            TextView deviceName;
            TextView deviceAddress;
        }
        
        // Hander
        public final Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case 1: // Notify change
                    mLeDeviceListAdapter.notifyDataSetChanged();
                    break;
                }
            }
        };
    }
    View Code

    3.

    package com.hmsoft.bluetooth.le;
    
    import com.example.bluetooth.le.R;
    
    import android.app.Activity;
    import android.bluetooth.BluetoothDevice;
    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.util.Log;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ScrollView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    
    /**
     * For a given BLE device, this Activity provides the user interface to connect, display data,
     * and display GATT services and characteristics supported by the device.  The Activity
     * communicates with {@code BluetoothLeService}, which in turn interacts with the
     * Bluetooth LE API.
     */
    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 mDataField;
        private String mDeviceName;
        private String mDeviceAddress;
        private BluetoothLeService mBluetoothLeService;
        private boolean mConnected = false;
        
        EditText edtSend;
        ScrollView svResult;
        Button btnSend;
    
        // 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();
                }
                
                Log.e(TAG, "mBluetoothLeService is okay");
                // 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)) {  //连接成功
                    Log.e(TAG, "Only gatt, just wait");
                } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { //断开连接
                    mConnected = false;
                    invalidateOptionsMenu();
                    btnSend.setEnabled(false);
                    clearUI();
                }else if(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) //可以开始干活了
                {
                    mConnected = true;
                    mDataField.setText("");
                    ShowDialog();
                    btnSend.setEnabled(true);
                    Log.e(TAG, "In what we need");
                    invalidateOptionsMenu();
                }else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { //收到数据
                    Log.e(TAG, "RECV DATA");
                    String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
                    if (data != null) {
                        if (mDataField.length() > 500)
                            mDataField.setText("");
                        mDataField.append(data); 
                        svResult.post(new Runnable() {
                            public void run() {
                                svResult.fullScroll(ScrollView.FOCUS_DOWN);
                            }
                        });
                    }
                }
            }
        };
    
        private void clearUI() {
            mDataField.setText(R.string.no_data);
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {                                        //初始化
            super.onCreate(savedInstanceState);
            setContentView(R.layout.gatt_services_characteristics);
    
            final Intent intent = getIntent();
            mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
            mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
    
            // Sets up UI references.
            mDataField = (TextView) findViewById(R.id.data_value);
            edtSend = (EditText) this.findViewById(R.id.edtSend);
            edtSend.setText("www.jnhuamao.cn");
            svResult = (ScrollView) this.findViewById(R.id.svResult);
            
            btnSend = (Button) this.findViewById(R.id.btnSend);
            btnSend.setOnClickListener(new ClickEvent());
            btnSend.setEnabled(false);
    
            getActionBar().setTitle(mDeviceName);
            getActionBar().setDisplayHomeAsUpEnabled(true);
            Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
            Log.d(TAG, "Try to bindService=" + bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE));
            
            registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
        }
    
        @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);
            unbindService(mServiceConnection);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //this.unregisterReceiver(mGattUpdateReceiver);
            //unbindService(mServiceConnection);
            if(mBluetoothLeService != null)
            {
                mBluetoothLeService.close();
                mBluetoothLeService = null;
            }
            Log.d(TAG, "We are in destroy");
        }
    
        @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:
                    if(mConnected)
                    {
                        mBluetoothLeService.disconnect();
                        mConnected = false;
                    }
                    onBackPressed();
                    return true;
            }
            return super.onOptionsItemSelected(item);
        }
        
        private void ShowDialog()
        {
            Toast.makeText(this, "连接成功,现在可以正常通信!", Toast.LENGTH_SHORT).show();
        }
    
     // 按钮事件
        class ClickEvent implements View.OnClickListener {
            @Override
            public void onClick(View v) {
                if (v == btnSend) {
                    if(!mConnected) return;
                    
                    if (edtSend.length() < 1) {
                        Toast.makeText(DeviceControlActivity.this, "请输入要发送的内容", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    mBluetoothLeService.WriteValue(edtSend.getText().toString());
                    
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    if(imm.isActive())
                        imm.hideSoftInputFromWindow(edtSend.getWindowToken(), 0);
                    //todo Send data
                }
            }
    
        }
        
        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);
            intentFilter.addAction(BluetoothDevice.ACTION_UUID);
            return intentFilter;
        }
    }
    View Code

    4.

    /*
     * Copyright (C) 2013 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.hmsoft.bluetooth.le;
    
    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;
    
    /**
     * Service for managing connection and data communication with a GATT server hosted on a
     * given Bluetooth LE device.
     */
    public class BluetoothLeService extends Service {
        private final static String TAG = BluetoothLeService.class.getSimpleName();
    
        private BluetoothManager mBluetoothManager;
        private BluetoothAdapter mBluetoothAdapter;
        private BluetoothGatt mBluetoothGatt;
    
        public final static String ACTION_GATT_CONNECTED =
                "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
        public final static String ACTION_GATT_DISCONNECTED =
                "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
        public final static String ACTION_GATT_SERVICES_DISCOVERED =
                "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
        public final static String ACTION_DATA_AVAILABLE =
                "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
        public final static String EXTRA_DATA =
                "com.example.bluetooth.le.EXTRA_DATA";
    
        public final static UUID UUID_NOTIFY =
                UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb");
        public final static UUID UUID_SERVICE =
            UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb");
        
        public BluetoothGattCharacteristic mNotifyCharacteristic;
        
        public void WriteValue(String strValue)
        {
            mNotifyCharacteristic.setValue(strValue.getBytes());
            mBluetoothGatt.writeCharacteristic(mNotifyCharacteristic);
        }
        
        public void findService(List<BluetoothGattService> gattServices)
        {
            Log.i(TAG, "Count is:" + gattServices.size());
            for (BluetoothGattService gattService : gattServices) 
            {
                Log.i(TAG, gattService.getUuid().toString());
                Log.i(TAG, UUID_SERVICE.toString());
                if(gattService.getUuid().toString().equalsIgnoreCase(UUID_SERVICE.toString()))
                {
                    List<BluetoothGattCharacteristic> gattCharacteristics =
                        gattService.getCharacteristics();
                    Log.i(TAG, "Count is:" + gattCharacteristics.size());
                    for (BluetoothGattCharacteristic gattCharacteristic :
                        gattCharacteristics) 
                    {
                        if(gattCharacteristic.getUuid().toString().equalsIgnoreCase(UUID_NOTIFY.toString()))
                        {
                            Log.i(TAG, gattCharacteristic.getUuid().toString());
                            Log.i(TAG, UUID_NOTIFY.toString());
                            mNotifyCharacteristic = gattCharacteristic;
                            setCharacteristicNotification(gattCharacteristic, true);
                            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
                            return;
                        }
                    }
                }
            }
        }
    
        // Implements callback methods for GATT events that the app cares about.  For example,
        // connection change and services discovered.
        private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                String intentAction;
                Log.i(TAG, "oldStatus=" + status + " NewStates=" + newState);
                if(status == BluetoothGatt.GATT_SUCCESS)
                {
                
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    intentAction = ACTION_GATT_CONNECTED;
                    
                    broadcastUpdate(intentAction);
                    Log.i(TAG, "Connected to GATT server.");
                    // Attempts to discover services after successful connection.
                    Log.i(TAG, "Attempting to start service discovery:" +
                            mBluetoothGatt.discoverServices());
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    intentAction = ACTION_GATT_DISCONNECTED;
                    mBluetoothGatt.close();
                    mBluetoothGatt = null;
                    Log.i(TAG, "Disconnected from GATT server.");
                    broadcastUpdate(intentAction);
                }
                }
            }
    
            @Override
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    Log.w(TAG, "onServicesDiscovered received: " + status);
                    findService(gatt.getServices());
                } else {
                    if(mBluetoothGatt.getDevice().getUuids() == null)
                    Log.w(TAG, "onServicesDiscovered received: " + status);
                }
            }
    
            @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) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
                Log.e(TAG, "OnCharacteristicWrite");
            }
            
            @Override
            public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
                                            int status)
            {
                Log.e(TAG, "OnCharacteristicWrite");
            }
            
            @Override
            public void onDescriptorRead(BluetoothGatt gatt,
                                             BluetoothGattDescriptor bd,
                                             int status) {
                Log.e(TAG, "onDescriptorRead");
            }
            
            @Override
            public void onDescriptorWrite(BluetoothGatt gatt,
                                             BluetoothGattDescriptor bd,
                                             int status) {
                Log.e(TAG, "onDescriptorWrite");
            }
            
            @Override
            public void onReadRemoteRssi(BluetoothGatt gatt, int a, int b)
            {
                Log.e(TAG, "onReadRemoteRssi");
            }
            
            @Override
            public void onReliableWriteCompleted(BluetoothGatt gatt, int a)
            {
                Log.e(TAG, "onReliableWriteCompleted");
            }
            
        };
    
        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);
    
            // This is special handling for the Heart Rate Measurement profile.  Data parsing is
            // carried out as per profile specifications:
            // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
                // For all other profiles, writes the data formatted in HEX.
            final byte[] data = characteristic.getValue();
            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) + "
    " + stringBuilder.toString());
                intent.putExtra(EXTRA_DATA, new String(data));
            }
            sendBroadcast(intent);
        }
    
        public class LocalBinder extends Binder {
            BluetoothLeService getService() {
                return BluetoothLeService.this;
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        @Override
        public boolean onUnbind(Intent intent) {
            // After using a given device, you should make sure that BluetoothGatt.close() is called
            // such that resources are cleaned up properly.  In this particular example, close() is
            // invoked when the UI is disconnected from the Service.
            close();
            return super.onUnbind(intent);
        }
    
        private final IBinder mBinder = new LocalBinder();
    
        /**
         * Initializes a reference to the local Bluetooth adapter.
         *
         * @return Return true if the initialization is successful.
         */
        public boolean initialize() {
            // For API level 18 and above, get a reference to BluetoothAdapter through
            // BluetoothManager.
            if (mBluetoothManager == null) {
                mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
                if (mBluetoothManager == null) {
                    Log.e(TAG, "Unable to initialize BluetoothManager.");
                    return false;
                }
            }
    
            mBluetoothAdapter = mBluetoothManager.getAdapter();
            if (mBluetoothAdapter == null) {
                Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
                return false;
            }
    
            return true;
        }
    
        /**
         * Connects to the GATT server hosted on the Bluetooth LE device.
         *
         * @param address The device address of the destination device.
         *
         * @return Return true if the connection is initiated successfully. The connection result
         *         is reported asynchronously through the
         *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
         *         callback.
         */
        public boolean connect(final String address) {
            if (mBluetoothAdapter == null || address == null) {
                Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
                return false;
            }
    /*
            // Previously connected device.  Try to reconnect.
            if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
                    && mBluetoothGatt != null) {
                Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
                if (mBluetoothGatt.connect()) {
                    mConnectionState = STATE_CONNECTING;
                    return true;
                } else {
                    return false;
                }
            }
    */
            BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
            if (device == null) {
                Log.w(TAG, "Device not found.  Unable to connect.");
                return false;
            }
            // We want to directly connect to the device, so we are setting the autoConnect
            // parameter to false.
            if(mBluetoothGatt != null)
            {
                mBluetoothGatt.close();
                mBluetoothGatt = null;
            }
            mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
            //mBluetoothGatt.connect();
            
            Log.d(TAG, "Trying to create a new connection.");
            return true;
        }
    
        /**
         * Disconnects an existing connection or cancel a pending connection. The disconnection result
         * is reported asynchronously through the
         * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
         * callback.
         */
        public void disconnect() {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.w(TAG, "BluetoothAdapter not initialized");
                return;
            }
            mBluetoothGatt.disconnect();
        }
    
        /**
         * After using a given BLE device, the app must call this method to ensure resources are
         * released properly.
         */
        public void close() {
            if (mBluetoothGatt == null) {
                return;
            }
            mBluetoothGatt.close();
            mBluetoothGatt = null;
        }
    
        /**
         * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
         * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
         * callback.
         *
         * @param characteristic The characteristic to read from.
         */
        public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.w(TAG, "BluetoothAdapter not initialized");
                return;
            }
            mBluetoothGatt.readCharacteristic(characteristic);
        }
    
        /**
         * Enables or disables notification on a give characteristic.
         *
         * @param characteristic Characteristic to act on.
         * @param enabled If true, enable notification.  False otherwise.
         */
        public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
                                                  boolean enabled) {
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.w(TAG, "BluetoothAdapter not initialized");
                return;
            }
            mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    /*
            // This is specific to Heart Rate Measurement.
            if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
                BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                        UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                mBluetoothGatt.writeDescriptor(descriptor);
            }
            */
        }
    
        /**
         * Retrieves a list of supported GATT services on the connected device. This should be
         * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
         *
         * @return A {@code List} of supported services.
         */
        public List<BluetoothGattService> getSupportedGattServices() {
            if (mBluetoothGatt == null) return null;
    
            return mBluetoothGatt.getServices();
        }
    }
    View Code

    5.

    // 检查设备是否支持BLE
     if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
                Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
                finish();
            }
    
            // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
            // BluetoothAdapter through BluetoothManager.
    // 获取 BluetoothAdapter
            final BluetoothManager bluetoothManager =
                    (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetoothAdapter = bluetoothManager.getAdapter();
    
            // Checks if Bluetooth is supported on the device.
            if (mBluetoothAdapter == null) {
                Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
                finish();
                return;
            }

    开启蓝牙:

    if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
       Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
       startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

    发现BLE设备:

    为了发现BLE设备,使用startLeScan())方法。这个方法需要一个参数BluetoothAdapter.LeScanCallback。你必须实现它的回调函数,那就是返回的扫描结果。因为扫描非常消耗电量,你应当遵守以下准则:

    只要找到所需的设备,停止扫描。

    不要在循环里扫描,并且对扫描设置时间限制。以前可用的设备可能已经移出范围,继续扫描消耗电池电量。

    <1> boolean

      startLeScan(BluetoothAdapter.LeScanCallback callback)
    Starts a scan for Bluetooth LE devices.

    <2>boolean

      startLeScan(UUID[] serviceUuids, BluetoothAdapter.LeScanCallback callback)
    Starts a scan for Bluetooth LE devices, looking for devices that advertise given services.

    <3>interface

      BluetoothAdapter.LeScanCallback Callback interface used to deliver LE scan results. 

    1.

        private static final long SCAN_PERIOD = 10000;
        ...
        private void scanLeDevice(final boolean enable) {
            if (enable) {
                // 经过预定扫描期后停止扫描
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mScanning = false;
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    }
                }, SCAN_PERIOD);
                mScanning = true;
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
            ...
        }
    ...
    }
    View Code

    2.调用startLeScan(UUID[], BluetoothAdapter.LeScanCallback)),需要提供你的app支持的GATT services的UUID对象数组。

    作为BLE扫描结果的接口,下面是BluetoothAdapter.LeScanCallback的实现。

    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi,
                byte[] scanRecord) {
            runOnUiThread(new Runnable() {
               @Override
               public void run() {
                   mLeDeviceListAdapter.addDevice(device);
                   mLeDeviceListAdapter.notifyDataSetChanged();
               }
           });
       }
    };
    View Code

    3.

    public boolean connect(final String address) {
            if (mBluetoothAdapter == null || address == null) {
                Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
                return false;
            }
    /*
            // Previously connected device.  Try to reconnect.
            if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
                    && mBluetoothGatt != null) {
                Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
                if (mBluetoothGatt.connect()) {
                    mConnectionState = STATE_CONNECTING;
                    return true;
                } else {
                    return false;
                }
            }
    */
            BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
            if (device == null) {
                Log.w(TAG, "Device not found.  Unable to connect.");
                return false;
            }
            // We want to directly connect to the device, so we are setting the autoConnect
            // parameter to false.
            if(mBluetoothGatt != null)
            {
                mBluetoothGatt.close();
                mBluetoothGatt = null;
            }
            mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
            //mBluetoothGatt.connect();
            
            Log.d(TAG, "Trying to create a new connection.");
            return true;
        }

    <暂存>

    今天多一点积累,明天少一分烦恼
  • 相关阅读:
    文章块引用模版
    悬停工具提示
    各个知识点
    Github Fork 缎带.html
    css重置样式
    暗灰色的圆形按钮.html
    css中的居中的方法
    display:table的几个用法 块级子元素垂直居中
    <meta>标签中http-equiv属性的属性值X-UA-Compatible详解
    jQuery难学是因为什么?
  • 原文地址:https://www.cnblogs.com/galibujianbusana/p/5915296.html
Copyright © 2011-2022 走看看