android6.0手机蓝牙与ble蓝牙模块通信

好久没有写博客了,因为最近一直在家浪,今天就来记录一下这几天来学校学到的东西(其实在本科就已经开始靴子了,只是还没完全弄明白),以便以后忘了回来看看,也希望对搜索并阅读本文章的朋友有所帮助。

本科毕设做的东西是“基于安卓系统的无人插秧机监控平台”,零基础学习,经过两个月的奋斗终于做的差不多了,遗憾的是没有将它继续完善投入使用,因为是本科学校的项目,毕业将到现在的学校来学习了。本科毕业之际没有事做就学习了一些其他自己感兴趣的东西:手机蓝牙与单片机端的蓝牙模块进行通信。相信学安卓的朋友也都做过这方面的实验。

我是控制出生,学安卓只是顺应潮流,现在很多项目都和安卓APP有关,不然都显得很low。于是自己开启了学习蓝牙之路。参考了很多书籍也搜索了很多网上的资料,但是始终没有搞清楚。于是就淘宝就买了一个淘宝的蓝牙模块(带有APP基本源码),本来就不是计算机出生,所以只能用这种方方式来学习:借鉴别人的代码,读懂并且能自己写出来,并且按照自己的需求进行开发。

唠叨了很多,下面开始步入正题。

****工程基本框架****

android6.0手机蓝牙与ble蓝牙模块通信_第1张图片

