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源码,与较高版本源码中已有所不同,只作为参考...)

 

001 View Code
002  public synchronized boolean enable(IBluetoothDeviceCallback callback) {
003          checkPermissionBluetoothAdmin();
004          Log.d(TAG,"start enable! ");
005          // Airplane mode can prevent Bluetooth radio from being turned on.
006          if (mIsAirplaneSensitive && isAirplaneModeOn()) {
007              return false;
008          }
009          if (mIsEnabled) {
010              return false;
011          }
012          if (mEnableThread != null && mEnableThread.isAlive()) {
013              return false;
014          }
015     //   主要的启动过程是放在一个新起的线程里面,但是不管能不能启动
016     //    仍然返回了true
017          mEnableThread = new EnableThread(callback);
018          mEnableThread.start();
019        //  
020          return true;
021     
022          }
023      
024      private EnableThread mEnableThread;
025      private class EnableThread extends Thread {
026          private final IBluetoothDeviceCallback mEnableCallback;
027          public EnableThread(IBluetoothDeviceCallback callback) {
028              mEnableCallback = callback;
029          }
030          public void run() {
031              boolean res = enableNative();
032              if (res) {
033                  mEventLoop.start();
034              }
035   
036              if (mEnableCallback != null) {
037                  try {
038                    
039                      // 通过回调函数来表明是否正常启动蓝牙设备
040                      mEnableCallback.onEnableResult(res ?
041                                                     BluetoothDevice.RESULT_SUCCESS :
042                                                     BluetoothDevice.RESULT_FAILURE);
043                  catch (RemoteException e) {}
044              }
045   
046              if (res) {
047                  mIsEnabled = true;
048                  mIsDiscovering = false;
049   
050                  Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION);
051                  mContext.sendBroadcast(intent);
052                  }
053              }else{
054                  mIsEnabled = false;
055                  mIsDiscovering = false;
056              }
057              mEnableThread = null;
058          }
059  }
060   
061   
062   
063   
064   
065       
066   
067  //  这个回调函数将被作为参数传进bluetoothservice 里面的enable(IBluetoothDeviceCallback callback)
068  static class DeviceCallback extends IBluetoothDeviceCallback.Stub {
069          Handler messageHandler;
070   
071          public void setHandler(Handler handler) {
072              synchronized (this) {
073                  messageHandler = handler;
074              }
075      
076      
077          public void onEnableResult(int result) {
078              switch(result) {
079   
080    //  启动不成功的时候执行
081                  case BluetoothDevice.RESULT_FAILURE:
082                       messageHandler.sendMessage(messageHandler.obtainMessage(EVENT_FAILED_BT_ENABLE,0));
083                      break;
084              }
085          }
086          
087   
088  //   配对完成时执行
089  public void onCreateBondingResult(String address, int result) {
090              synchronized (this) {
091                  if (messageHandler != null) {
092                      if (result == BluetoothDevice.RESULT_FAILURE) {
093                          messageHandler.sendMessage(messageHandler.obtainMessage(
094                                  HANDLE_PAIRING_FAILED, address));
095                      else {
096                          messageHandler.sendMessage(messageHandler.obtainMessage(
097                                  HANDLE_PAIRING_PASSED, address));
098                      }
099                  }
100              }
101          }
102   
103      }

涉及到的类: 

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 具体实现文件传输的类

 

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()。

 

### 安装LibreOffice于无外网连接的Linux系统 #### 准备工作 对于在没有互联网连接的情况下安装LibreOffice,在离线环境中操作前需确认目标系统的具体发行版,例如CentOS、Ubuntu或Debian等[^1]。这一步骤至关重要,因为不同版本的操作系统可能需要特定配置或是依赖库。 #### 下载所需文件 为了顺利完成安装过程,建议先在一个有网络访问权限的机器上登录LibreOffice官方网站,依据所使用的操作系统环境挑选相匹配的软件包组合。通常情况下,除了主要的应用程序包之外,还需要额外获取中文语言支持以及帮助文档的相关资源,并将这些压缩文件传输至待部署的目标设备上的`/opt`目录下[^3]。 #### 解压并设置环境变量 一旦所有必需的数据都被安全转移过来之后,则可利用命令行工具解压缩已下载好的档案: ```bash tar -xvf LibreOffice_*.tar.gz -C /opt/ ``` 接着创建指向新安装位置的链接以便后续调用更加便捷: ```bash ln -s /opt/LibreOffice_* /opt/libreoffice ``` 最后更新共享库缓存使新增加的内容生效: ```bash ldconfig ``` #### 配置桌面集成 为了让应用程序更好地融入现有的图形界面当中去,还需执行如下指令来完成最终设定: ```bash /opt/libreoffice/program/setup.bin --nodefaultlinktarget --nologo --norestore ``` 通过上述一系列措施即可实现在不具备公网接入条件下的Linux平台上成功部署LibreOffice办公套件的目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值