Android藍牙(二)

Android藍牙開發(二)


有問題可以加羣討論:517018699
這裏寫圖片描述

藍牙官方文檔
中文api

Android 可以通過Android BlueTooth訪問藍牙功能的途徑,這些API允許應用以無線的形式連接到其他藍牙,從而實現點到點和多點無線功能。

使用BlueTooth API,Android應用可以執行以下操作
* 掃描其他藍牙設備
* 查詢本地藍牙適配器的配對藍牙設備
* 建立RFCOMM通道
* 通過服務發現連接到其他設備
* 與其他設備進行雙向數據傳輸
* 管理多個連接

Android藍牙採用的是SDP協議進行通信,通信方式類似於平常使用的socket

權限

<!--需要硬件支持低功耗藍牙-->
<uses-feature android:name"android.permission.BLUETOOTH_ADMIN"/>
<!--藍牙權限-->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<!--Android 5.0以上藍牙好需要位置權限-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="andriod.permission.ACCESS_FINE_LOCATION"/>

是的,你會發現使用藍牙還需要位置權限?我開始也覺得一個藍牙也要位置權限,後來在翻看官方文檔的時候才知道的,不然你在5.0以上的手機上掃不出藍牙的!詳情請翻閱官方文檔

API提供的方法

在Android API裏面提供了Bluetooth相關的類21個和一個接口

 1.BluetoothAdapter 
 2.BluetoothAssignedNumbers
 3.BluetoothA2dp
 4.BluetoothClass
 5.BluetoothDevice
 6.BluetoothGatt
 7.BluetoothGattCallback
 8.BluetoothGattCharacteristic
 9.BluetoothGattDescriptor
 10.BluetoothGattServer
 11.BluetoothGattService
 12.BluetoothGattServerCallback
 13.BluetoothHeadset
 14.BluetoothLeAdvertiser
 15.BluetoothLeScanner
 16.BluetoothManager
 17.BluetoothHealth
 18.BluetoothHealthAppConfiguration
 19.BluetoothHealthCallback
 20.BluetoothServerSocket
 21.BluetoothSocket 

 22.BluetoothProfile          ----接口

日常開發中我們使用到的

BluetoothAdapter——藍牙適配器
* 用於:建立藍牙連接(bluetoothSocket)之前使用
* 提供方法:
* cancelDiscovery();——取消發現藍牙設備
* disable()——關閉藍牙
* enable()——打開藍牙
* isEnabled()——判斷本地藍牙是否打開——true打開
* getAddress()——獲取本地藍牙地址
* getDefaultAdapter()——獲取默認BluetoothAdapter,實際上,也只有這一種方法獲取BluetoothAdapter
* getName()——獲取本地藍牙名稱
* getRemoteDevice(String address)——根據藍牙地址獲取遠程藍牙設備
* getState()獲取本地藍牙是適配器當前狀態
* isDiscovering()判斷當前是否在查找設備——是返回true
* startDiscovery()——開始搜索
* listenUsingRfcommWithServiceRecord(String name,UUID uuid)根據名稱,UUID創建並返回BluetoothServerSocket,這是創建BluetoothSocket服務器端的第一步

BluetoothDevice——藍牙設備

  • 提供方法:
    • createRfcommSocketToServiceRecord(UUIDuuid)根據UUID創建並返回一個BluetoothSocket
    • getState()藍牙狀態:只有在BluetoothAdapter.STATE_ON 狀態下纔可以監聽
    • getName()——獲取本地藍牙名稱
    • getAddress()——獲取本地藍牙地址

BluetoothServerSocket——服務端藍牙通信
* 提供方法:
* 兩個重載accept(),accept(inttimeout)兩者的區別在於後面的方法指定了過時時間,需要注意的是,執行這兩個方法的時候,直到接收到了客戶端的請求(或是過期之後),都會阻塞線程,應該放在新線程裏運行!兩個方法都返回一個BluetoothSocket,最後的連接也是服務器端與客戶端的兩個BluetoothSocket的連接
* close()——關閉!

BluetoothSocket——客戶端藍牙通信
* 提供方法:
* connect()——連接
* getInptuStream()——獲取輸入流
* getOutputStream()——獲取輸入流
* getRemoteDevice()——獲取遠程設備——這裏指的是獲取bluetoothSocket指定連接的那個遠程藍牙設備
* close()——關閉


獲取藍牙適配器

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
if(mBluetoothAdapter==null){
//改設備不支持藍牙
}

開啓藍牙

if(!mBluetoothAdapter.isEnabled()){  
//彈出對話框提示用戶是後打開  
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);
private static final int REQUEST_BLUETOOTH_PERMISSION=10;

