Android 蓝牙设备通讯的开发(配对/连接/传输数据)

Posted BandaYung

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 蓝牙设备通讯的开发(配对/连接/传输数据)相关的知识,希望对你有一定的参考价值。

最近公司想做一个关于蓝牙的项目,同时我也学习到了很多关于蓝牙方面的很多知识点,希望在这里跟大家分享下,不足之处有望指明.

项目源码:http://download.csdn.net/detail/qq_30552993/9529815

这里先附上项目图片,不过这里ListView中如果是已配对的就进行连接,如果是未配对的就进行配对,配对完成之后这里的话要重新搜索设备,这里没做刷新.还有就是可以在两只手机上都装上这个,再连接上就可以进行发送到另一只手机上去,不知道为什么有时候好像蓝牙有些不知是否不太稳定,出现搜索蓝牙有些没搜到.

在很多方面,蓝牙是一种能够发送或接受两个不同的设备之间传输的数据。 android平台包含了蓝牙框架,使设备以无线方式与其他蓝牙设备进行数据交换的支持。

Android提供蓝牙API来执行这些不同的操作。

  1. 扫描其他蓝牙设备
  2. 获取配对设备列表
  3. 连接到通过服务发现其他设备
  • Android提供BluetoothAdapter类蓝牙通信。通过调用创建的对象的静态方法getDefaultAdapter()。其语法如下给出。
private BluetoothAdapter BA;
BA = BluetoothAdapter.getDefaultAdapter();
  • 这里我把一些关于蓝牙的打开/关闭/配对/连接/数据传输的线程都封装BlueToothUtils这个蓝牙工具类中
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * Created by shaolin on 5/23/16.
 */
