• 实现Android和PC之间的蓝牙通信(转载)


     原文链接:http://www.cnblogs.com/buptzym/archive/2011/09/07/2169858.html

      这两天想实现PC和安卓手机的通信,限于水平,知道的方法大概有两种:基于数据包的socket和蓝牙。虽然看起来简单,但调也调了两天多。自己测试了下socket,在室内WIFI环境下时延大概是0.1s。而在3G网络下时延居然达3s之多,而且只要不发数据,端口貌似就会断掉,总之,很不爽。于是,便考虑了蓝牙的方法。

      实现手机和PC的蓝牙通信,一种是最常用的蓝牙虚拟串口,这种方法可以通过配置非常简单地实现,很多外置蓝牙GPS都用这种做法。但大名鼎鼎的安卓却不支持,因此对大部分外置GPS都不提供支持(可能安卓手机大部分包含内置GPS,觉得外置的太鸡肋了)。因此必须采用第二种,蓝牙socket。

          在电脑上,实在不想去在C++下开发,于是便寻找.NET组件,但实际上微软的NET库中不支持蓝牙,因此必须采用第三方的控件,名字叫inthehand.

          这篇文章中详细的介绍了inthehan

    d组件,http://www.cnblogs.com/procoder/archive/2009/09/22/1571580.html。由于它讨论了实现文件传输的思路,我们在这篇文章中就只讨论简单的字符传输。

           它的官方网站是inthehand.net,其中多数的类库和方法都能找到。

     下面是手机端的初始化代码。其中的具体含义可参照http://android.tgbus.com/Android/tutorial/201103/346657.shtml

        private PrintStream mPrintStream = null;
    private BufferedReader mBufferedReader = null;

    BluetoothAdapter myBluetoothAdapter
    = null;
    BluetoothServerSocket mBThServer
    = null;
    BluetoothSocket mBTHSocket
    = null;


    myBluetoothAdapter
    = BluetoothAdapter.getDefaultAdapter();

    myBluetoothAdapter.enable();
    //open bth

    Intent discoverableIntent
    = new Intent(
    BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//使得蓝牙处于可发现模式,持续时间150s
    discoverableIntent.putExtra(
    BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
    150);

     下面是PC上的初始化核心代码:PC是作为客户端出现的。它需要通过搜索获取手机的蓝牙MAC地址,实现通信。GUID又名UUID,是标记硬件地址的一种方法。

       /// <summary>
            /// 打开端口
            /// </summary>
            /// <param name="Name">端口名称</param>
            /// <returns>成功否</returns>
            public bool OpenPort(string Name)
            {

                InTheHand.Net.Bluetooth.BluetoothRadio.PrimaryRadio.Mode = InTheHand.Net.Bluetooth.RadioMode.Connectable;
                InTheHand.Net.Sockets.BluetoothClient cli = new InTheHand.Net.Sockets.BluetoothClient();
                InTheHand.Net.Sockets.BluetoothDeviceInfo[] devices = cli.DiscoverDevices();
                foreach (InTheHand.Net.Sockets.BluetoothDeviceInfo device in devices)//设备搜寻
                {
                    device.Update();
                    device.Refresh();
                    MessageBox.Show("设备已找到");
                    break;
                }


                BluetoothDeviceInfo bd = new BluetoothDeviceInfo(devices[0].DeviceAddress);
                bluetoothClient = new BluetoothClient();


                Guid mGUID = Guid.Parse("fa87c0d0-afac-11de-8a39-0800200c9a66");
                bluetoothClient.Connect(devices[0].DeviceAddress, mGUID);//客户端对地址实现连接,这是一个阻塞线程,需要服务器端的回应

                ReceiveThread = new Thread(ReceiveMethod);
                ReceiveThread.Start();

                return true;
            }

            下面是手机接受PC端连接请求的方法:

    View Code
     1     if (connected)
    2 {
    3 return;
    4 }
    5 try
    6 {
    7 mBThServer = myBluetoothAdapter
    8 .listenUsingRfcommWithServiceRecord(NAME_SECURE,
    9 MY_UUID_SECURE);
    10 } catch (IOException e)
    11 {
    12 // TODO Auto-generated catch block
    13 e.printStackTrace();
    14 }
    15
    16 try
    17 {
    18 mBTHSocket = mBThServer.accept();
    19 } catch (IOException e)
    20 {
    21 // TODO Auto-generated catch block
    22 e.printStackTrace();
    23 }
    24 try
    25 {
    26 mBufferedReader = new BufferedReader(new InputStreamReader(
    27 mBTHSocket.getInputStream()));
    28 } catch (IOException e1)
    29 {
    30 // TODO Auto-generated catch block
    31 e1.printStackTrace();
    32 }// 取得输入、输出流
    33 try
    34 {
    35 mPrintStream = new PrintStream(
    36 mBTHSocket.getOutputStream(), true);
    37 connected = true;
    38 } catch (IOException e)
    39 {
    40 // TODO Auto-generated catch block
    41 e.printStackTrace();
    42 }

       要通过手机发送数据,执行以下代码即可:

            mPrintStream.write(buff);
    }
    catch (IOException e)
    {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    // 发送给服务器
    mPrintStream.flush();

        PC端的接受代码:

      while (isConnecting)
    {

    try
    {
    Stream peerStream
    = bluetoothClient.GetStream();
    peerStream.Read(buffer,
    0, PACKETLENGTH);
    //dataprocess();
    }

    catch (Exception ex)
    {
    isConnecting
    = false;
    MessageBox.Show(ex.ToString());

    }

      这里要注意以下几个小问题,但也就是这几个问题,耽误了我很久时间:

          inthehand.net.personal是PC端上一定要用得到的库,但注意这个库函数的版本,我一开始用了的dll是600K左右的,编译没问题,运行就会报错,提示找不到dll。但后来左思右想,才发现还有另外的一个同名dll,150K左右,换过来以后一切OK,太坑爹了!

            手机设备的蓝牙硬件权限要打开,否则就没法运行。

            还有我特想将手机做个蓝牙HID设备,但这样貌似是不行的。因为这个库本身提供的方法不够底层...总之还想再研究下。

            有任何问题欢迎讨论

  • 相关阅读:
    主键、外键、复合外键的创建
    DbHelper and OracleHelper
    Oracle 给表添加主键和使ID自增、触发器、创建结构一样的表
    Oracle 参数化更新数据时报错:Oracle ORA-01722: 无效数字
    ASP.NET MVC 基础
    5. CSS新特性之浏览器私有前缀
    JavaScript-----15.简单数据类型和复杂数据类型
    JavaScript-----14.内置对象 Array()和String()
    JavaScript-----13.内置对象 Math()和Date()
    JavaScript-----12.对象
  • 原文地址:https://www.cnblogs.com/liuliunumberone/p/2398565.html
Copyright © 2020-2023  润新知