Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 藍牙開發全面總結

Android 藍牙開發全面總結

編輯:關於Android編程

基本概念:

安卓平台提供對藍牙的通訊棧的支持,允許設別和其他的設備進行無線傳輸數據。應用程序層通過安卓API來調用藍牙的相關功

能,這些API使程序無線連接到藍牙設備,並擁有P2P或者多端無線連接的特性。

 

藍牙的功能:

1、掃描其他藍牙設備

2、為可配對的藍牙設備查詢藍牙適配器

3、建立RFCOMM通道

4、通過服務搜索來鏈接其他的設備

5、與其他的設備進行數據傳輸

6、管理多個連接



藍牙建立連接必須要求:

1、打開藍牙

2、查找附近已配對或可用設備

3、連接設備

4、設備間數據交換

 

 

常用的藍牙API如下:

 

BluetoothAdapter

代表本地藍牙適配器(藍牙無線電)。BluetoothAdapter是所有藍牙交互的入口。使用這個你可以發現其他藍牙設備,查詢已配對的設備列表,使用一個已知的MAC地址來實例化一個BluetoothDevice,以及創建一個BluetoothServerSocket來為監聽與其他設備的通信。

 

BlueDevice 代表一個遠程藍牙設備,使用這個來請求一個與遠程設備的BluetoothSocket連接,或者查詢關於設備名稱、地址、類和連接狀態等設備信息。 BluetoothSocket 代表一個藍牙socket的接口(和TCP Socket類似)。這是一個連接點,它允許一個應用與其他藍牙設備通過InputStream和OutputStream交換數據。 BluetoothServerSocket 代表一個開放的服務器socket,它監聽接受的請求(與TCP ServerSocket類似)。為了連接兩台Android設備,一個設備必須使用這個類開啟一個服務器socket。當一個遠程藍牙設備開始一個和該設備的連接請求,BluetoothServerSocket將會返回一個已連接的BluetoothSocket,接受該連接。

 

BluetoothAdapter 中常用方法如下所示:

boolean cancelDiscovery() Cancel the current device discovery process. static boolean checkBluetoothAddress(Stringaddress) Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"

Alphabetic characters must be uppercase to be valid.

void closeProfileProxy(int profile,BluetoothProfileproxy) Close the connection of the profile proxy to the Service. boolean disable() Turn off the local Bluetooth adapter—do not use without explicit user action to turn off Bluetooth. boolean enable() Turn on the local Bluetooth adapter—do not use without explicit user action to turn on Bluetooth. String getAddress() Returns the hardware address of the local Bluetooth adapter. Set<BluetoothDevice> getBondedDevices() Return the set ofBluetoothDeviceobjects that are bonded (paired) to the local adapter. synchronized staticBluetoothAdapter getDefaultAdapter() Get a handle to the default local Bluetooth adapter. String getName() Get the friendly Bluetooth name of the local Bluetooth adapter. int getProfileConnectionState(int profile) Get the current connection state of a profile. boolean getProfileProxy(Contextcontext,BluetoothProfile.ServiceListenerlistener, int profile) Get the profile proxy object associated with the profile. BluetoothDevice getRemoteDevice(byte[] address) Get aBluetoothDeviceobject for the given Bluetooth hardware address. BluetoothDevice getRemoteDevice(Stringaddress) Get aBluetoothDeviceobject for the given Bluetooth hardware address. int getScanMode() Get the current Bluetooth scan mode of the local Bluetooth adapter. int getState() Get the current state of the local Bluetooth adapter. boolean isDiscovering() Return true if the local Bluetooth adapter is currently in the device discovery process. boolean isEnabled() Return true if Bluetooth is currently enabled and ready for use. BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(Stringname,UUIDuuid) Create a listening, insecure RFCOMM Bluetooth socket with Service Record. BluetoothServerSocket listenUsingRfcommWithServiceRecord(Stringname,UUIDuuid) Create a listening, secure RFCOMM Bluetooth socket with Service Record. boolean setName(Stringname) Set the friendly Bluetooth name of the local Bluetooth adapter. boolean startDiscovery() Start the remote device discovery process. boolean startLeScan(BluetoothAdapter.LeScanCallbackcallback) Starts a scan for Bluetooth LE devices. boolean startLeScan(UUID[]serviceUuids,BluetoothAdapter.LeScanCallbackcallback) Starts a scan for Bluetooth LE devices, looking for devices that advertise given services. void stopLeScan(BluetoothAdapter.LeScanCallbackcallback) Stops an ongoing Bluetooth LE device scan.

 

BluetoothDevice 中常用方法如下所示:

BluetoothGatt connectGatt(Contextcontext, boolean autoConnect,BluetoothGattCallbackcallback) Connect to GATT Server hosted by this device. boolean createBond() Start the bonding (pairing) process with the remote device. BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUIDuuid) Create an RFCOMMBluetoothSocketsocket ready to start an insecure outgoing connection to this remote device using SDP lookup of uuid. BluetoothSocket createRfcommSocketToServiceRecord(UUIDuuid) Create an RFCOMMBluetoothSocketready to start a secure outgoing connection to this remote device using SDP lookup of uuid. int describeContents() Describe the kinds of special objects contained in this Parcelable's marshalled representation. boolean equals(Objecto) Compares this instance with the specified object and indicates if they are equal. boolean fetchUuidsWithSdp() Perform a service discovery on the remote device to get the UUIDs supported. String getAddress() Returns the hardware address of this BluetoothDevice. BluetoothClass getBluetoothClass() Get the Bluetooth class of the remote device. int getBondState() Get the bond state of the remote device. String getName() Get the friendly Bluetooth name of the remote device. int getType() Get the Bluetooth device type of the remote device. ParcelUuid[] getUuids() Returns the supported features (UUIDs) of the remote device. int hashCode() Returns an integer hash code for this object. boolean setPairingConfirmation(boolean confirm) Confirm passkey forPAIRING_VARIANT_PASSKEY_CONFIRMATIONpairing. boolean setPin(byte[] pin) Set the pin during pairing when the pairing method isPAIRING_VARIANT_PIN

RequiresBLUETOOTH_ADMIN.

String toString() Returns a string representation of this BluetoothDevice. void writeToParcel(Parcelout, int flags) Flatten this object in to a Parcel.

 

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.

 

BluetoothServerSocket 中常用方法如下所示:

BluetoothSocket accept(int timeout) Block until a connection is established, with timeout. BluetoothSocket accept() Block until a connection is established. void close() Immediately close this socket, and release all associated resources.

 

以上四個類貫穿於我們藍牙通信的全過程,包括藍牙搜索、配對、連接以及通信。

 

 

使用藍牙需要在配置文件Androidmanifest.xml 中注冊兩種權限:

其中,權限1在得到默認藍牙適配器時需要,即BluetoothAdapter mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter( )

權限2在mBluetoothAdapter.enable( )或者mBluetoothAdapter.disable( ) 時需要使用到。

 

 

一、藍牙搜索功能的實現:

 

1、得到藍牙適配器:

BluetoothAdapter mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();

若mBluetoothAdapter為 null,則說明當前手機不支持藍牙功能(現在幾乎所有手機都支持了吧。。。)

 

2、判斷藍牙是否打開:

if (!mBluetoothAdapter.isEnabled()) {
       //若沒打開則打開藍牙
       mBluetoothAdapter.enable();
  
}

值得注意的是,強制打開藍牙設備的情況有三種:

(1)沒有任何提示,直接打開了藍牙。如Nexus 5 Android 4.4.4 手機。

(2)會彈出提示框,提示安全警告 “ ***應用嘗試開啟藍牙”,可以選擇“拒絕”或“允許”。大多數手機都是這樣的。

(3)強制打開藍牙失敗,並且沒有任何提示。

 

 

3、注冊藍牙搜索廣播接收者:

(1)Android 的廣播機制:

Adnroid的廣播機制(以intent對象的形式廣播出去),Android系統廣播的時候不會關心你是否收得到消息、只負責廣播出去,而

且廣播的對象只是在應用程序中注冊了的廣播接收器。我們要做的就是自定義廣播接收器並將其注冊給應用程序,在廣播接收器中

將接收到廣播事件作出相應的處理。如果廣播的事件並不是我們定義的廣播接收器需要的事件類型,一般是會過濾掉不被接收。只

有當廣播事件和我們寫的接收器定義的接收的事件類型一致的時候才會觸發廣播接收器。並且觸發廣播接收器的onReceive方法。當

然我們自定義的廣播接收器需要接受事件的類型是在XML清單文件的中自己定義聲明的或者自己在程序代碼中定義一

個IntentFilter對象然後通過對象的addAction()方法來自定義接收事件類型。然後我們需要將接收到的事件的處理代碼寫在onReceive

方法中。

(2)注冊分為兩種:靜態注冊和動態注冊。

靜態注冊就是在AndroidManifest.xml文件中定義,注冊的廣播接收器必須繼承BroadReceiver動態注冊就是在程序中使用Context.registerReceiver注冊。

 

我們先演示動態注冊:

//注冊設備被發現時的廣播
IntentFilter filter=new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(mReceiver,filter);
//注冊一個搜索結束時的廣播
IntentFilter filter2=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(mReceiver,filter2);


對應的靜態注冊如下:


        
    		
        		
        		
    		
	


我們如何知道BluetoothAdapter.ACTION_DISCOVERY_FINISHED對應著android.bluetooth.adapter.action.DISCOVERY_FINISHED呢?

這就要看強大的API了。如圖就是一種對應關系:

\

此處推薦別人上傳的中文API:

點我打開Android中文API

 

 

4、定義廣播接收:

自定義的廣播接收器對象必須要繼承BroadcastReceiver,然後重寫onReceive方法,處理接收的數據的代碼就寫在這個方法裡面。