如图,工程的基本框架主要如图。两个活动和一个服务。MainActivity是主活动,对应的布局是activity_main.xml(图2),在此界面定义了一个按钮和一个ListView(对应listitem.xml,按钮用于启动扫描或停止扫描蓝牙设备,ListView用于显示扫描到的蓝牙设备的相关信息。Ble_Activity是另一个活动,是和扫描到的蓝牙设备进行连接后进入的界面,在此界面与连接的蓝牙设备进行收发数据的通信,其对应的布局文件是ble_activity.xml

ble_activity.xml的总体结构如题6,其他细节部分参看代码。ble_activity.xml的第一部分是图3,用于实时显示连接状态;第二部分用于显示接收到来自单片机端发送过来的数据;第三部分是四个按钮,按钮用于启动数据发送线程。BluetoothService顾名思义就是蓝牙服务,用于负责在后台实现蓝牙的连接,数据的发送接受。这就是工程的大体框架,下面细致介绍分别在两个活动和一个服务需要做哪些事情。

****MainActivity****

    在这里主要进行蓝牙的扫描,当点击扫描到的蓝牙模块时进入Ble_Activity,并且将蓝牙的先关信息传入Ble_Activity,以便与目标蓝牙模块进行连接。

****Ble_Activity****

    当进入该活动时首先接收MainActivity传来的蓝牙信息,然后绑定服务,在绑定服务时与蓝牙模块进行连接,之后就可以利用服务可以和蓝牙模块进行数据传输了。

****BluetoothService****

在这里主要是进行蓝牙的连接、数据的发送与接收。

****权限申明****

AndroidManifest.xml文件中进行相关申明。查看代码:

注意:

 

大致的框架与实现如上所述,具体查看以下代码:

**********************************1AndroidManifest.xml*************************



    package="com.example.bluetoothrobot"
    android:versionCode="1"
    android:versionName="1.2" >

    
    
    

    
    

    

    
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
            android:name=".MainActivity"
            android:label="@string/app_name" >
            
                

                
            
        
        
            android:name=".Ble_Activity">

        
    

************************************2MainActivity.java*************************

package com.example.bluetoothrobot;

import java.util.ArrayList;

import android.app.Activity;
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.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

//import com.example.bluetoothrobot.Ble_Activity;

/**
 * 特别说明:HC_BLE助手是广州汇承信息科技有限公司独自研发的手机APP,方便用户调试08蓝牙模块。
 * 本软件只能支持安卓版本4.3并且有蓝牙4.0的手机使用。
 * 另外对于自家的0506模块,要使用另外一套蓝牙2.0的手机APP,用户可以在汇承官方网的下载中心自行下载。
 * 本软件提供代码和注释,免费给购买汇承08模块的用户学习和研究,但不能用于商业开发,最终解析权在广州汇承信息科技有限公司。
 * **/
/**
 * @Description: TODO类实现打开蓝牙、扫描蓝牙>
 * @author 广州汇承信息科技有限公司
 * @data: 2014-10-12 上午10:28:18
 * @version: V1.0
 */
public class MainActivity extends Activity implements OnClickListener {
   // 扫描蓝牙按钮
   private Button scan_btn;
   // 蓝牙适配器
   BluetoothAdapter mBluetoothAdapter;
   // 蓝牙信号强度
   private ArrayList rssis;
   // 自定义Adapter
   LeDeviceListAdapter mleDeviceListAdapter;
   // listview显示扫描到的蓝牙信息
   ListView lv;
   // 描述扫描蓝牙的状态
   private boolean mScanning;
   private boolean scan_flag;
   private Handler mHandler;
   int REQUEST_ENABLE_BT = 1;
   // 蓝牙扫描时间
   private static final long SCAN_PERIOD = 10000;

   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      // 初始化控件
      init();
      // 初始化蓝牙
      init_ble();
      scan_flag = true;
      // 自定义适配器
      mleDeviceListAdapter = new LeDeviceListAdapter();
      // listview指定适配器
      lv.setAdapter(mleDeviceListAdapter);

      /* listview点击函数 */
      lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
      {

         @Override
         public void onItemClick(AdapterView arg0, View v, int position,
                           long id)
         {
            // TODO Auto-generated method stub
            final BluetoothDevice device = mleDeviceListAdapter
                  .getDevice(position);
            if (device == null)
               return;
            final Intent intent = new Intent(MainActivity.this,
                  Ble_Activity.class);//活动切换
            intent.putExtra(Ble_Activity.EXTRAS_DEVICE_NAME,
                  device.getName());//活动间传递意图参数
            intent.putExtra(Ble_Activity.EXTRAS_DEVICE_ADDRESS,
                  device.getAddress());//活动间传递意图参数
            intent.putExtra(Ble_Activity.EXTRAS_DEVICE_RSSI,
                  rssis.get(position).toString());//活动间传递意图参数
            if (mScanning)
            {
               /* 停止扫描设备 */
               mBluetoothAdapter.stopLeScan(mLeScanCallback);
               mScanning = false;
            }

            try
            {
               // 启动Ble_Activity
               startActivity(intent);
            } catch (Exception e)
            {
               e.printStackTrace();
               // TODO: handle exception
            }

         }
      });

   }

   /**
    * @Title: init
    * @Description: TODO(初始化UI控件)
    * @param
    * @return void
    * @throws
    */
   private void init()
   {
      scan_btn = (Button) this.findViewById(R.id.scan_dev_btn);
      scan_btn.setOnClickListener(this);
      lv = (ListView) this.findViewById(R.id.lv);
      mHandler = new Handler();
   }

   /**
    * @Title: init_ble
    * @Description: TODO(初始化蓝牙)
    * @param
    * @return void
    * @throws
    */
   private void init_ble()
   {
      // 手机硬件支持蓝牙
      if (!getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_BLUETOOTH_LE))
      {
         Toast.makeText(this, "不支持BLE", Toast.LENGTH_SHORT).show();
         finish();
      }
      // Initializes Bluetooth adapter.
      // 获取手机本地的蓝牙适配器
      final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
      mBluetoothAdapter = bluetoothManager.getAdapter();
      // 打开蓝牙权限
      if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled())
      {
         Intent enableBtIntent = new Intent(
               BluetoothAdapter.ACTION_REQUEST_ENABLE);
         startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
      }

   }

   /*
    * 按钮响应事件
    */
   @Override
   public void onClick(View v)
   {
      // TODO Auto-generated method stub

      if (scan_flag)
      {
         mleDeviceListAdapter = new LeDeviceListAdapter();
         lv.setAdapter(mleDeviceListAdapter);
         scanLeDevice(true);
      } else
      {

         scanLeDevice(false);
         scan_btn.setText("扫描设备");
      }
   }

   /**
    * @Title: scanLeDevice
    * @Description: TODO(扫描蓝牙设备 )
    * @param enable
    *            (扫描使能,true:扫描开始,false:扫描停止)
    * @return void
    * @throws
    */
   private void scanLeDevice(final boolean enable)
   {
      if (enable)
      {
         // Stops scanning after a pre-defined scan period.
         mHandler.postDelayed(new Runnable()
         {
            @Override
            public void run()
            {
               mScanning = false;
               scan_flag = true;
               scan_btn.setText("扫描设备");
               Log.i("SCAN", "stop.....................");
               mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
         }, SCAN_PERIOD);
         /* 开始扫描蓝牙设备,带mLeScanCallback 回调函数 */
         Log.i("SCAN", "begin.....................");
         mScanning = true;
         scan_flag = false;
         scan_btn.setText("停止扫描");
         mBluetoothAdapter.startLeScan(mLeScanCallback);
      } else
      {
         Log.i("Stop", "stoping................");
         mScanning = false;
         mBluetoothAdapter.stopLeScan(mLeScanCallback);
         scan_flag = true;
      }

   }

   /**
    * 蓝牙扫描回调函数 实现扫描蓝牙设备,回调蓝牙BluetoothDevice,可以获取name MAC等信息
    *
    * **/
   private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback()
   {

      @Override
      public void onLeScan(final BluetoothDevice device, final int rssi,
                      byte[] scanRecord)
      {
         // TODO Auto-generated method stub

         runOnUiThread(new Runnable()
         {
            @Override
            public void run()
            {
               /* 讲扫描到设备的信息输出到listview的适配器 */
               mleDeviceListAdapter.addDevice(device, rssi);
               mleDeviceListAdapter.notifyDataSetChanged();
            }
         });

         System.out.println("Address:" + device.getAddress());
         System.out.println("Name:" + device.getName());
         System.out.println("rssi:" + rssi);

      }
   };

   /**
    * @Description: TODO<自定义适配器Adapter,作为listview的适配器>
    * @author 广州汇承信息科技有限公司
    * @data: 2014-10-12 上午10:46:30
    * @version: V1.0
    */
   private class LeDeviceListAdapter extends BaseAdapter {
      private ArrayList mLeDevices;

      private LayoutInflater mInflator;

      public LeDeviceListAdapter()
      {
         super();
         rssis = new ArrayList();
         mLeDevices = new ArrayList();
         mInflator = getLayoutInflater();
      }

      public void addDevice(BluetoothDevice device, int rssi)
      {
         if (!mLeDevices.contains(device))
         {
            mLeDevices.add(device);
            rssis.add(rssi);
         }
      }

      public BluetoothDevice getDevice(int position)
      {
         return mLeDevices.get(position);
      }

      public void clear()
      {
         mLeDevices.clear();
         rssis.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;
      }

      /**
       * 重写getview
       *
       * **/
      @Override
      public View getView(int i, View view, ViewGroup viewGroup)
      {

         // General ListView optimization code.
         // 加载listview每一项的视图
         view = mInflator.inflate(R.layout.listitem, null);
         // 初始化三个textview显示蓝牙信息
         TextView deviceAddress = (TextView) view
               .findViewById(R.id.tv_deviceAddr);
         TextView deviceName = (TextView) view
               .findViewById(R.id.tv_deviceName);
         TextView rssi = (TextView) view.findViewById(R.id.tv_rssi);

         BluetoothDevice device = mLeDevices.get(i);
         deviceAddress.setText(device.getAddress());
         deviceName.setText(device.getName());
         rssi.setText("" + rssis.get(i));

         return view;
      }
   }

}

 

