Android——蓝牙通信

27 篇文章 0 订阅

最近想做一个项目,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 BroadcastReceiver
private 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和一个主线程传递过来的handle
public 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连接中断
     }
}

客户端通信

@Override
public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值