Android蓝牙(二)

来源:互联网 发布:德云社 知乎 编辑:程序博客网 时间:2024/06/06 19:52

Android蓝牙开发(二)


有问题可以加群讨论:517018699
这里写图片描述

蓝牙官方文档
中文api

Android 可以通过Android BlueTooth访问蓝牙功能的途径,这些API允许应用以无线的形式连接到其他蓝牙,从而实现点到点和多点无线功能。

使用BlueTooth API,Android应用可以执行以下操作
* 扫描其他蓝牙设备
* 查询本地蓝牙适配器的配对蓝牙设备
* 建立RFCOMM通道
* 通过服务发现连接到其他设备
* 与其他设备进行双向数据传输
* 管理多个连接

Android蓝牙采用的是SDP协议进行通信,通信方式类似于平常使用的socket

权限

<!--需要硬件支持低功耗蓝牙--><uses-feature android:name"android.permission.BLUETOOTH_ADMIN"/><!--蓝牙权限--><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/><uses-permission android:name="android.permission.BLUETOOTH"/><!--Android 5.0以上蓝牙好需要位置权限--><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><uses-permission android:name="andriod.permission.ACCESS_FINE_LOCATION"/>

是的,你会发现使用蓝牙还需要位置权限?我开始也觉得一个蓝牙也要位置权限,后来在翻看官方文档的时候才知道的,不然你在5.0以上的手机上扫不出蓝牙的!详情请翻阅官方文档:

API提供的方法

在Android API里面提供了Bluetooth相关的类21个和一个接口

 1.BluetoothAdapter  2.BluetoothAssignedNumbers 3.BluetoothA2dp 4.BluetoothClass 5.BluetoothDevice 6.BluetoothGatt 7.BluetoothGattCallback 8.BluetoothGattCharacteristic 9.BluetoothGattDescriptor 10.BluetoothGattServer 11.BluetoothGattService 12.BluetoothGattServerCallback 13.BluetoothHeadset 14.BluetoothLeAdvertiser 15.BluetoothLeScanner 16.BluetoothManager 17.BluetoothHealth 18.BluetoothHealthAppConfiguration 19.BluetoothHealthCallback 20.BluetoothServerSocket 21.BluetoothSocket  22.BluetoothProfile          ----接口

日常开发中我们使用到的

BluetoothAdapter——蓝牙适配器
* 用于:建立蓝牙连接(bluetoothSocket)之前使用
* 提供方法:
* cancelDiscovery();——取消发现蓝牙设备
* disable()——关闭蓝牙
* enable()——打开蓝牙
* isEnabled()——判断本地蓝牙是否打开——true打开
* getAddress()——获取本地蓝牙地址
* getDefaultAdapter()——获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdapter
* getName()——获取本地蓝牙名称
* getRemoteDevice(String address)——根据蓝牙地址获取远程蓝牙设备
* getState()获取本地蓝牙是适配器当前状态
* isDiscovering()判断当前是否在查找设备——是返回true
* startDiscovery()——开始搜索
* listenUsingRfcommWithServiceRecord(String name,UUID uuid)根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步

BluetoothDevice——蓝牙设备

  • 提供方法:
    • createRfcommSocketToServiceRecord(UUIDuuid)根据UUID创建并返回一个BluetoothSocket
    • getState()蓝牙状态:只有在BluetoothAdapter.STATE_ON 状态下才可以监听
    • getName()——获取本地蓝牙名称
    • getAddress()——获取本地蓝牙地址