兩種方法:

自定義一個類實現BroadcastReceiver抽象類,並且實現其onReceiver(Context context, Intent intent )方法。直接new BroadcastReceiver()來搞定。

方法1如下:

public class BluetoothReceiver extends BroadcastReceiver{
        @Override
	public void onReceive(Context context, Intent intent) {

          ...................
       }

}

方法2如下:

 //定義廣播接收
    private BroadcastReceiver mReceiver=new BroadcastReceiver(){

        @Override
        public void onReceive(Context context, Intent intent) {
              .......................
                   }
    };


5、開始廣播:

通過 mBluetoothAdapter.startDiscovery( ); 來開始廣播。當廣播的事件是我們剛剛注冊的事件時就會觸發廣播接收器,並且觸

發廣播接收器中的onReceiver()方法。

 

6、解除注冊:

通過 unregisterReceiver(mReceiver); 來解除剛剛的注冊。

 

至此我們完成了藍牙通信的第一步:藍牙搜索。

下邊給出一個完整Demo實例。

功能為:點擊按鈕將搜索附近的藍牙設備,並且判斷是否與本設備已經配對,分類顯示。

代碼如下:

mainActivity.java

package com.example.administrator.myapplication;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    //定義
    private BluetoothAdapter mBluetoothAdapter;
    private TextView text,text2,text3;
    private Button botton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        text=(TextView) this.findViewById(R.id.textView);  //已配對
        text2= (TextView) this.findViewById(R.id.textView2); //狀態信息
        text3= (TextView) this.findViewById(R.id.textView3); //未配對
        botton=(Button) this.findViewById(R.id.button);

        mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();

        IntentFilter filter=new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(mReceiver,filter);
        IntentFilter filter2=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(mReceiver,filter2);

        botton.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View arg0) {

                if(!mBluetoothAdapter.isEnabled())
                {
                    mBluetoothAdapter.enable();

                }

                    mBluetoothAdapter.startDiscovery();
                    text2.setText("正在搜索...");

            }


        });


    }


    public void onDestroy() {

        super.onDestroy();
        //解除注冊
        unregisterReceiver(mReceiver);
        Log.e("destory","解除注冊");
    }



    //定義廣播接收
    private BroadcastReceiver mReceiver=new BroadcastReceiver(){



        @Override
        public void onReceive(Context context, Intent intent) {

            String action=intent.getAction();

            Log.e("ywq", action);
            if(action.equals(BluetoothDevice.ACTION_FOUND))
            {
                BluetoothDevice device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                if(device.getBondState()==BluetoothDevice.BOND_BONDED)
                {    //顯示已配對設備
                    text.append("\n"+device.getName()+"==>"+device.getAddress()+"\n");
                }else if(device.getBondState()!=BluetoothDevice.BOND_BONDED)
                {
                    text3.append("\n"+device.getName()+"==>"+device.getAddress()+"\n");
                }

            }else if(action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)){

                text2.setText("搜索完成...");


            }

        }


    };

}


AndroidManifest.xml代碼如下:




    
    

    
        
            
                

                
            
        
    

 

布局文件activity_main.xml代碼如下:



程序運行結果如下:

\

二、藍牙自動配對功能實現:

藍牙配對是建立連接的基礎和前提。為什麼不配對便無法建立連接?

任何無線通信技術都存在被監聽和破解的可能,藍牙SIG為了保證藍牙通信的安全性,采用認證的方式進行數據交互。同時為

了保證使用的方便性,以配對的形式完成兩個藍牙設備之間的首次通訊認證,經配對之後,隨後的通訊連接就不必每次都要做確

認。所以認證碼的產生是從配對開始的,經過配對,設備之間以PIN碼建立約定的link key用於產生初始認證碼,以用於以後建立的

連接。

所以如果不配對,兩個設備之間便無法建立認證關系,無法進行連接及其之後的操作,所以配對在一定程度上保證了藍牙通信

的安全,當然這個安全保證機制是比較容易被破解的,因為現在很多個人設備沒有人機接口,所以PIN碼都是固定的而且大都設置為

通用的0000或者1234之類的,所以很容易被猜到並進而建立配對和連接。

 

關於藍牙的自動配對,大家可以參考我的這篇博客:Android藍牙自動配對Demo,親測好使!!!

這裡自誇一下,這篇博客還是受到了大家的一些好評。該自動配對方法,博主在魅藍、華為、聯想、紅米以及Nexus手機上都有測

試過,使用的Android系統包括4.0+和5.0+,所以各位可以仔細閱讀該博客。

三、藍牙通信的實現:

藍牙通信分為Android 端藍牙設備之間的通信以及Android 端藍牙設備與其他藍牙設備之間的通信。

 

1、通信方式1:

Android手機端藍牙與Arduino外接HC-05藍牙模塊之間進行通信。

(待續......................)

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved