• Android 蓝牙4.0的连接和通讯


    1.加入权限

     <uses-sdk android:minSdkVersion="18"
            android:targetSdkVersion="18"/>
        <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"/>

    2.蓝牙服务

    /*
     * 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 myapplication.com.myappforble.activity;
    
    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 {
            public 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();
        }
    }

    3.连接通讯

    package myapplication.com.myappforble;
    
    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.IBinder;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.Button;
    import android.widget.ScrollView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import myapplication.com.myappforble.activity.BluetoothLeService;
    
    
    public class MainActivity extends Activity {
    
        TextView textView_show;
        private boolean mConnected = false;
        Button button_send,button_lianjie;
        private String mDeviceName;
        private String mDeviceAddress;
        private static final String TAG = "MainActivity";
        private BluetoothLeService mBluetoothLeService;
    
    
        /**
         *
         * */
    
        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;
            }
        };
    
        /***
         *
         * */
        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();
                    button_send.setEnabled(false);
                }else if(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action))
                {
                    mConnected = true;
                    button_send.setEnabled(true);
                    ShowDialog();
                    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 (textView_show.getText().toString().length() <500) textView_show.append(data); } } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); mDeviceName = "NDCT-T0001"; //这里是蓝牙的名称 mDeviceAddress = "04:A3:16:A6:FE:FE"; // 蓝牙地址 Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); Log.d(TAG, "Try to bindService=" + bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE)); registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); } public void init(){ textView_show= (TextView) findViewById(R.id.textView_show); button_lianjie= (Button) findViewById(R.id.button_lianjian); button_send= (Button) findViewById(R.id.button_send);
          // 连接蓝牙 button_lianjie.setOnClickListener(
    new View.OnClickListener() { @Override public void onClick(View v) { mBluetoothLeService.connect(mDeviceAddress); } }); /** * 发送 * */ button_send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(!mConnected) return; mBluetoothLeService.WriteValue("12345678"); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); } }); } private void ShowDialog() { Toast.makeText(this, "开始通讯吧", Toast.LENGTH_SHORT).show(); } 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; } @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"); } }

    4.主布局2个按钮,一个textView

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="myapplication.com.myappforble.MainActivity">
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:text=""
            android:id="@+id/textView_show"
            android:textColor="@color/hei"/>
        <LinearLayout
            android:layout_marginLeft="20dp"
            android:layout_marginTop="40dp"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:orientation="horizontal">
        <Button
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="连接"
            android:textColor="@color/hei"
            android:id="@+id/button_lianjian" />
    
        <Button
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="发送"
            android:id="@+id/button_send"
            android:textColor="@color/hei"
            android:layout_marginStart="43dp"
            />
    
        </LinearLayout>
    </LinearLayout>

    实现效果图:发送的数据写死了,可以修改。

    <压缩包:蓝牙4.0连接通讯(不含搜索)>


    http://pan.baidu.com/share/link?shareid=3842796160&uk=3608711668

    今天多一点积累,明天少一分烦恼
  • 相关阅读:
    5.2 i++
    5.1 赋值语句
    Implement Queue using Stacks
    Binary Tree Paths
    Single Number III
    Ugly Number
    SurfaceHolder.Callback
    intellj(idea) 编译项目时在warnings 页签框里 报 “xxx包不存在” 或 “找不到符号” 或 “未结束的字符串字面值” 或 “需要)” 或 “需要;”等错误提示
    Hibernate添加日志--log4j
    java实现网页验证码
  • 原文地址:https://www.cnblogs.com/galibujianbusana/p/6322344.html
Copyright © 2020-2023  润新知