Android蓝牙串口通信的用法(一)

一. 蓝牙权限


    <uses-permission android:name="android.permission.BLUETOOTH"/>

    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

二.配对

代码走起~~ 会顺带加些常用的知识点。简书这个贴代码,格式都没了,将就的看吧,需要的时候自己再检查括号啥的,毕竟时间很紧张。

1.发起请求:

BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();

 if(mAdapter!=null && mAdapter.isEnabled()){

   try {   

          // pair before connect   

          BluetoothDevice Vdevice = mAdapter.getRemoteDevice(BTMAC);

           if (Vdevice.getBondState() == BluetoothDevice.BOND_NONE) {   

                       Method creMethod = BluetoothDevice.class.getMethod("createBond");   

                       Log.e(TAG, "START pair");   

                     creMethod.invoke(Vdevice);   

           } else {

                    Log.e(TAG, "paired!");

           } 

       } catch (Exception e) {   

        // TODO: handle exception   

              e.printStackTrace();   

         }

}else{

         //;

 }

2.如果需要固定码直接配对,可以使用方法:(此段代码在下面完整的广播例子中有)

if(action.equals("android.bluetooth.device.action.PAIRING_REQUEST")) //再次得到的action,会等于PAIRING_REQUEST

        { 

            BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            Log.e(TAG, action); 

            if(btDevice.getAddress().equals(BTMAC))  //btDevice.getName().contains("HC-05")

            { 

                try { 

                    //1.确认配对 

                    ClsUtils.setPairingConfirmation(btDevice.getClass(), btDevice, true); 

                    //2.终止有序广播 

                    Log.i(TAG, "isOrderedBroadcast:"+isOrderedBroadcast()+",isInitialStickyBroadcast:"+isInitialStickyBroadcast()); 

                    abortBroadcast();//如果没有将广播终止,则会出现一个一闪而过的配对框。 

                    //3.调用setPin方法进行配对... 

                    boolean ret = ClsUtils.setPin(btDevice.getClass(), btDevice, BTPIN); 


                } catch (Exception e) { 

                    // TODO Auto-generated catch block 

                    e.printStackTrace(); 

                } 

            }else{ 

                Log.e(TAG, "NOT THE BT U WANT"); 

            }

3.以上用到将相关方法封装的一个类,ClsUtils。也是参考网上的“轮子”,感谢热心分享的技术大牛。

public class ClsUtils

{   

    /** 

    * 与设备配对 参考源码:platform/packages/apps/Settings.git 

    * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java 

    */   

    static public boolean createBond(Class btClass, BluetoothDevice btDevice)   

    throws Exception   

    {   

        Method createBondMethod = btClass.getMethod("createBond");   

        Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);   

        return returnValue.booleanValue();   

    }   


    static public boolean removeBond(Class btClass, BluetoothDevice btDevice)   

            throws Exception   

    {   

        Method removeBondMethod = btClass.getMethod("removeBond");   

        Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);   

        return returnValue.booleanValue();   

    }   


    static public boolean setPin(Class btClass, BluetoothDevice btDevice,   

            String str) throws Exception   

    {   

        try   

        {   

            Method removeBondMethod = btClass.getDeclaredMethod("setPin",   

                    new Class[]   

                    {byte[].class});   

            Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,   

                    new Object[]   

                    {str.getBytes()});   

            Log.e("returnValue", "" + returnValue);   

        }   

        catch (SecurityException e)   

        {   

            // throw new RuntimeException(e.getMessage());   

            e.printStackTrace();   

        }   

        catch (IllegalArgumentException e)   

        {   

            // throw new RuntimeException(e.getMessage());   

            e.printStackTrace();   

        }   

        catch (Exception e)   

        {   

            // TODO Auto-generated catch block   

            e.printStackTrace();   

        }   

        return true;   


    }   


    // 取消用户输入   

    static public boolean cancelPairingUserInput(Class btClass,   

            BluetoothDevice device)  throws Exception   

    {   

        Method createBondMethod = btClass.getMethod("cancelPairingUserInput");   

//        cancelBondProcess(btClass, device); 

        Boolean returnValue = (Boolean) createBondMethod.invoke(device);   

        return returnValue.booleanValue();   

    }   


    // 取消配对   

    static public boolean cancelBondProcess(Class btClass,   

            BluetoothDevice device)   


    throws Exception   

    {   

        Method createBondMethod = btClass.getMethod("cancelBondProcess");   

        Boolean returnValue = (Boolean) createBondMethod.invoke(device);   

        return returnValue.booleanValue();   

    } 


    //确认配对 


    static public void setPairingConfirmation(Class btClass,BluetoothDevice device,boolean isConfirm)throws Exception 

    { 

        Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation",boolean.class); 

        setPairingConfirmation.invoke(device,isConfirm); 

    } 

    /** 

    * 

    * @param clsShow 

    */   

    static 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)   

        {   

            // throw new RuntimeException(e.getMessage());   

            e.printStackTrace();   

        }   

        catch (IllegalArgumentException e)   

        {   

            // throw new RuntimeException(e.getMessage());   

            e.printStackTrace();   

        }   

        catch (Exception e)   

        {   

            // TODO Auto-generated catch block   

            e.printStackTrace();   

        }   

    }   