************************************3Ble_Activity.java*************************

package com.example.bluetoothrobot;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
//import com.huicheng.service.*;
import android.app.Activity;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
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.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;

//import com.huicheng.R;
//import com.huicheng.service.BluetoothLeService;

/**
 * 特别说明:HC_BLE助手是广州汇承信息科技有限公司独自研发的手机APP,方便用户调试08蓝牙模块。
 * 本软件只能支持安卓版本4.3并且有蓝牙4.0的手机使用。
 * 另外对于自家的0506模块,要使用另外一套蓝牙2.0的手机APP,用户可以在汇承官方网的下载中心自行下载。
 * 本软件提供代码和注释,免费给购买汇承08模块的用户学习和研究,但不能用于商业开发,最终解析权在广州汇承信息科技有限公司。
 **/

/**
 * @author 广州汇承信息科技有限公司
 * @Description: TODO实现连接BLE,发送和接受BLE的数据>
 * @data: 2014-10-20 下午12:12:04
 * @version: V1.0
 */
public class Ble_Activity extends Activity implements OnClickListener {

    private final static String TAG = Ble_Activity.class.getSimpleName();
    //蓝牙4.0UUID,其中0000ffe1-0000-1000-8000-00805f9b34fb是广州汇承信息科技有限公司08蓝牙模块的UUID
    public static String HEART_RATE_MEASUREMENT = "0000ffe1-0000-1000-8000-00805f9b34fb";
    public static String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
    ;
    public static String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
    public static String EXTRAS_DEVICE_RSSI = "RSSI";
    //蓝牙连接状态
    private boolean mConnected = false;
    private String status = "disconnected";
    //蓝牙名字
    private String mDeviceName;
    //蓝牙地址
    private String mDeviceAddress;
    //蓝牙信号值
    private String mRssi;
    private Bundle b;
    private String rev_str = "";
    //蓝牙service,负责后台的蓝牙服务
    private static BluetoothLeService mBluetoothLeService;
    //文本框,显示接受的内容
    private TextView rev_tv, connect_state;
    //发送按钮
    private Button send_btn1, send_btn2, send_btn3, send_btn4;
    //发送内容选择变量
    private int sendFlag = 0;
    //文本编辑框
    //private EditText send_et;
    private ScrollView rev_sv;
    private ArrayList> mGattCharacteristics = new ArrayList>();
    //蓝牙特征值
    private static BluetoothGattCharacteristic target_chara=null;
    public static byte[] revDataForCharacteristic;
    private Handler mhandler = new Handler();
    private Handler myHandler = new Handler() {
        // 2.重写消息处理函数
        public void handleMessage(Message msg) {
            switch (msg.what) {
                // 判断发送的消息
                case 1: {
                    // 更新View
                    String state = msg.getData().getString("connect_state");
                    connect_state.setText(state);

                    break;
                }

            }
            super.handleMessage(msg);
        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ble_activity);
        b = getIntent().getExtras();
        //从意图获取显示的蓝牙信息
        mDeviceName = b.getString(EXTRAS_DEVICE_NAME);
        mDeviceAddress = b.getString(EXTRAS_DEVICE_ADDRESS);
        mRssi = b.getString(EXTRAS_DEVICE_RSSI);

      /* 启动蓝牙service */
        Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
        init();

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //解除广播接收器
        unregisterReceiver(mGattUpdateReceiver);
        mBluetoothLeService = null;
    }

