藍牙開發我的總結文檔

 基本概念: 安卓平臺提供對藍牙的通信棧的支持,容許設別和其餘的設備進行無線傳輸數據。應用程序層經過安卓API來調用藍牙的相關功能,這些API使程序無線鏈接到藍牙設備,並擁有P2P或者多端無線鏈接的特性。 藍牙的功能: 一、掃描其餘藍牙設備 二、爲可配對的藍牙設備查詢藍牙適配器 三、創建RFCOMM通道(其實就是尼瑪的認證) 四、經過服務搜索來連接其餘的設備 五、與其餘的設備進行數據傳輸 六、管理多個鏈接 藍牙創建鏈接必需要求: 一、打開藍牙 二、查找附近已配對或可用設備 三、鏈接設備 四、設備間數據交互 首先,要操做藍牙,先要在AndroidManifest.xml里加入權限 <uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permissionandroid:name="android.permission.BLUETOOTH" /> Android全部關於藍牙開發的類都在android.bluetooth包下,只有8個類 1.BluetoothAdapter 藍牙適配器 直到咱們創建bluetoothSocket鏈接以前,都要不斷操做它BluetoothAdapter裏的方法不少,經常使用的有如下幾個:       cancelDiscovery() 根據字面意思,是取消發現,也就是說當咱們正在搜索設備的時候調用這個方法將再也不繼續搜索       disable()關閉藍牙       enable()打開藍牙,這個方法打開藍牙不會彈出提示,更多的時候咱們須要問下用戶是否打開,一下這兩行代碼一樣是打開藍牙,不過會提示用戶:       Intemtenabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);       startActivityForResult(enabler,reCode);//同startActivity(enabler);       getAddress()獲取本地藍牙地址       getDefaultAdapter()獲取默認BluetoothAdapter,實際上,也只有這一種方法獲取BluetoothAdapter       getName()獲取本地藍牙名稱       getRemoteDevice(String address)根據藍牙地址獲取遠程藍牙設備       getState()獲取本地藍牙適配器當前狀態(感受可能調試的時候更須要)       isDiscovering()判斷當前是否正在查找設備,是返回true       isEnabled()判斷藍牙是否打開,已打開返回true,不然,返回false       listenUsingRfcommWithServiceRecord(String name,UUID uuid)根據名稱,UUID建立並返回BluetoothServerSocket,這是建立BluetoothSocket服務器端的第一步       startDiscovery()開始搜索,這是搜索的第一步       使用BluetoothAdapter的startDiscovery()方法來搜索藍牙設備       startDiscovery()方法是一個異步方法,調用後會當即返回。該方法會進行對其餘藍牙設備的搜索,該過程會持續12秒。該方法調用後,搜索過程其實是在一個System Service中進行的,因此能夠調用cancelDiscovery()方法來中止搜索(該方法能夠在未執行discovery請求時調用)。       請求Discovery後,系統開始搜索藍牙設備,在這個過程當中,系統會發送如下三個廣播:       ACTION_DISCOVERY_START:開始搜索       ACTION_DISCOVERY_FINISHED:搜索結束       ACTION_FOUND:找到設備,這個Intent中包含兩個extra fields:EXTRA_DEVICE和EXTRA_CLASS,分別包含BluetooDevice和BluetoothClass。       咱們能夠本身註冊相應的BroadcastReceiver來接收響應的廣播,以便實現某些功能 2.BluetoothDevice    描述了一個藍牙設備        createRfcommSocketToServiceRecord(UUIDuuid)根據UUID建立並返回一個BluetoothSocket        getState() 藍牙狀態這裏要說一下,只有在 BluetoothAdapter.STATE_ON 狀態下才能夠監聽,具體能夠看andrid api;        這個方法也是咱們獲取BluetoothDevice的目的——建立BluetoothSocket        這個類其餘的方法,如getAddress(),getName(),同BluetoothAdapter 3.BluetoothServerSocket 這個類一種只有三個方法兩個重載的accept(),accept(inttimeout)二者的區別在於後面的方法指定了過期時間,須要注意的是,執行這兩個方法的時候,直到接收到了客戶端的請求(或是過時以後),都會阻塞線程,應該放在新線程裏運行! 還有一點須要注意的是,這兩個方法都返回一個BluetoothSocket,最後的鏈接也是服務器端與客戶端的兩個BluetoothSocket的鏈接        void    close()        Closes the object and release any system resources it holds.        void    connect()        Attempt to connect to a remote device.        InputStream    getInputStream()        Get the input stream associated with this socket.        OutputStream    getOutputStream()        Get the output stream associated with this socket.        BluetoothDevice    getRemoteDevice()        Get the remote device this socket is connecting, or connected, to.        獲取遠程設備,該套接字鏈接,或鏈接到---。        boolean    isConnected()        Get the connection status of this socket, ie, whether there is an active connection with remote device.        判斷當前的鏈接狀態 4.BluetoothSocket  跟BluetoothServerSocket相對,是客戶端一共5個方法,不出意外,都會用到       close(),關閉       connect()鏈接       getInptuStream()獲取輸入流       getOutputStream()獲取輸出流       getRemoteDevice()獲取遠程設備,這裏指的是獲取bluetoothSocket指定鏈接的那個遠程藍牙設備 五、BluetoothClass 表明一個描述了設備通用特性和功能的藍牙類。好比,一個藍牙類會指定皆如電話、計算機或耳機的通用設備類型,能夠提供皆如音頻或者電話的服務。 每一個藍牙類都是有0個或更多的服務類,以及一個設備類組成。設備類將被分解成主要和較小的設備類部分。 BluetoothClass 用做一個能粗略描述一個設備(好比關閉用戶界面上一個圖標的設備)的線索,但當藍牙服務事實上是被一個設備所支撐的時候,BluetoothClass的 介紹則不那麼可信任。精確的服務搜尋經過SDP請求來完成。當運用createRfcommSocketToServiceRecord(UUID) 和listenUsingRfcommWithServiceRecord(String, UUID)來建立RFCOMM端口的時候,SDP請求就會自動執行。 使用getBluetoothClass()方法來獲取爲遠程設備所提供的類。          兩個內部類:      class   BluetoothClass.Device             定義全部設備類的常量       class   BluetoothClass.Service       定義全部服務類的常量     公共方法:      public int describeContents () 描述包含在可封裝編組的表示中全部特殊對象的種類。         返回值 一個指示被Parcelabel所排列的特殊對象類型集合的位掩碼。     public boolean equals (Object o) 比較帶有特定目標的常量。若是他們相等則標示出來。 爲了保證其相等,o必須表明相同的對象,該對象做爲這個使用類依賴比較的常量。一般約定,該比較既要可移植又需靈活。     當且僅當o是一個做爲接收器(使用==操做符來作比較)的精確相同的對象是,這個對象的實現才返回true值。子類一般實現equals(Object)方法,這樣它纔會重視這兩個對象的類型和狀態。     一般約定,對於equals(Object)和hashCode() 方法,若是equals對於任意兩個對象返回真值,那麼hashCode()必須對這些對象返回相同的紙。這意味着對象的子類一般都覆蓋或者都不覆蓋這兩個方法。         參數         o   須要對比常量的對象     返回值         若是特定的對象和該對象相等則返回true,不然返回false。       public int getDeviceClass ()     返回BluetoothClass中的設備類部分(主要的和較小的)     從函數中返回的值能夠和在BluetoothClass.Device中的公共常量作比較,從而肯定哪一個設備類在這個藍牙類中是被編碼的。     返回值         設備類部分           public int getMajorDeviceClass ()     返回BluetoothClass中設備類的主要部分     從函數中返回的值能夠和在BluetoothClass.Device.Major中的公共常量作比較,從而肯定哪一個主要類在這個藍牙類中是被編碼的。     返回值     主要設備類部分       public boolean hasService (int service)          若是該指定服務類被BluetoothClass所支持,則返回true          在BluetoothClass.Service中,合法的服務類是公共常量,好比AUDIO類。          參數          service 合法服務類          返回值          若是該服務類可被支持,則返回true       public int hashCode ()          返回這個對象的整型哈希碼。按約定,任意兩個在equals(Object)中返回true的對象必須返回相同的哈希碼。這意味着對象的子類一般一般覆蓋或者都不覆蓋這兩個方法。          注意:除非同等對比信息發生改變,不然哈希碼不隨時間改變而改變。       public String toString ()       返回這個對象的字符串,該字符串包含精確且可讀的介紹。系統鼓勵子類去重寫該方法,而且提供了能對該對象的類型和數據進行重視的實現方法。默認的實現方法只是簡單地把類名、「@「符號和該對象hashCode()方法的16進制數鏈接起來(以下列所示的表達式):         public void writeToParcel (Parcel out, int flags)          將類的數據寫入外部提供的Parcel中         參數     out     對象須要被寫入的Parcel     flags  和對象須要如何被寫入有關的附加標誌。多是0,或者多是PARCELABLE_WRITE_RETURN_VALUE。 以上是藍牙主要操做的類 基本用法: 一、獲取本地藍牙適配器       BluetoothAdapter mAdapter= BluetoothAdapter.getDefaultAdapter(); 二、打開藍牙       if(!mAdapter.isEnabled()){       //彈出對話框提示用戶是後打開       Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);       startActivityForResult(enabler, REQUEST_ENABLE);       //不作提示,強行打開,此方法須要權限<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" />       // mAdapter.enable();     } 三、搜索設備    1)mAdapter.startDiscovery() 是第一步,可能你會發現沒有返回的藍牙設備    2)定義BroadcastReceiver,代碼以下     // 建立一個接收ACTION_FOUND廣播的BroadcastReceiver     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {             public void onReceive(Context context, Intent intent) {          String action = intent.getAction();         // 發現設備         if (BluetoothDevice.ACTION_FOUND.equals(action)) {             // 從Intent中獲取設備對象             BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);             // 將設備名稱和地址放入array adapter,以便在ListView中顯示             mArrayAdapter.add(device.getName() + "\n" + device.getAddress());         }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED                       .equals(action)) {                   if (mNewDevicesAdapter.getCount() == 0) {                       Log.v(TAG, "find over");                   }            }       };     // 註冊BroadcastReceiver     IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);     registerReceiver(mReceiver, filter); // 不要忘了以後解除綁定 四、創建鏈接,首先Android sdk(2.0以上版本)支持的藍牙鏈接是經過BluetoothSocket創建鏈接,服務器端(BluetoothServerSocket)和客戶端(BluetoothSocket)需指定一樣的UUID,才能創建鏈接,由於創建鏈接的方法會阻塞線程,因此服務器端和客戶端都應啓動新線程鏈接     1)服務器端:     //UUID格式通常是"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"可到         //http://www.uuidgenerator.com 申請     BluetoothServerSocket serverSocket = mAdapter. listenUsingRfcommWithServiceRecord(serverSocketName,UUID);     serverSocket.accept();     2)客戶端:     //經過BroadcastReceiver獲取了BLuetoothDevice     BluetoothSocket clienSocket=dcvice. createRfcommSocketToServiceRecord(UUID);     clienSocket.connect(); 五、數據傳遞,經過以上操做,就已經創建的BluetoothSocket鏈接了,數據傳遞是經過流     1)獲取流         inputStream = socket.getInputStream();         outputStream = socket.getOutputStream();     2)寫出、讀入(JAVA常規操做)         補充一下,使設備可以被搜索         Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);         startActivityForResult(enabler,REQUEST_DISCOVERABLE); 關於藍牙鏈接:     能夠直接用一下代碼進行鏈接:     final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";               UUID uuid = UUID.fromString(SPP_UUID);               BluetoothSocket socket;               socket = device.createInsecureRfcommSocketToServiceRecord(uuid);           adapter.cancelDiscovery();            socket.connect();       1.startDiscovey有可能啓動失敗     通常程序中會有兩步:開啓藍牙、開始尋找設備。順序執行了開啓藍牙-尋找設備的步驟,可是因爲藍牙尚未徹底打開,就開始尋找設備,致使尋找失敗。     解決辦法:     adapter = BluetoothAdapter.getDefaultAdapter();           if (adapter == null)      {               // 設備不支持藍牙            }           // 打開藍牙            if (!adapter.isEnabled()){                   adapter.enable();              adapter.cancelDiscovery();      }           // 尋找藍牙設備,android會將查找到的設備以廣播形式發出去            while (!adapter.startDiscovery()){              Log.e("BlueTooth", "嘗試失敗");              try {                      Thread.sleep(100);              } catch (InterruptedException e) {                      e.printStackTrace();              }      }      2.    接收數據轉換     使用socket.getInputStream接收到的數據是字節流,這樣的數據是無法分析的,因此不少狀況須要一個byte轉十六進制String的函數:     public static String bytesToHex(byte[] bytes) {          char[] hexChars = new char[bytes.length * 2];          for ( int j = 0; j < bytes.length; j++ ) {                  int v = bytes[j] & 0xFF;                  hexChars[j * 2] = hexArray[v >>> 4];                  hexChars[j * 2 + 1] = hexArray[v & 0x0F];          }          return new String(hexChars);     }
相關文章
相關標籤/搜索