4.配对的相关广播,查询配对状态,根据这些时机插入需要处理的事件,

顺便把广播的使用方式贴出来:

filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);

filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);

//filter.addAction(Intent.ACTION_POWER_CONNECTED);

//filter.addAction(Intent.ACTION_POWER_DISCONNECTED);

filter.addAction("android.bluetooth.device.action.PAIRING_REQUEST");

//filter.addAction("android.bluetooth.device.action.FOUND");

filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

//filter.addAction("android.bluetooth.adapter.action.STATE_CHANGED");

registerReceiver(myReceiver, filter);


private BroadcastReceiver myReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if(action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)){

        Log.d(TAG, "ACTION_USB_DEVICE_ATTACHED");//这个广播是当Android系统作为host插入USB设备的时候发出的

}else if(action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)){

        Log.d(TAG, "ACTION_USB_DEVICE_DETACHED");//拔出USB设备


}else if(action.equals(Intent.ACTION_POWER_CONNECTED)){

        Log.d(TAG, "ACTION_POWER_CONNECTED");

}else if(action.equals(Intent.ACTION_POWER_DISCONNECTED)){

        Log.d(TAG, "ACTION_POWER_DISCONNECTED");

}else if(action.equals("android.bluetooth.device.action.PAIRING_REQUEST")) //再次得到的action,会等于PAIRING_REQUEST 

        { 

            BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            Log.e(TAG, action); 

            if(btDevice.getAddress().equals(BTMAC))  //btDevice.getName().contains("HC-05")

            { 

                try { 

                    //1.确认配对 

                    ClsUtils.setPairingConfirmation(btDevice.getClass(), btDevice, true); 

                    //2.终止有序广播 

                    Log.i(TAG, "isOrderedBroadcast:"+isOrderedBroadcast()+",isInitialStickyBroadcast:"+isInitialStickyBroadcast()); 

                    abortBroadcast();//如果没有将广播终止,则会出现一个一闪而过的配对框。 

                    //3.调用setPin方法进行配对... 

                    boolean ret = ClsUtils.setPin(btDevice.getClass(), btDevice, BTPIN); 


                } catch (Exception e) { 

                    // TODO Auto-generated catch block 

                    e.printStackTrace(); 

                } 

            }else{ 

                Log.e(TAG, "NOT THE BT U WANT"); 

            }


        }else if(action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {

            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

            //String name = device.getName();

            //Log.d("aaa", "device name: " + name);

            int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);

            switch (state) {

                case BluetoothDevice.BOND_NONE:

                    Log.d(TAG, "BOND_NONE 删除配对");

                    break;

                case BluetoothDevice.BOND_BONDING:

                    Log.d(TAG, "BOND_BONDING 正在配对");

                    break;

                case BluetoothDevice.BOND_BONDED:

                    Log.d(TAG, "BOND_BONDED 配对成功");

                    break;

            }

        }else if(action.equals("android.bluetooth.adapter.action.STATE_CHANGED")){

        int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,

            BluetoothAdapter.ERROR);

    switch (state) {

        case BluetoothAdapter.STATE_OFF:

            //Log.d("aaa", "STATE_OFF 手机蓝牙关闭");

            break;

        case BluetoothAdapter.STATE_TURNING_OFF:

            //Log.d("aaa", "STATE_TURNING_OFF 手机蓝牙正在关闭");

            break;

        case BluetoothAdapter.STATE_ON:

            //Log.d(TAG, "STATE_ON"+s);

         break;

        case BluetoothAdapter.STATE_TURNING_ON:

            //Log.d("aaa", "STATE_TURNING_ON 手机蓝牙正在开启");

            break;

    }


        }else{

Log.d(TAG, action);

}

}

};


5.解配对方法:

try {

      // pair before connect   

          BluetoothDevice Vdevice = mAdapter2.getRemoteDevice(BTMAC);

      if (Vdevice.getBondState() == BluetoothDevice.BOND_BONDED) {   

              Method creMethod = BluetoothDevice.class.getMethod("removeBond");   

          Log.e(TAG, "removeBond");   

          creMethod.invoke(Vdevice);   

      } else {

      Log.e(TAG, "un paired");

      } 

    } catch (Exception e) {   

        // TODO: handle exception   

        e.printStackTrace();   

    }

三.连接

private int connect(String mac) {//这个返回int状态只是因为个人项目需要,可以自行修改

    Log.e("wwww", "start, was connect()? "+isConnection);

    if (!this.isConnection ) {

       mBluetoothDevice=mBluetoothAdapter.getRemoteDevice(mac);

        try {

        // 固定的UUID     串口通信profile

            final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";   

            UUID uuid = UUID.fromString(SPP_UUID);

        mBluetoothSocket = this.mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);

        mBluetoothSocket.connect();

            outputStream = mBluetoothSocket.getOutputStream();

            inputStream = mBluetoothSocket.getInputStream();

            SocketReadThread rt = new SocketReadThread();//这个用来等待接收对方的数据

            rt.setLocalSocket(inputStream, 1);

            Thread thread = new Thread(rt);

               thread.start();


            this.isConnection = true;

        } catch (Exception e) {

            System.out.println("1" + e);

            return -1;

        }

        Log.e("www", "连接成功!");

        return 0;

    } else {

        return 0;

    }

}

接收线程:

public class SocketReadThread implements Runnable

    {

    InputStream input;

    int inum = 1;//预留

        public void setLocalSocket(InputStream is, int num )

        {

        input = is;

        inum = num;

        }

        public void run()

        {

try {

            DataInputStream dis = new DataInputStream(input);

            byte[] bytes = new byte[1024];//1k

                int readnum=0;

            while ((readnum=dis.read(bytes)) != -1) {//阻塞

                 printHexString(TAG,bytes);//前面的文章有讲过这个方法

             }

} catch (IOException e) {

Log.d(TAG, "read duankai");

// TODO Auto-generated catch block

e.printStackTrace();

}

}   

}

四.发送数据

private boolean send(byte[] sendData) {//这个返回也是因为当时项目需要

    if (this.isConnection) {

        try {

            //byte[] data = sendData.getBytes();//"GBK"

            outputStream.write(sendData, 0, sendData.length);

            outputStream.flush();

            Log.e("com send", "send-flush");

        } catch (IOException e) {

        Log.e("com send", "send-", e);

        return false;

        }

        return true;

    } else {

    Log.e("com send", "not connection");

    return false;

    }

}

五.关闭资源

这些不使用的时候,没关闭也是很耗资源的,不能忘记哈

private void closeBtconnect() {

// TODO Auto-generated method stub

    try {

            if(outputStream!=null){

            outputStream.close();

            outputStream=null;

            }

            if(inputStream!=null){

            inputStream.close();

            inputStream=null;

            }

            if(mBluetoothSocket!=null){

            mBluetoothSocket.close();

            mBluetoothSocket=null;

            }


} catch (Exception e) {

// TODO: handle exception

}

        this.isConnection = false;

}

几个主要的功能API使用大概如此。就是这个后台不适合代码编排,简书需要改进才是。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容