    // Activity出来时候,绑定广播接收器,监听蓝牙连接服务传过来的事件
    @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);
        }
    }

    /**
     * @param
     * @return void
     * @throws
     * @Title: init
     * @Description: TODO(初始化UI控件)
     */
    private void init() {
        rev_sv = (ScrollView) this.findViewById(R.id.rev_sv);
        rev_tv = (TextView) this.findViewById(R.id.rev_tv);
        connect_state = (TextView) this.findViewById(R.id.connect_state);
        send_btn1 = (Button) this.findViewById(R.id.send_btn1);
        send_btn2 = (Button) this.findViewById(R.id.send_btn2);
        send_btn3 = (Button) this.findViewById(R.id.send_btn3);
        send_btn4 = (Button) this.findViewById(R.id.send_btn4);
        //send_et = (EditText) this.findViewById(R.id.send_et);
        connect_state.setText(status);
        send_btn1.setOnClickListener(this);
        send_btn2.setOnClickListener(this);
        send_btn3.setOnClickListener(this);
        send_btn4.setOnClickListener(this);
    }

    /* BluetoothLeService绑定的回调函数 */
    private final ServiceConnection mServiceConnection = new ServiceConnection() {

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

        }

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

    };

    /**
     * 广播接收器,负责接收BluetoothLeService类发送的数据
     */
    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))//Gatt连接成功
            {
                mConnected = true;
                status = "connected";
                //更新连接状态
                updateConnectionState(status);
                System.out.println("BroadcastReceiver :" + "device connected");

            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED//Gatt连接失败
                    .equals(action)) {
                mConnected = false;
                status = "disconnected";
                //更新连接状态
                updateConnectionState(status);
                System.out.println("BroadcastReceiver :"
                        + "device disconnected");

            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED//发现GATT服务器
                    .equals(action)) {
                // Show all the supported services and characteristics on the
                // user interface.
                //获取设备的所有蓝牙服务
                displayGattServices(mBluetoothLeService
                        .getSupportedGattServices());
                System.out.println("BroadcastReceiver :"
                        + "device SERVICES_DISCOVERED");
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))//有效数据
            {
                //处理发送过来的数据
                displayData(intent.getExtras().getString(
                        BluetoothLeService.EXTRA_DATA), intent);
                System.out.println("BroadcastReceiver onData:"
                        + intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
            }
        }
    };

    /* 更新连接状态 */
    private void updateConnectionState(String status) {
        Message msg = new Message();
        msg.what = 1;
        Bundle b = new Bundle();
        b.putString("connect_state", status);
        msg.setData(b);
        //将连接状态更新的UItextview
        myHandler.sendMessage(msg);
        System.out.println("connect_state:" + status);

    }

    /* 意图过滤器 */
    private static IntentFilter makeGattUpdateIntentFilter() {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter
                .addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        return intentFilter;
    }

    /**
     * @param @param rev_string(接受的数据)
     * @return void
     * @throws
     * @Title: displayData
     * @Description: TODO(接收到的数据在scrollview上显示)
     */
    private void displayData(String rev_string, Intent intent) {
        try {
            byte[] data = intent.getByteArrayExtra("BLE_BYTE_DATA");
            if (data == null)
                System.out.println("data is null!!!!!!");
            //GB2312编码
            rev_string = new String(data, 0, data.length, "GB2312");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        rev_str += rev_string;
        //更新UI
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                rev_tv.setText(rev_str);
                rev_sv.scrollTo(0, rev_tv.getMeasuredHeight());
                System.out.println("rev:" + rev_str);
            }
        });

    }

    /**
     * @param
     * @return void
     * @throws
     * @Title: displayGattServices
     * @Description: TODO(处理蓝牙服务)
     */
    private void displayGattServices(List gattServices) {

        if (gattServices == null)
            return;
        String uuid = null;
        String unknownServiceString = "unknown_service";
        String unknownCharaString = "unknown_characteristic";

        // 服务数据,可扩展下拉列表的第一级数据
        ArrayList> gattServiceData = new ArrayList>();

        // 特征数据(隶属于某一级服务下面的特征值集合)
        ArrayList>> gattCharacteristicData = new ArrayList>>();

        // 部分层次,所有特征值集合
        mGattCharacteristics = new ArrayList>();

        // Loops through available GATT Services.
        for (BluetoothGattService gattService : gattServices) {

            // 获取服务列表
            HashMap currentServiceData = new HashMap();
            uuid = gattService.getUuid().toString();

            // 查表,根据该uuid获取对应的服务名称。SampleGattAttributes这个表需要自定义。

            gattServiceData.add(currentServiceData);

            System.out.println("Service uuid:" + uuid);

            ArrayList> gattCharacteristicGroupData = new ArrayList>();

            // 从当前循环所指向的服务中读取特征值列表
            List gattCharacteristics = gattService
                    .getCharacteristics();

            ArrayList charas = new ArrayList();

            // Loops through available Characteristics.
            // 对于当前循环所指向的服务中的每一个特征值
            for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                charas.add(gattCharacteristic);
                HashMap currentCharaData = new HashMap();
                uuid = gattCharacteristic.getUuid().toString();

                if (gattCharacteristic.getUuid().toString()
                        .equals(HEART_RATE_MEASUREMENT)) {
                    // 测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
                    mhandler.postDelayed(new Runnable() {

                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            mBluetoothLeService
                                    .readCharacteristic(gattCharacteristic);
                        }
                    }, 200);

                    // 接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
                    mBluetoothLeService.setCharacteristicNotification(
                            gattCharacteristic, true);
                    target_chara = gattCharacteristic;
                    // 设置数据内容
                    // 往蓝牙模块写入数据
                    // mBluetoothLeService.writeCharacteristic(gattCharacteristic);
                }
                List descriptors = gattCharacteristic
                        .getDescriptors();
                for (BluetoothGattDescriptor descriptor : descriptors) {
                    System.out.println("---descriptor UUID:"
                            + descriptor.getUuid());
                    // 获取特征值的描述
                    mBluetoothLeService.getCharacteristicDescriptor(descriptor);
                    // mBluetoothLeService.setCharacteristicNotification(gattCharacteristic,
                    // true);
                }

                gattCharacteristicGroupData.add(currentCharaData);
            }
            // 按先后顺序,分层次放入特征值集合中,只有特征值
            mGattCharacteristics.add(charas);
            // 构件第二级扩展列表(服务下面的特征值)
            gattCharacteristicData.add(gattCharacteristicGroupData);

        }

    }

    /**
     * 将数据分包
     **/
    public int[] dataSeparate(int len) {
        int[] lens = new int[2];
        lens[0] = len / 20;
        lens[1] = len % 20;
        return lens;
    }

    /*
     * 数据发送线程
     *
     * */
    public class sendDataThread implements Runnable {
        public sendDataThread() {
            super();
            new Thread(this).start();
        }

        @Override
        public void run() {
            byte[] buff = null;
            try {
                buff =String.valueOf(sendFlag).getBytes("utf-8");//将输入框的数据转换成utf-8格式的数据存入字节数组
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            int[] sendDatalens = dataSeparate(buff.length);//分散数据
            for (int i = 0; i < sendDatalens[0]; i++)//
            {
                byte[] dataFor20 = new byte[20];//定义一个长度为20的字节数组

                for (int j = 0; j < 20; j++) {
                    dataFor20[j] = buff[i * 20 + j];//给数组单元赋值
                }
                target_chara.setValue(dataFor20);
                mBluetoothLeService.writeCharacteristic(target_chara);
            }
            if (sendDatalens[1] != 0) {
                System.out.println("here2");
                byte[] lastData = new byte[20];
                for (int i = 0; i < sendDatalens[1]; i++)
                    lastData[i] = buff[sendDatalens[0] * 20 + i];
                String str = null;
                try {
                    str = new String(lastData, 0, sendDatalens[1], "utf-8");//将输入框的数据转换成utf-8格式的数据存入字节数组
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                target_chara.setValue(lastData);
                mBluetoothLeService.writeCharacteristic(target_chara);
            }

        }

    }

    /*
     * 发送按键的响应事件,主要发送文本框的数据
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.send_btn1:
                sendFlag = 1;
                //new sendDataThread();
                break;
            case R.id.send_btn2:
                sendFlag = 2;
                //new sendDataThread();
                break;
            case R.id.send_btn3:
                sendFlag = 3;
                //new sendDataThread();
                break;
            case R.id.send_btn4:
                sendFlag = 4;
                //new sendDataThread();
                break;
        }
        new sendDataThread();
    }
}

 

*********************************4BluetoothLeService.java************************

package com.example.bluetoothrobot;
      import java.util.ArrayList;
      import java.util.List;
      import java.util.UUID;

      //import org.apache.http.entity.ByteArrayEntity;

      //import com.example.blutoothhc.Ble_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.hardware.Sensor;
      import android.os.Binder;
      import android.os.Bundle;
      import android.os.IBinder;
      import android.util.Log;

/**
 * 特别说明:HC_BLE助手是广州汇承信息科技有限公司独自研发的手机APP,方便用户调试08蓝牙模块。
 * 本软件只能支持安卓版本4.3并且有蓝牙4.0的手机使用。
 * 另外对于自家的0506模块,要使用另外一套蓝牙2.0的手机APP,用户可以在汇承官方网的下载中心自行下载。
 * 本软件提供代码和注释,免费给购买汇承08模块的用户学习和研究,但不能用于商业开发,最终解析权在广州汇承信息科技有限公司。
 * **/

/**
 * @Description:  TODO<蓝牙服务,负责在后台实现蓝牙的连接,数据的发送接受>
 * @author  广州汇承信息科技有限公司
 * @data:  2014-10-22 下午2:30:38
 * @version:  V1.0
 */
public class BluetoothLeService extends Service {
   private final static String TAG = "BluetoothLeService";// luetoothLeService.class.getSimpleName();
   private List mEnabledSensors = new ArrayList();
   //蓝牙相关类
   private BluetoothManager mBluetoothManager;
   private BluetoothAdapter mBluetoothAdapter;
   private String mBluetoothDeviceAddress;
   private BluetoothGatt mBluetoothGatt;
   private int mConnectionState = STATE_DISCONNECTED;

   private static final int STATE_DISCONNECTED = 0;
   private static final int STATE_CONNECTING = 1;
   private static final int STATE_CONNECTED = 2;

   public final static String ACTION_GATT_CONNECTED = "com.hc_ble.bluetooth.le.ACTION_GATT_CONNECTED";
   public final static String ACTION_GATT_DISCONNECTED = "com.hc_ble.bluetooth.le.ACTION_GATT_DISCONNECTED";
   public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.hc_ble.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
   public final static String ACTION_DATA_AVAILABLE = "com.hc_ble.bluetooth.le.ACTION_DATA_AVAILABLE";
   public final static String EXTRA_DATA = "com.hc_ble.bluetooth.le.EXTRA_DATA";

   // public final static UUID UUID_HEART_RATE_MEASUREMENT =zzzzzzzzzzzzz
   // UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);
   private OnDataAvailableListener mOnDataAvailableListener;

   // Implements callback methods for GATT events that the app cares about. For
   // example,
   // connection change and services discovered.

   public interface OnDataAvailableListener {
      public void onCharacteristicRead(BluetoothGatt gatt,
                               BluetoothGattCharacteristic characteristic, int status);

      public void onCharacteristicWrite(BluetoothGatt gatt,
                                BluetoothGattCharacteristic characteristic);

      public void onCharacteristicChanged(BluetoothGatt gatt,
                                 BluetoothGattCharacteristic characteristic);
   }

   public void setOnDataAvailableListener(OnDataAvailableListener l)
   {
      mOnDataAvailableListener = l;
   }

   /* 连接远程设备的回调函数 */
   private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
   {
      @Override
      public void onConnectionStateChange(BluetoothGatt gatt, int status,
                                 int newState)
      {
         String intentAction;
         if (newState == BluetoothProfile.STATE_CONNECTED)//连接成功
         {
            intentAction = ACTION_GATT_CONNECTED;
            mConnectionState = STATE_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;
            mConnectionState = STATE_DISCONNECTED;
            Log.i(TAG, "Disconnected from GATT server.");
            broadcastUpdate(intentAction);
         }
      }
      /*
         * 重写onServicesDiscovered,发现蓝牙服务
         *
         * */
      @Override
      public void onServicesDiscovered(BluetoothGatt gatt, int status)
      {
         if (status == BluetoothGatt.GATT_SUCCESS)//发现到服务
         {
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            Log.i(TAG, "--onServicesDiscovered called--");
         } else
         {
            Log.w(TAG, "onServicesDiscovered received: " + status);
            System.out.println("onServicesDiscovered received: " + status);
         }
      }
      /*
         * 特征值的读写
         * */
      @Override
      public void onCharacteristicRead(BluetoothGatt gatt,
                               BluetoothGattCharacteristic characteristic, int status)
      {
         if (status == BluetoothGatt.GATT_SUCCESS)
         {
            Log.i(TAG, "--onCharacteristicRead called--");
            //从特征值读取数据
            byte[] sucString = characteristic.getValue();
            String string = new String(sucString);
            //将数据通过广播到Ble_Activity
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
         }

      }
      /*
         * 特征值的改变
         * */
      @Override
      public void onCharacteristicChanged(BluetoothGatt gatt,
                                 BluetoothGattCharacteristic characteristic)
      {
         System.out.println("++++++++++++++++");
         broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);

      }
      /*
         * 特征值的写
         * */
      @Override
      public void onCharacteristicWrite(BluetoothGatt gatt,
                                BluetoothGattCharacteristic characteristic, int status)
      {

         Log.w(TAG, "--onCharacteristicWrite--: " + status);
         // 以下语句实现 发送完数据或也显示到界面上
         //broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
      }
      /*
         * 读描述值
         * */
      @Override
      public void onDescriptorRead(BluetoothGatt gatt,
                            BluetoothGattDescriptor descriptor, int status)
      {
         // TODO Auto-generated method stub
         // super.onDescriptorRead(gatt, descriptor, status);
         Log.w(TAG, "----onDescriptorRead status: " + status);
         byte[] desc = descriptor.getValue();
         if (desc != null)
         {
            Log.w(TAG, "----onDescriptorRead value: " + new String(desc));
         }

      }
      /*
         * 写描述值
         * */
      @Override
      public void onDescriptorWrite(BluetoothGatt gatt,
                             BluetoothGattDescriptor descriptor, int status)
      {
         // TODO Auto-generated method stub
         // super.onDescriptorWrite(gatt, descriptor, status);
         Log.w(TAG, "--onDescriptorWrite--: " + status);
      }
      /*
         * 读写蓝牙信号值
         * */
      @Override
      public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status)
      {
         // TODO Auto-generated method stub
         // super.onReadRemoteRssi(gatt, rssi, status);
         Log.w(TAG, "--onReadRemoteRssi--: " + status);
         broadcastUpdate(ACTION_DATA_AVAILABLE, rssi);
      }

      @Override
      public void onReliableWriteCompleted(BluetoothGatt gatt, int status)
      {
         // TODO Auto-generated method stub
         // super.onReliableWriteCompleted(gatt, status);
         Log.w(TAG, "--onReliableWriteCompleted--: " + status);
      }

   };
   //广播意图
   private void broadcastUpdate(final String action, int rssi)
   {
      final Intent intent = new Intent(action);
      intent.putExtra(EXTRA_DATA, String.valueOf(rssi));
      sendBroadcast(intent);
   }
   //广播意图
   private void broadcastUpdate(final String action)
   {
      final Intent intent = new Intent(action);
      sendBroadcast(intent);
   }

   /* 广播远程发送过来的数据 */
   public void broadcastUpdate(final String action,
                        final BluetoothGattCharacteristic characteristic)
   {
      final Intent intent = new Intent(action);
      //从特征值获取数据
      final byte[] data = characteristic.getValue();
      Ble_Activity.revDataForCharacteristic =data;
      if (data != null && data.length > 0)
      {
         final StringBuilder stringBuilder = new StringBuilder(data.length);
         for (byte byteChar : data)
         {
            stringBuilder.append(String.format("%02X ", byteChar));

            Log.i(TAG, "***broadcastUpdate: byteChar = " + byteChar);

         }
         intent.putExtra("BLE_BYTE_DATA", data);
         intent.putExtra(EXTRA_DATA, new String(data));
         System.out.println("broadcastUpdate for  read 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)
   {
      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.
    */
   /* service 中蓝牙初始化 */
   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())//连接蓝牙,其实就是调用BluetoothGatt的连接方法
         {
            mConnectionState = STATE_CONNECTING;
            return true;
         } else
         {
            return false;
         }
      }
      /* 获取远端的蓝牙设备 */
      final 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.
      /* 调用device中的connectGatt连接到远程设备 */
      mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
      Log.d(TAG, "Trying to create a new connection.");
      mBluetoothDeviceAddress = address;
      mConnectionState = STATE_CONNECTING;
      System.out.println("device.getBondState==" + device.getBondState());
      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.
    */
   /*
    * 取消连接
    *
    * */
   /**
    * @Title: disconnect
    * @Description: TODO(取消蓝牙连接)
    * @param   
    * @return void
    * @throws
    */
   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.
    */
   /**
    * @Title: close
    * @Description: TODO(关闭所有蓝牙连接)
    * @param  
    * @return void
    * @throws
    */
   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.
    */
   /**
    * @Title: readCharacteristic
    * @Description: TODO(读取特征值)
    * @param @param characteristic(要读的特征值)
    * @return void    返回类型
    * @throws
    */
   public void readCharacteristic(BluetoothGattCharacteristic characteristic)
   {
      if (mBluetoothAdapter == null || mBluetoothGatt == null)
      {
         Log.w(TAG, "BluetoothAdapter not initialized");
         return;
      }
      mBluetoothGatt.readCharacteristic(characteristic);

   }

   // 写入特征值
   public void writeCharacteristic(BluetoothGattCharacteristic characteristic)
   {
      if (mBluetoothAdapter == null || mBluetoothGatt == null)
      {
         Log.w(TAG, "BluetoothAdapter not initialized");
         return;
      }
      mBluetoothGatt.writeCharacteristic(characteristic);

   }

   // 读取RSSi
   public void readRssi()
   {
      if (mBluetoothAdapter == null || mBluetoothGatt == null)
      {
         Log.w(TAG, "BluetoothAdapter not initialized");
         return;
      }
      mBluetoothGatt.readRemoteRssi();
   }

   /**
    * Enables or disables notification on a give characteristic.
    *
    * @param characteristic
    *            Characteristic to act on.
    * @param enabled
    *            If true, enable notification. False otherwise.
    */
   /**
    * @Title: setCharacteristicNotification
    * @Description: TODO(设置特征值通变化通知)
    * @param @param characteristic(特征值)
    * @param @param enabled (使能)
    * @return void
    * @throws
    */
   public void setCharacteristicNotification(
         BluetoothGattCharacteristic characteristic, boolean enabled)
   {
      if (mBluetoothAdapter == null || mBluetoothGatt == null)
      {
         Log.w(TAG, "BluetoothAdapter not initialized");
         return;
      }
      mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);

      BluetoothGattDescriptor clientConfig = characteristic
            .getDescriptor(UUID
                  .fromString("00002902-0000-1000-8000-00805f9b34fb"));

      if (enabled)
      {
         clientConfig
               .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
      } else
      {
         clientConfig
               .setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
      }
      mBluetoothGatt.writeDescriptor(clientConfig);
   }

   /**
    * @Title: getCharacteristicDescriptor
    * @Description: TODO(得到特征值下的描述值)
    * @param @param
    * @return void
    * @throws
    */
   public void getCharacteristicDescriptor(BluetoothGattDescriptor descriptor)
   {
      if (mBluetoothAdapter == null || mBluetoothGatt == null)
      {
         Log.w(TAG, "BluetoothAdapter not initialized");
         return;
      }

      mBluetoothGatt.readDescriptor(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.
    */
   /**
    * @Title: getSupportedGattServices
    * @Description: TODO(得到蓝牙的所有服务)
    * @param @return    
    * @return List
    * @throws
    */
   public List getSupportedGattServices()
   {
      if (mBluetoothGatt == null)
         return null;
      return mBluetoothGatt.getServices();

   }

}

*********************************5activity_main.xml************************


    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

   

你可能感兴趣的:(android学习)