zoukankan      html  css  js  c++  java
  • android 蓝牙源码分析

    BluetoothService类中定义的Native方法都在android_server_BluetoothServer.cpp里建立jni调用

    一、开启(BT Turn on Turn off) (蓝牙的打开关闭由类BluetoothEnabler控制。)

    1.由BluetoothEnabler控制界面操作,在其构造函数里会先调用 LocalBluetoothManager.getInstance(context)。

    2.然后在LocalBluetoothManager类的getInstance函数里会调用当前类下的init()函数,该init()函数中通过BluetoothAdapter.getDefaultAdapter()获得蓝牙设备的句柄,如果当前没有蓝牙设备则返回null。 

    3.初始化完毕会监听checkbox的状态,当触发点击checkbox会响应onPreferenceChange方法,其中将调用 LocalBluetoothManager.setBluetoothEnabled(enable)方法。

    而LocalBluetoothManager.setBluetoothEnabled(enable)方法,会调用mAdapter.enable()方法,enable()方法又会调用 BluetoothService.enable()方法。其中,

    (1)打开(关闭)操作成功后会有一个异步事件ACTION_STATE_CHANGED返回,异步事件由类BluetoothEventRedirector控制(接收广播,进行处理)。在收到ACTION_STATE_CHANGED异步事件后,还需要做update本地设备profile的事情,读取上次关闭前搜索到的蓝牙设备。

    (1.1)update本地设备profile的事情:?

    (1.2)读取上次关闭前搜索到的蓝牙设备:

    通过LocalBluetoothManager.setBluetoothStateInt(int state)方法调到 CachedBluetoothDeviceManager.onBluetoothStateChanged方法来读取上次关闭之前搜索到device. 

    (2)来开启EnableThread线程,进行打开操作,蓝牙的打开关闭属于异步操作。

    ps:在启动蓝牙的时候,要注意的地方是不能正常启动蓝牙的情况,因为正常启动的时候会返回BluetoothIntent.ENABLED_ACTION 这个Intent,当时当启动出现异常的时候是没有Intent返回的,android使用回调函数来解决这个问题。下面是在bluetoothdeviceservice.java 里面enable(IBluetoothDeviceCallback callback 的过程:(以下代码属于较低版本的android源码,与较高版本源码中已有所不同,只作为参考...)

    View Code
      1 public synchronized boolean enable(IBluetoothDeviceCallback callback) {
      2         checkPermissionBluetoothAdmin();
      3         Log.d(TAG,"start enable! ");
      4         // Airplane mode can prevent Bluetooth radio from being turned on.
      5         if (mIsAirplaneSensitive && isAirplaneModeOn()) {
      6             return false;
      7         }
      8         if (mIsEnabled) {
      9             return false;
     10         }
     11         if (mEnableThread != null && mEnableThread.isAlive()) {
     12             return false;
     13         }
     14    //   主要的启动过程是放在一个新起的线程里面,但是不管能不能启动 
     15    //    仍然返回了true
     16         mEnableThread = new EnableThread(callback);
     17         mEnableThread.start();
     18       //   
     19         return true;
     20   
     21         }
     22    
     23     private EnableThread mEnableThread;
     24     private class EnableThread extends Thread {
     25         private final IBluetoothDeviceCallback mEnableCallback;
     26         public EnableThread(IBluetoothDeviceCallback callback) {
     27             mEnableCallback = callback;
     28         }
     29         public void run() {
     30             boolean res = enableNative();
     31             if (res) {
     32                 mEventLoop.start();
     33             }
     34 
     35             if (mEnableCallback != null) {
     36                 try {
     37                  
     38                     // 通过回调函数来表明是否正常启动蓝牙设备
     39                     mEnableCallback.onEnableResult(res ?
     40                                                    BluetoothDevice.RESULT_SUCCESS :
     41                                                    BluetoothDevice.RESULT_FAILURE);
     42                 } catch (RemoteException e) {}
     43             }
     44 
     45             if (res) {
     46                 mIsEnabled = true;
     47                 mIsDiscovering = false;
     48 
     49                 Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION);
     50                 mContext.sendBroadcast(intent);
     51                 }
     52             }else{
     53                 mIsEnabled = false;
     54                 mIsDiscovering = false;
     55             }
     56             mEnableThread = null;
     57         }
     58 }
     59 
     60 
     61 
     62 
     63 
     64     
     65 
     66 //  这个回调函数将被作为参数传进bluetoothservice 里面的enable(IBluetoothDeviceCallback callback)
     67 static class DeviceCallback extends IBluetoothDeviceCallback.Stub {
     68         Handler messageHandler;
     69 
     70         public void setHandler(Handler handler) {
     71             synchronized (this) {
     72                 messageHandler = handler;
     73             }
     74    
     75    
     76         public void onEnableResult(int result) {
     77             switch(result) {
     78 
     79   //  启动不成功的时候执行
     80                 case BluetoothDevice.RESULT_FAILURE:
     81                      messageHandler.sendMessage(messageHandler.obtainMessage(EVENT_FAILED_BT_ENABLE,0));
     82                     break;
     83             }
     84         }
     85        
     86 
     87 //   配对完成时执行
     88 public void onCreateBondingResult(String address, int result) {
     89             synchronized (this) {
     90                 if (messageHandler != null) {
     91                     if (result == BluetoothDevice.RESULT_FAILURE) {
     92                         messageHandler.sendMessage(messageHandler.obtainMessage(
     93                                 HANDLE_PAIRING_FAILED, address));
     94                     } else {
     95                         messageHandler.sendMessage(messageHandler.obtainMessage(
     96                                 HANDLE_PAIRING_PASSED, address));
     97                     }
     98                 }
     99             }
    100         }
    101 
    102     }

    涉及到的类: 

    BluetoothService(最主要的类,开启具体命令的线程进行enable,disable等操作) 
    LocalBluetoothManager(本机蓝牙设备管理,开启关闭,搜索等等,初始化BluetoothAdapter) 
    BluetoothEnabler(界面的点击和状态文字的显示) 
    BluetoothAdapter(framework封装的类,提供本地蓝牙设备的配置,包括开启蓝牙,搜索周围蓝牙设备,设置本地蓝牙可见性;建立LocalBluetoothManager和BluetoothService的映射关系,主要是通过它调用BluetoothService的函数)

    BluetoothEventRedirector(接收Bluetooth API 的广播和回调,并且将Settings中的UI线程上的事件分派到正确的类)

     

    二、可检测性(Discoverable)

    1.蓝牙的discoverable mode由类BluetoothDiscoverableEnabler控制。点击将触发OnPreferenceChangeListener监听事件,调用onPreferenceChange()方法,该方法中调用setEnabled(true),而setEnabled(true)方法将调用到BluetoothAdapter的setScanMode () 方法。

    蓝牙模式有两种模式SCAN_MODE_CONNECTABLE_DISCOVERABLE(可连接可发现)和SCAN_MODE_CONNECTABLE(可连接但不可发现)

     
    涉及到的类:
    LocalBluetoothManager 
    BluetoothDiscoverableEnabler 
    BluetoothAdapter

     

    三、扫描 

    1.在BluetoothSetting里触发点击,调用LocalBluetoothManager.startScanning(true)函数,通过BluetoothAdapter的startDiscovery调用到BluetoothService里的startDiscovery来调用Native函数 startDiscoveryNative()。 

    startDiscovery()是个异步函数,会立即返回,通过注册 ACTION_DISCOVERY_STARTED、ACTION_DISCOVERY_FINISHED、ACTION_FOUND,来确定当前的状态。 

    当蓝牙由disable变成enable时会调用扫描,当距离上次扫描超过5分钟的前提下,退出页面,再进到页面的时候也会启动扫描。 

    在启动scan的时候,还会判断当前是否在播放音乐,如果在播放音乐,则不启动扫描。 

    点击查找设备后,会把设备列表里没有配对的设备清除掉,保留配对状态的设备。

    扫描的过程是一个很耗费资源的过程,在扫描过程,不会去尝试进行新的连接,扫描时间默认是12秒,它是以一个系统服务的形式存在的,可以调用cancelDiscovery()来取消扫描。 

     

    四、连接 

    1.1 在setting界面点击连接,会调到CachedBluetoothDevice类的connect方法。

    1.2 而connect方法会调用connectWithoutResettingTimer()方法。

    1.3 而connectWithoutResettingTimer()方法会调用 connectInt方法。

    在connectInt里,根据不同的profile来获得profilemanger,然后调用 profilemanger.connect()函数 。此处的链接会涉及到的profile有A2DP AVRCP DUN HSP HFP 等。

    同理如果配对或者解除配对,也会调到CachedBluetoothDevice类的pair()方法和unpair()。

     

    以A2DP为例,在connectInt里,根据不同的profile来获得profilemanger,然后调用 profilemanger.connect()函数,在这个函数里调用了BluetoothA2dpService的connectSink()函数,最后调到Native方法

    connectSinkNative()去建立连接。 

    涉及到的一些类: 

    CachedBluetoothDevice(搜索到的设备) 
    BluetoothDevice(设备类) 
    LocalBluetoothProfileManager(是一个抽象类,各种ProfileManger,实例化各种Profile的service) 
    SettingsBtStatus(蓝牙的状态类) 
    BluetoothA2dp(为LocalBluetoothProfileManager和BluetoothA2dpService建立映射关系) 
    BluetoothA2dpService(最终的服务类,由它调用连接、断开等Native函数,和底层通信)

     

    其他文件作用(接收与发送类似)

    1.BluetoothOppReceiver.java 这个类里描述的是蓝牙传输文件过程中接收到的广播事件。

    2.BluetoothOppTransfer.java 管理文件传输的类

    3. BluetoothOppService.java 蓝牙传输文件后台的类

    4. BluetoothOppObexClientSession.java 具体实现文件传输的类

     

    通过源码分析蓝牙执行过程:(Bluetooth--->BT)
    1、开启
    
    步骤1:首先从BTSettings开始,执行onCreate方法。因为是初始化状态,所以if(action.equal(BTDevicePicker.ACTION_LAUNCH))不满足,故执行else语句。
    
    步骤2:初始化mEnable对象,调用BTEnable构造函数。通过LocalBTManager.getInstance调用init方法,再通过init方法调用BTAdapter.getDefaultAdapter()获得适配器句柄。
    
    步骤3:各种初始化完毕后,执行BTSettings中的onResume方法,调用BTEnabler.resume方法,该resume方法为组合框设置监听事件。
    
    步骤4:当蓝牙开启时,该组合框被选中,将响应监听事件,执行BTEnabler.onPreferenceChange方法。该方法中会调用LocalBTManager.setBTEnabled方法。而setBTEnabled方法会调用BTAdapter.enable()方法,继而调用BTService.enable()方法,继而调用BTService.enable(true)方法。在该方法中,
    
    (1)当enable(true)方法返回true时,在setBTEnabled方法中会调用BTService中的setBTStateInt方法,继而广播出去,由BTEventRedirector类接收。
    
    (2)开启新的线程,主要的启动过程是放在这个新启动的线程里面。
    
    (3)开启蓝牙后,会调用CachedBTDeviceManager.onBTStateChanged方法来读取上次关闭前搜索到的蓝牙设备。
    
    2.可检测的
    
    点击“可检测性”组合框,将触发BTDiscoverableEnabler.onPreferenceChange方法,然后调用同个类中的setEnabled方法,来调用BTAdapter.setScanMode方法(其中传递SCAN_MODE_CONNECTABLE_DISCOVERABLE参数),继而会调用BTService.setScanMode方法,在该方法中,会通过setDiscoverableTimeout方法设置检测时间。
    
    3.扫描
    
    BTSettings的onResume方法继续往下运行,将调用LocalBTManager.startScanning方法,该方法会调用BTAdapter.startDiscovery方法,继而调用BTService.startDiscovery方法,再调用startDIscoveryNative方法。
    
    4.连接
    
    步骤1:在setting界面点击连接,会调到CachedBluetoothDevice类的connect方法。
    
    步骤2:而connect方法会调用connectWithoutResettingTimer()方法。
    
    步骤3:而connectWithoutResettingTimer()方法会调用 connectInt方法。
    
    步骤4:在connectInt里,根据不同的profile来获得profilemanger,然后调用 profilemanger.connect()函数 。此处的链接会涉及到的profile有A2DP AVRCP DUN HSP HFP 等。
    
    同理如果配对或者解除配对,也会调到CachedBluetoothDevice类的pair()方法和unpair()。
    

      

     

     

  • 相关阅读:
    iOS-mac下 svn的使用
    iOS-Model-View-ViewModel & ReactiveCocoa
    iOS-通过实现一个TableView来理解iOS UI编程(转)
    iOS-细说 iOS 消息推送(转)
    【原创】O2O,你真的知道怎么玩吗?
    谷歌提升虚拟运营商逼格,传统电信运营商的好日子到头?
    【技术贴】大型发布会现场的WiFi网络应该如何搭建?
    千万别把WIFI玩坏了!关于WIFI的新鲜玩法和商业模式探讨
    【深度分享】千团大战:看今天商业WiFi乱局及其破解之道
    (转)迎接 Entity Framework 7
  • 原文地址:https://www.cnblogs.com/chenbin7/p/2608135.html
Copyright © 2011-2022 走看看