Android——蓝牙通信

来源:互联网 发布:greenvpn软件下载 编辑:程序博客网 时间:2024/04/30 23:47

最近想做一个项目,Android手表将采集到的数据实时的发送到手机上,选择的数据传递方式为蓝牙通信。由于暂时没有手表,所以在两台手机上进行实验。(最终的结果发现通信成功好像跟手机系统有关,后面会具体说道这个问题)

下面开始介绍系统蓝牙服务的使用,最要涉及到使用四个类:
BluetoothAdapter,BluetoothDevice,BluetoothServerSocket,BluetoothSocket.
发现了没,后面的两个类和java的ServerSocket.Socket很类似(不存在继承关系)。他们的用法大致都差不多,只不过创建的方式不一样(仅此而已)。所以在后面会发现一旦获得了BluetoothServerScoket和BluetoothSocket,就和普通的Sokcet编程一样

1.蓝牙的开启

//获得系统蓝牙服务BluetoothAdapter adapter=BluetoothAdpater.getDefaultAdapter();//判断蓝牙是否开启if(!adapter.isEnabled())  adapter.enable();//开启蓝牙//判断蓝牙是否设置为可被其他蓝牙设备发现if(!adapter.isDiscovering()){    Intent i=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//设置可被发现的时间    i.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,120000);}startActivity(i);//会弹出一个对话框,询问是否允许被发现adapter.startDiscovery();//开启被发现

2.查找设备
在上面的步骤执行完,开启了蓝牙之后,需要手机查找周围的蓝牙设备

//通过注册广播的方式,将查找的结果返回给当前的Activity,所以先需要定义一个BroadcastReceiver对象,也可以定义一个内部类继承自BroadcastReceiver(个人喜欢直接写匿名内部类)

private BroadcastReceiver receiver=new BroadcastReceiverprivate BroadcastReceiver receiver = new BroadcastReceiver(){     @Override     public void onReceiver(Contect  context,Intent intent){         //判断当前的动作是什么类型       if(intent.getAction()==BluetoothDevice.ACTION_FOUND);       //BluetoothDevices实现了可序列化接口,可以直接放在Intent中传递         BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);         //对于得到的deceive,可以获得它的名字等属性,将他们加入到List中显示,以及将deceive用List保存起来     }};//定义了BroadcastReceiver对象receiver,就可以来使用它来监听蓝牙查找情况IntentFilter intentFilter=new IntentFilter(BluetoothDevice.ACTION_FOUND);registerReceiver(receiver,intentFilter);//注册广播

3.创建BluetoothSocket
在上面通过注册广播的方式,我们可以得到周围的deceive信息。
通过的deceive来创建BluetoothSocket
有两种方式

  • 通过直接调用:
//UUID="00001101-0000-1000-8000-00805F9B34FB" BluetoothSocket socket=deceive.createRfcommSocketToServiceRecord(UUID.fromString(Config.UUID));
  • 利用反射的方式
Method method=device.getClass().getMethod("createRfcommSocket",new Class[]{int.class});socket=method.invoke(device,1);

4.获得BluetoothServerSocket
和获得BluetoothSocket一样两种方式
- 通过直接调用:

//UUID="00001101-0000-1000-8000-00805F9B34FB" BluetoothServerSocket serverSocket=bluetoothAdapter.listenUsingRfcommWithServiceRecord(UUID.fromString(Config.UUID));
  • 利用反射的方式
Method method=bluetoothAdapter.getClass().getMethod("listenUsingRfcommOn",new Class[]{int.class});serverSocket=method.invoke(bluetoothAdapter,1);

进行客户端服务端通信

  • 服务端需要向获得一个BluetoothServerSocket,上面已经介绍了怎么获取
    按照Socket编程的一般方式进行处理即可
//开启一个线程,监听是否有客户端连接(我是将通信放在一个单独的类里,这个类继承自Thread类),run方法里处理,在初始化的时候已经得到bluetoothAdapter,bluetoothServerSocket和一个主线程传递过来的handlepublic void run(){  // boolean getSocket=false;全局变量   //获得服务端的socket   while(!getSocket){      socket=bluetoothServerSocket.accept();//是不是和将java Socket编程一样      if(socket!=null)      getSocket=true;   }   //开始读取数据   startReading();}//简单的写写读取过程,异常处理不写了private void startReading(){   while(isReading){//isReading全局变量       if(socket==null) break;       InputStream in=socket.getInputStremam();       byte[] bytes=new byte[in.available()];       if(in.read(bytes,0,in.available())>0){           //通过handle将读取到的数据发出去           Message msg=new Message();           msg.what=1;//1表示读取成功           msg.obj=new String(bytes);           handle.sendMessage(msg);       }       //注意read操作会阻塞子线程,所以最好sleep       sleep(100);//抛出异常    }}//写操作一样pulic void write(String str){     if(socket!=null){        OutputStream out=socket.getOutputStream();        byte[] bytes=str.getBytes();        out.write(bytes,0,bytes.length);        out.flush();        //注意不要关闭读写,可能导致socket连接中断     }}

客户端通信

@Overridepublic void run() {  try {      socket =device.createRfcommSocketToServiceRecord(UUID.fromString(Config.UUID));      socket.connect();  } catch (IOException e) {      e.printStackTrace();      Log.e("TAG", "socket 创建失败" + e.toString());      handler.sendEmptyMessage(Config.STATUES_CONNECT_FAILED);  }  if (socket.isConnected())      handler.sendEmptyMessage(Config.STATUES_CONNECT_SUCCESS);  else handler.sendEmptyMessage(Config.STATUES_CONNECT_FAILED);  while (isReading) {            try {                sleep(100);                if (socket == null) continue;                if (in == null)                    in = socket.getInputStream();                byte[] bytes = new byte[in.available()];                if (in.read(bytes,0,in.available()) > 0) {                    Message msg = new Message();                    msg.what = Config.STATUES_READ_SUCCESS;                    msg.obj = new String(bytes);                    handler.sendMessage(msg);                }            } catch (IOException e) {                e.printStackTrace();                handler.sendEmptyMessage(Config.STATUES_READ_FAILED);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }

存在的问题

  • 用BufferReader包装socket的输入流读取数据出错
  • 用发射的方法获取BluetoothServerSocket和BluetoothSocket出问题
  • 两台手机,一台华为的P6一台魅蓝note2,华为手机当服务端魅蓝当客户端没问题,但魅蓝但服务端就报错,说没有APN 系统权限之类的
0 0
原创粉丝点击