Android學習筆記(九)藍牙設備

一、廢話

  就快過年了,公司還不給發年終獎!我都快到大街上討飯了,公司也不帶管我的!

二、正文

  藍牙是啥我就不再說了,因爲我肯定解釋不清楚藍牙是啥,有興趣請移步至百度百科

  在開始前我們需要準備好一部手機而不是模擬器,且手機已經打開調試模式並連接到電腦上。文中的本地設備均指我們自己的手機,而遠程設備則是指其他的設備(電腦、其他手機或者其他)。

  通常情況下,我們對藍牙的操作主要有:開啓和關閉藍牙、搜索周邊設備、能被周邊設備所發現、獲取配對設備、藍牙設備間的數據傳輸。

  1、打開藍牙(當然首先要確保你的手機是有藍牙設備的)

  藍牙設備主要分爲兩部分,一部分爲本地設備,另一部分爲遠程設備。

  • BluetoothAdapter——本地設備,對藍牙操作首先就需要有一個BluetoothAdapter實例。常用的幾個方法如下:
    •   cancelDiscovery()——取消本地藍牙設備的搜索操作,如果本地設備正在進行搜索,那麼調用該方法後將停止搜索操作。
    •   Disable()——關閉藍牙設備。
    •   Enable()——打開藍牙設備。相信大家都有過打開藍牙的經歷,一般情況下都會彈出一個窗口,說正在請求打開藍牙設備,你是不是允許云云。
    •   getAddress()——獲取藍牙設備的MAC地址。
    •   GetDefaultAdapter()——獲取本地的藍牙設備
    •   getName()——獲取本地藍牙的名稱
    •   getRemoteDevice(String address)——根據遠程設備的MAC地址來獲取遠程設備
    •   startDiscovery()——藍牙設備開始搜索周邊設備
  • BuletoothDevice——遠程設備。

    它所包含的方法和BluetoothAdapter一樣,不再累述。

按 Ctrl+C 複製代碼
View Code 
 // 獲取本地的藍牙適配器實例
             BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
             if(adapter!=null)
             {
                 if(!adapter.isEnabled())
                 {
                     //通過這個方法來請求打開我們的藍牙設備
                     Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                     startActivity(intent);
                 }
             }
             else
             {
                 System.out.println("本地設備驅動異常!");
             }
按 Ctrl+C 複製代碼

  2、搜索周邊設備

  對於Android查找發現藍牙設備使用BluetoothAdapter類的startDiscovery()方法就可以執行一個異步方式獲取周邊的藍牙設備,因爲是一個異步的方法所以我們不需要考慮線程被阻塞問題,整個過程大約需要12秒時間,這時我們可以註冊一個 BroadcastReceiver 對象來接收查找到的藍牙設備信息,我們通過Filter來過濾ACTION_FOUND這個 Intent動作以獲取每個遠程設備的詳細信息,通過Intent字段EXTRA_DEVICE 和 EXTRA_CLASS可以獲得包含了每個BluetoothDevice 對象和對象的該設備類型 BluetoothClass。

  實現一個自己的BroadCastReceiver類,並註冊這個類。

View Code
複製代碼
 1     private class BluetoothReciever extends BroadcastReceiver {
2
3 @Override
4 public void onReceive(Context context, Intent intent) {
5 // TODO Auto-generated method stub
6 String action = intent.getAction();
7 if (BluetoothDevice.ACTION_FOUND.equals(action)) {
8 BluetoothDevice device = intent
9 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
10 System.out.println(device.getAddress());
11 }
12 }
13
14 }
複製代碼
View Code
1         IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
2 bluetoothReceive = new BluetoothReciever();
3 registerReceiver(bluetoothReceive, intentFilter);

  因爲在註冊一個Receiver後,程序並不知道該何時去回收它,所以需要我們自己重寫Activity類的onDestroy()方法。

View Code
1     @Override
2 protected void onDestroy() {
3 // TODO Auto-generated method stub
4 unregisterReceiver(bluetoothReceive);
5 super.onDestroy();
6 }

  3、被周邊設備所發現  

  如果需要用戶確認操作,不需要獲取底層藍牙服務實例,可以通過一個Intent來傳遞ACTION_REQUEST_DISCOVERABLE參數, 這裏通過startActivity來請求開啓。

View Code

  4、配對

  配對操作呢,一般都是發現設備後,由我們人工來進行選擇後系統自動去配對。我們可以通過下面的方法來獲得配對的設備:

View Code
複製代碼
 1                 //通過getBondedDevices方法來獲取已經與本設備配對的設備