public class BlueToothUtils 
    private static final String TAG = "BlueToothUtils";
    private Context mContext;
    public static BlueToothUtils sInstance;
    private BluetoothAdapter mBA;
    // UUID.randomUUID()随机获取UUID
    private final UUID MY_UUID = UUID
            .fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3");
    // 连接对象的名称
    private final String NAME = "LGL";

    // 这里本身即是服务端也是客户端,需要如下类
    private BluetoothSocket mSocket;
    private BluetoothDevice mOldDevice;
    private BluetoothDevice mCurDevice;
    // 输出流_客户端需要往服务端输出
    private OutputStream os;

    //线程类的实例
    private AcceptThread ac;

    public static synchronized BlueToothUtils getInstance() 
        if (sInstance == null) 
            sInstance = new BlueToothUtils();
        
        return sInstance;
    

    public BlueToothUtils() 
        mBA = BluetoothAdapter.getDefaultAdapter();
        ac = new AcceptThread();
    

    public void setContext(Context context) 
        this.mContext = context;
    

    public BluetoothAdapter getBA() 
        return mBA;
    

    public AcceptThread getAc() 
        return ac;
    

    public BluetoothDevice getCurDevice() 
        return mCurDevice;
    

    /**
     * 判断是否打开蓝牙
     *
     * @return
     */
    public boolean isEnabled() 
        if (mBA.isEnabled()) 
            return true;
        
        return false;
    

    /**
     * 搜索设备
     */
    public void searchDevices() 
        // 判断是否在搜索,如果在搜索,就取消搜索
        if (mBA.isDiscovering()) 
            mBA.cancelDiscovery();
        
        // 开始搜索
        mBA.startDiscovery();
        Log.e(TAG, "正在搜索...");
    

    /**
     * 获取已经配对的设备
     *
     * @return
     */
    public List<BluetoothDevice> getBondedDevices() 
        List<BluetoothDevice> devices = new ArrayList<>();
        Set<BluetoothDevice> pairedDevices = mBA.getBondedDevices();
        // 判断是否有配对过的设备
        if (pairedDevices.size() > 0) 
            for (BluetoothDevice device : pairedDevices) 
                devices.add(device);
                Log.e(TAG, "BondedDevice:" + device.getName());
            
        
        return devices;
    

    /**
     * 与设备配对
     *
     * @param device
     */
    public void createBond(BluetoothDevice device) 
        try 
            Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
            createBondMethod.invoke(device);
         catch (Exception e) 
            e.printStackTrace();
        
    

    /**
     * 与设备解除配对
     *
     * @param device
     */
    public void removeBond(BluetoothDevice device) 
        try 
            Method removeBondMethod = device.getClass().getMethod("removeBond");
            removeBondMethod.invoke(device);
         catch (Exception e) 
            e.printStackTrace();
        
    

    /**
     *
     * @param device
     * @param str  设置PIN码
     * @return
     */
    public boolean setPin(BluetoothDevice device, String str) 
        try 
            Method removeBondMethod = device.getClass().getDeclaredMethod("setPin",
                    new Class[]byte[].class);
            Boolean returnValue = (Boolean) removeBondMethod.invoke(device,
                    new Object[]str.getBytes());
            Log.e("returnValue", "" + returnValue);
         catch (SecurityException e) 
            e.printStackTrace();
         catch (IllegalArgumentException e) 
            e.printStackTrace();
         catch (Exception e) 
            e.printStackTrace();
        
        return true;
    

    /**
     * 取消用户输入
     */
    public boolean cancelPairingUserInput(BluetoothDevice device) 
        Boolean returnValue = false;
        try 
            Method createBondMethod = device.getClass().getMethod("cancelPairingUserInput");
            returnValue = (Boolean) createBondMethod.invoke(device);
         catch (NoSuchMethodException e) 
            e.printStackTrace();
         catch (InvocationTargetException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
        
        // cancelBondProcess()
        return returnValue.booleanValue();
    

    /**
     * 取消配对
     */
    public boolean cancelBondProcess(BluetoothDevice device) 
        Boolean returnValue = null;
        try 
            Method createBondMethod = device.getClass().getMethod("cancelBondProcess");
            returnValue = (Boolean) createBondMethod.invoke(device);
         catch (IllegalAccessException e) 
            e.printStackTrace();
         catch (InvocationTargetException e) 
            e.printStackTrace();
         catch (NoSuchMethodException e) 
            e.printStackTrace();
        
        return returnValue.booleanValue();
    

    /**
     * @param strAddr
     * @param strPsw
     * @return
     */
    public boolean pair(String strAddr, String strPsw) 
        boolean result = false;
        mBA.cancelDiscovery();

        if (!mBA.isEnabled()) 
            mBA.enable();
        

        if (!BluetoothAdapter.checkBluetoothAddress(strAddr))  // 检查蓝牙地址是否有效
            Log.d("mylog", "devAdd un effient!");
        

        BluetoothDevice device = mBA.getRemoteDevice(strAddr);
        if (device.getBondState() != BluetoothDevice.BOND_BONDED) 
            Log.d("mylog", "NOT BOND_BONDED");
            try 
                setPin(device, strPsw); // 手机和蓝牙采集器配对
                createBond(device);
                result = true;
             catch (Exception e) 
                Log.d("mylog", "setPiN failed!");
                e.printStackTrace();
             //

         else 
            Log.d("mylog", "HAS BOND_BONDED");
            try 
                createBond(device);
                setPin(device, strPsw); // 手机和蓝牙采集器配对
                createBond(device);
                result = true;
             catch (Exception e) 
                Log.d("mylog", "setPiN failed!");
                e.printStackTrace();
            
        
        return result;
    

    /**
     * 获取device.getClass()这个类中的所有Method
     *
     * @param clsShow
     */
    public void printAllInform(Class clsShow) 
        try 
            // 取得所有方法
            Method[] hideMethod = clsShow.getMethods();
            int i = 0;
            for (; i < hideMethod.length; i++) 
                Log.e("method name", hideMethod[i].getName() + ";and the i is:" + i);
            
            // 取得所有常量
            Field[] allFields = clsShow.getFields();
            for (i = 0; i < allFields.length; i++) 
                Log.e("Field name", allFields[i].getName());
            
         catch (SecurityException e) 
            e.printStackTrace();
         catch (IllegalArgumentException e) 
            e.printStackTrace();
         catch (Exception e) 
            e.printStackTrace();
        
    

    /**
     * 打开蓝牙
     */
    public void openBlueTooth() 
        if (!mBA.isEnabled()) 
            // 弹出对话框提示用户是后打开
            /*Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, 1);*/
            // 不做提示,强行打开
            mBA.enable();
            showToast("打开蓝牙");
         else 
            showToast("蓝牙已打开");
        
    

    /**
     * 关闭蓝牙
     */
    public void closeBlueTooth() 
        mBA.disable();
        showToast("关闭蓝牙");
    

    /**
     * 弹出Toast窗口
     *
     * @param message
     */
    private void showToast(String message) 
        if (mContext != null) 
            Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
         else 
            Log.e(TAG, "message:" + message);
        
    

    /**
     * 主动连接蓝牙
     *
     * @param device
     */
    public void connectDevice(BluetoothDevice device) 
        // 判断是否在搜索,如果在搜索,就取消搜索
        if (mBA.isDiscovering()) 
            mBA.cancelDiscovery();
        
        try 
            // 获得远程设备
            if (mCurDevice == null || mCurDevice != mOldDevice) 
                mCurDevice = mBA.getRemoteDevice(device.getAddress());
                mOldDevice = mCurDevice;
                Log.e(TAG, "device:" + mCurDevice);
                mSocket = mCurDevice.createRfcommSocketToServiceRecord(MY_UUID);
                // 连接
                mSocket.connect();
                // 获得输出流
                os = mSocket.getOutputStream();
            
            // 如果成功获得输出流

         catch (IOException e) 
            e.printStackTrace();
        
    

    /**
     * 传输数据
     *
     * @param message
     */
    public void write(String message) 
        try 
            if (os != null) 
                os.write(message.getBytes("GBK"));
            
            Log.e(TAG, "write:" + message);
         catch (IOException e) 
            e.printStackTrace();
        

    

    // 服务端,需要监听客户端的线程类
    private Handler handler = new Handler() 
        public void handleMessage(Message msg) 
            showToast(String.valueOf(msg.obj));
            Log.e(TAG, "服务端:" + msg.obj);
            super.handleMessage(msg);
        
    ;


    // 线程服务类
    public class AcceptThread extends Thread 
        private BluetoothServerSocket serverSocket;
        private BluetoothSocket socket;
        // 输入 输出流
        private OutputStream os;
        private InputStream is;

        public AcceptThread() 
            try 
                serverSocket = mBA.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
             catch (IOException e) 
                e.printStackTrace();
            
        

        @Override
        public void run() 
            // 截获客户端的蓝牙消息
            try 
                socket = serverSocket.accept(); // 如果阻塞了,就会一直停留在这里
                is = socket.getInputStream();
                os = socket.getOutputStream();
                while (true) 
                    synchronized (this) 
                        byte[] tt = new byte[is.available()];
                        if (tt.length > 0) 
                            is.read(tt, 0, tt.length);
                            Message msg = new Message();
                            msg.obj = new String(tt, "GBK");
                            Log.e(TAG, "客户端:" + msg.obj);
                            handler.sendMessage(msg);
                        
                    
                
             catch (Exception e) 
                e.printStackTrace();
            
        
    

参考:http://www.yiibai.com/android/android_bluetooth.html

http://www.cnblogs.com/jason-star/archive/2012/09/10/2678368.html

 

以上是关于Android 蓝牙设备通讯的开发(配对/连接/传输数据)的主要内容,如果未能解决你的问题,请参考以下文章

Android开发之蓝牙(Bluetooth)操作--扫描已经配对的蓝牙设备

Android -- 蓝牙蓝牙配对和蓝牙连接

Android 蓝牙开发之搜索配对连接通信大全

Android 蓝牙开发-打开蓝牙后能不能立即连接固定地址的蓝牙设备??还是需要进行判断啥的?

Android蓝牙开发—— 经典蓝牙连接方法

Android 经典蓝牙开发(一)