private void requestBluetoothPermission(){
  //判斷系統版本
  if (Build.VERSION.SDK_INT >= 23) {
    //檢測當前app是否擁有某個權限
    int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, 
        Manifest.permission.ACCESS_COARSE_LOCATION);
    //判斷這個權限是否已經授權過
    if(checkCallPhonePermission != PackageManager.PERMISSION_GRANTED){
      //判斷是否需要 向用戶解釋,爲什麼要申請該權限
      if(ActivityCompat.shouldShowRequestPermissionRationale(this, 
          Manifest.permission.ACCESS_COARSE_LOCATION))
      ActivityCompat.requestPermissions(this ,new String[]
          {Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_BLUETOOTH_PERMISSION);
      return;
    }else{
    }
  } else {
  }
}
//接下來我們就可以靜默開啓藍牙了:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.enable(); //開啓
//mBluetoothAdapter.disable(); //關閉

}  

獲取本地藍牙信息

//獲取本機藍牙名稱  
String name = mBluetoothAdapter.getName();  
//獲取本機藍牙地址  
String address = mBluetoothAdapter.getAddress();  
Log.d(TAG,"bluetooth name ="+name+" address ="+address);  
//獲取已配對藍牙設備  
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();  
Log.d(TAG, "bonded device size ="+devices.size());  
for(BluetoothDevice bonddevice:devices){  
    Log.d(TAG, "bonded device name ="+bonddevice.getName()+" address"+bonddevice.getAddress());  
} 

搜索設備——停止搜索


mBluetoothAdapter.startDiscovery();   //——————搜索
mBluetoothAdapter.cancelDiscovery();  //——————停止搜索
     public boolean isDiscovering ();//返回true——正處於掃描設備中

設置藍牙可見性

/*
*有時候掃描不到某設備,這是因爲該設備對外不可見或者距離遠,需要設備該藍牙可見,這樣該才能被搜索到。
*可見時間默認值爲120s,最多可設置300。
*/

if (mBluetoothAdapter.isEnabled()) {  
    if (mBluetoothAdapter.getScanMode() !=   
            BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {  
        Intent discoverableIntent = new Intent(  
                BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);  
        discoverableIntent.putExtra(  
                BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 120);  
        startActivity(discoverableIntent);  
    }  
}  

監聽掃描結果

/**
*通過廣播接收者查看掃描到的藍牙設備,每掃描到一個設備,系統都會發送此廣播(BluetoothDevice.ACTION_FOUNDE)。
*其中參數intent可以獲取藍牙設備BluetoothDevice。
*/

private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver(){  
        @Override  
        public void onReceive(Context context, Intent intent) {  
            String action = intent.getAction();  
            Log.d(TAG,"mBluetoothReceiver action ="+action);  
            if(BluetoothDevice.ACTION_FOUND.equals(action)){//每掃描到一個設備,系統都會發送此廣播。  
                //獲取藍牙設備  
                BluetoothDevice scanDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  
                if(scanDevice == null || scanDevice.getName() == null) return;  
                Log.d(TAG, "name="+scanDevice.getName()+"address="+scanDevice.getAddress());  
                //藍牙設備名稱  
                String name = scanDevice.getName();  
                if(name != null && name.equals(VnApplication.BLUETOOTH_NAME)){  
                    mBluetoothAdapter.cancelDiscovery();  
                    //取消掃描  
                    mProgressDialog.setTitle(getResources().getString
                      (R.string.progress_connecting));           //連接到設備。  
                    mBlthChatUtil.connect(scanDevice);  
                }  
            }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){  

            }  
        }  

    };

連接設備


 public BluetoothGatt connectGatt(Content content,boolean autoConnect,BluetoothGattCallback callback){
   return(connectGatt(context,autoConnect,callback,TRANSPORT_AUTO));
 }
 /**
  *第一個 Context 就不說了;第二個參數 autoConnect 的解釋是“是否直接連接到遠程設備(false)或一旦遠程設備可用即可自動連接(true)”;
  *第三個參數也是上面提到的抽象類,這個類在連接過程中起到關鍵作用。最後方法會返回一個 BluetoothGatt 對象,後續我們通過這個對
  *象可以重連、斷開、關閉設備。貼下我例子中的連接方法:
  */

 /**
  *連接設備,如果服務未開啓或者地址爲空的情況就返回false;
  *如果地址存在是否連接成功取決於藍牙底層
  *@param address
  *@return 是否連接到
  */
  @Override
 public boole connectDevice(String address){
   if(address.equals(mAddress)&&mBluetoothGatt !=null){
         return mBluetoothGatt.connect();
     }
  BluetoothDevice device=arshowBluetooth.getBluetoothAdaoter().
             getRemoteDevice(address);
   if(device ==null){
      return fasle;
   }
   //false表示直接連接,ture表示遠程設備可用之後連接
   mBluetoothGatt=device.connectGatt(context,false,mGattCallback);
   mAddress=address;
   return true;    
  }

Android藍牙自動配對

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