BluetoothServerSocket——服务端蓝牙通信
* 提供方法:
* 两个重载accept(),accept(inttimeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行!两个方法都返回一个BluetoothSocket,最后的连接也是服务器端与客户端的两个BluetoothSocket的连接
* close()——关闭!

BluetoothSocket——客户端蓝牙通信
* 提供方法:
* connect()——连接
* getInptuStream()——获取输入流
* getOutputStream()——获取输入流
* getRemoteDevice()——获取远程设备——这里指的是获取bluetoothSocket指定连接的那个远程蓝牙设备
* close()——关闭


获取蓝牙适配器

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if(mBluetoothAdapter==null){//改设备不支持蓝牙}

开启蓝牙

if(!mBluetoothAdapter.isEnabled()){  //弹出对话框提示用户是后打开  startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);private static final int REQUEST_BLUETOOTH_PERMISSION=10;private void requestBluetoothPermission(){  //判断系统版本  if (Build.VERSION.SDK_INT >= 23) {    //检测当前app是否拥有某个权限    int checkCallPhonePermission = ContextCompat.checkSelfPermission(this,         Manifest.permission.ACCESS_COARSE_LOCATION);    //判断这个权限是否已经授权过    if(checkCallPhonePermission != PackageManager.PERMISSION_GRANTED){      //判断是否需要 向用户解释,为什么要申请该权限      if(ActivityCompat.shouldShowRequestPermissionRationale(this,           Manifest.permission.ACCESS_COARSE_LOCATION))      ActivityCompat.requestPermissions(this ,new String[]          {Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_BLUETOOTH_PERMISSION);      return;    }else{    }  } else {  }}//接下来我们就可以静默开启蓝牙了:BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();mBluetoothAdapter.enable(); //开启//mBluetoothAdapter.disable(); //关闭}  

获取本地蓝牙信息

//获取本机蓝牙名称  String name = mBluetoothAdapter.getName();  //获取本机蓝牙地址  String address = mBluetoothAdapter.getAddress();  Log.d(TAG,"bluetooth name ="+name+" address ="+address);  //获取已配对蓝牙设备  Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();  Log.d(TAG, "bonded device size ="+devices.size());  for(BluetoothDevice bonddevice:devices){      Log.d(TAG, "bonded device name ="+bonddevice.getName()+" address"+bonddevice.getAddress());  } 

搜索设备——停止搜索

mBluetoothAdapter.startDiscovery();   //——————搜索mBluetoothAdapter.cancelDiscovery();  //——————停止搜索     public boolean isDiscovering ();//返回true——正处于扫描设备中

设置蓝牙可见性

/**有时候扫描不到某设备,这是因为该设备对外不可见或者距离远,需要设备该蓝牙可见,这样该才能被搜索到。*可见时间默认值为120s,最多可设置300。*/if (mBluetoothAdapter.isEnabled()) {      if (mBluetoothAdapter.getScanMode() !=               BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {          Intent discoverableIntent = new Intent(                  BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);          discoverableIntent.putExtra(                  BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120);          startActivity(discoverableIntent);      }  }  

监听扫描结果

/***通过广播接收者查看扫描到的蓝牙设备,每扫描到一个设备,系统都会发送此广播(BluetoothDevice.ACTION_FOUNDE)。*其中参数intent可以获取蓝牙设备BluetoothDevice。*/private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver(){          @Override          public void onReceive(Context context, Intent intent) {              String action = intent.getAction();              Log.d(TAG,"mBluetoothReceiver action ="+action);              if(BluetoothDevice.ACTION_FOUND.equals(action)){//每扫描到一个设备,系统都会发送此广播。                  //获取蓝牙设备                  BluetoothDevice scanDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                  if(scanDevice == null || scanDevice.getName() == null) return;                  Log.d(TAG, "name="+scanDevice.getName()+"address="+scanDevice.getAddress());                  //蓝牙设备名称                  String name = scanDevice.getName();                  if(name != null && name.equals(VnApplication.BLUETOOTH_NAME)){                      mBluetoothAdapter.cancelDiscovery();                      //取消扫描                      mProgressDialog.setTitle(getResources().getString                      (R.string.progress_connecting));           //连接到设备。                      mBlthChatUtil.connect(scanDevice);                  }              }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){              }          }      };

连接设备

 public BluetoothGatt connectGatt(Content content,boolean autoConnect,BluetoothGattCallback callback){   return(connectGatt(context,autoConnect,callback,TRANSPORT_AUTO)); } /**  *第一个 Context 就不说了;第二个参数 autoConnect 的解释是“是否直接连接到远程设备(false)或一旦远程设备可用即可自动连接(true)”;  *第三个参数也是上面提到的抽象类,这个类在连接过程中起到关键作用。最后方法会返回一个 BluetoothGatt 对象,后续我们通过这个对  *象可以重连、断开、关闭设备。贴下我例子中的连接方法:  */ /**  *连接设备,如果服务未开启或者地址为空的情况就返回false;  *如果地址存在是否连接成功取决于蓝牙底层  *@param address  *@return 是否连接到  */  @Override public boole connectDevice(String address){   if(address.equals(mAddress)&&mBluetoothGatt !=null){         return mBluetoothGatt.connect();     }  BluetoothDevice device=arshowBluetooth.getBluetoothAdaoter().             getRemoteDevice(address);   if(device ==null){      return fasle;   }   //false表示直接连接,ture表示远程设备可用之后连接   mBluetoothGatt=device.connectGatt(context,false,mGattCallback);   mAddress=address;   return true;      }

Android蓝牙自动配对

原创粉丝点击