2 Set<BluetoothDevice> device= adapter.getBondedDevices();
3 if(device.size()>0)
4 {
5 for(Iterator iterator=device.iterator();iterator.hasNext();)
6 {
7 BluetoothDevice bluetoothDevice=(BluetoothDevice)iterator.next();
8 System.out.println(bluetoothDevice.getAddress());
9 }
10 }
複製代碼

  5、數據交換  

  在看過前面的啓動、發現/搜索、配對這些操作後,下面來說說數據傳輸的問題。

  在Android系統中,藍牙設備間的數據傳輸問題和我們在PC上的網絡編程頗爲類似,有一端作爲Server端監聽Client端的連接請求,在二者建立了連接後,就可以使用普通的數據傳輸方式進行數據交換操作了。在這個過程中,我需要使用到BluetoothServerSocket和BluetoothSocket兩個類來建立Server端和Client端,還需要使用到一些關於流(Stream)的知識。

  • BluetoothServerSocket——服務端(監聽端、監聽器、接受請求的一端)
    • Accept()——阻塞宿主線程,直至收到客戶端請求。返回BluetoothSocket對象。由於這個
    • Accept(int timeout)——阻塞宿主線程,直至收到客戶端請求或等待時間超過timeout。返回BluetoothSocket對象。
    • Close()——關閉BluetoothServerSocket監聽器。

  可以看到,Accept方法是一個阻塞方法,所以在進行開發的時候,一般都需要用到多線程的知識。JAVA的多線程知識,可以在JAVA的JDK幫助文檔中查看,就單純的應用來說還是比較簡單的。

  • BluetoothSocket——客戶端(請求端)
    • Close()——關閉BluetoothSocket請求端。
    • Connect()——主動向服務端(監聽端)發起連接請求。

  在瞭解了這兩個類後,可以着手來建立我們自己的Server端和Client端了。

  如果一個設備需要和兩個或多個設備連接時,就需要作爲一個server來傳輸,服務器端套接字在接受(accepted) 一個客戶發來的BluetoothSocket連接請求時作出相應的響應。服務器socket將監聽進入的連接請求,一旦連接被接受,將產生一個BluetoothSocket。

  • 創建一個Server

  使用BluetoothAdapter類的listenUsingRfcommWithServiceRecord方法來新建一個ServerSocket。在listenUsingRfcommWithServiceRecord中有一個參數叫做UUID,UUID(Universally Unique Identifier)是一個128位的字符串ID,被用於唯一標識我們的藍牙服務。你可以使用web上的任何一款UUID產生器爲你的程序獲取一個UUID,然後使用fromString(String)初始化一個UUID。

  使用ServerSocket實例的accept方法進行監聽,當監聽到帶有我們初始化的UUID參數的連接請求後作出響應,連接成功後返回一個BluetoothSocket對象。連接完成後,調用close方法關閉該Socket監聽。

View Code
  • 創建一個Client

  創建一個Client端,首先需要我們使用BluetoothDevice的實例的createRfcommSocketToServiceRecord方法來創建一個BluetoothSocket實例。在創建的時候,需要給createRfcommSocketToServiceRecord方法傳入我們服務端的UUID值。然後使用BluetoothSocket實例的Connect方法對Server端進行連接請求,當連接成功後,Client端和Server端的傳輸通道就被打開。最後在連接完成後使用該實例的close方法來關閉這個連接。

View Code

  getInputStream()——獲得一個可讀的流,該流在連接不成功的情況下依舊可以獲得,但是對其操作的話就會報IOException的異常。需要從外部獲取的數據都從該流中獲取。

  getOutputStrem()——獲得一個可寫的流,該流在連接不成功的情況下依舊可以獲得,但是對其操作的話就會報IOException的異常。需要往外部傳輸的數據都可以寫到該流中傳輸出去。

  數據傳輸的大致流程如下:

    • 首先,分別通過getInputStream()和getOutputStream()獲得管理數據傳輸的InputStream和OutputStream。
    • 然後,開闢一個線程專門用於數據的讀或寫。這是非常重要的,因爲read(byte[])和write(byte[])方法都是阻塞調用。read(byte[])從輸入流(InputStream)中讀取數據。write(byte[])將數據寫入到OutputStream流中去,這個方法一般不會阻塞,但當遠程設備的中間緩衝區已滿而對方沒有及時地調用read(byte[])時將會一直阻塞。所以,新開闢的線程中的主循環將一直用於從InputStream中讀取數據。

  還要補充一點,由於藍牙設備是系統設備,所以需要有相應的權限支持。在AndroidManifest.xml文件中添加上權限。

1     <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
2 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>

三、總結

  在這個筆記中將了下藍牙的一些簡單的操作,包括藍牙的開啓、搜索、配對等操作,同時還有數據的傳輸問題,關於數據的傳輸的相關操作最重要的其實是多線程的操作和數據流的操作,所以對這兩點不熟悉的同學可以去看看java的JDK幫助文檔。在下節中,將會將一些WIFI的操作,因爲WIFI內容不是很多,所以還將附加上一些Android網絡編程方面的內容。

 


作者:Libo@Deng 
出處:http://www.cnblogs.com/cxcco/ 
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。 
我的微博: 新浪微博

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章