Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 【Android藍牙開發】手機藍牙與下位機HC-05藍牙模塊通信系統

【Android藍牙開發】手機藍牙與下位機HC-05藍牙模塊通信系統

編輯:關於Android編程

本文根據自己的實踐總結而來,參考前人博客之余,也自己總結和開發了一些功能,在這裡給自己備份也分享給大家。不同之處在於:自動打開並搜索藍牙、修改藍牙名字、完整接收藍牙傳輸數據、修改藍牙密碼、解除藍牙綁定。

系統框架簡介 軟件界面設計 藍牙開發

一、系統框架簡介

系統由上、下位機兩部分構成,旨在實現移動端app通過藍牙通信,將app發送過來的數據存儲在下位機的存儲單元,與此同時,app也可以通過指令查詢下位機的參數設置。系統框架圖如下:

這裡寫圖片描述

二、軟件界面設計

話不多說,先上軟件界面:

這裡寫圖片描述

界面主要涉及到按鍵的監聽和Activity的跳轉:
①按鍵監聽有四種方法,詳情可以參考博客;
②Activity的跳轉包括:直接跳startActivity轉和帶返回跳startActivityForResult轉,詳情可以參考博客

二、藍牙開發

藍牙功能 函數名稱 (1)開啟&關閉藍牙 enable()/disable() (2)修改藍牙名字 changeName() (3)搜索&顯示藍牙設備 DeviceListActivity (4)配對&連接藍牙 connectToServerSocket(address) (5)數據收發 write/ConnectedThread (6)修改藍牙密碼 changeMima() (7)取消藍牙配對 removeBond

本系統中實現的功能如表所示,這裡不打算贅述已經開發成熟的功能,可以參考這篇博客,講得比較清晰,這裡只針對自己在開發中添加的功能做一下記錄,開發之前需要提醒的有兩點:
①不要忘記藍牙權限的設置:

  
  

②讓主程序彈出搜索對話框時,不要忘了intent設置;


(1)自動打開並搜索藍牙

一般的做法都是監聽按鍵(打開藍牙按鍵和搜索設備按鍵),先打開藍牙,接著搜索藍牙。但是,這樣做無疑使操作更加復雜,在實際生產和用戶使用時並不方便,我要做的效果是程序啟動的時候自動打開藍牙並開始搜索設備,於是乎,出問題了,藍牙雖然打開了,但是不接著搜索設備了,汗。。。解決辦法是,打開藍牙後延時1秒後開始搜索,這樣就行了

//得到BluetoothAdapter對象
BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();
mBtAdapter.enable();//打開藍牙
Timer timer=new Timer();
TimerTask task=new TimerTask(){//定時1k=new TimerTask(){//定時1秒後搜索設備
    @Override
     public void run() {
        Intent serverIntent = new Intent(MainActivity.this, DeviceListActivity.class); //跳轉程序設置
        startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);  //設置返回宏定義
    }          
};
timer.schedule(task,1000);

(3)修改藍牙名字

這一功能有兩種實現方式,一種是通過藍牙傳輸將名字傳輸給下位機,用單片機操作藍牙AT指令直接修改藍牙名字,這樣,以後任何手機搜索該藍牙設備時,顯示的名字都是你所修改的名字;另一種方式是在軟件層面實現藍牙名字的修改,其實是搜索出藍牙設備的ID,然後將其對應到你想修改的名字,並將這一映射存在本地,那麼,以後這部手機下次搜索到該設備時,就會顯示你所修改的名字,而不影響其他手機對該設備的顯示。這種方法各有特色,就看你的需求了。這裡就講講第二種方式的實現:

步驟一:搜索藍牙設備,獲取並修改名字

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode) {
    case REQUEST_CONNECT_DEVICE:     //連接結果,由DeviceListActivity設置返回
        if (resultCode == Activity.RESULT_OK) { //選擇藍牙
            String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
            device = mBluetoothAdapter.getRemoteDevice(address);// 得到藍牙設備句柄
            connectToServerSocket(address);
            setting_thread=true;
            ConnectedThread thread=new ConnectedThread();
            thread.start();
        }
        break;
        default:break;
    }
}

在從DeviceListActivity返回的數據中,其實已經包含藍牙設備的句柄,我們可以通過device.getName()獲取當前連接的藍牙模塊的名字,然後將設備的名字或者其唯一標識符(例如,98:D3:34:90:8A:BC)與新修改的名字做映射保存在本地。
步驟二:存儲設置到本地,下次搜索藍牙時做映射顯示
使用SharedPreferences存儲數據,SharedPreferences是Android平台上一個輕量級的存儲類,主要是保存一些常用的配置比如窗口狀態,一般在Activity中 重載窗口狀態onSaveInstanceState保存一般使用SharedPreferences完成,它提供了Android平台常規的Long長 整形、Int整形、String字符串型的保存。

//獲取SharedPreferences對象
Context ctx = MainActivity.this;       
SharedPreferences sp = ctx.getSharedPreferences("SP", MODE_PRIVATE);
//存入數據
Editor editor = sp.edit();
editor.putString("STRING_KEY", "string");
editor.commit();

(4)完整接收藍牙傳輸數據

在開發藍牙數據接收時,發現一個問題:數據有時候會接收不完整。由於項目中的每一位數據返回都十分重要,所以必須保證數據的完整性,要解決這一問題需要清楚的了解如何從InputStream中讀取數據,從輸入流中讀取數據最常用的方法基本上就是如下 3 個 read() 方法:

① read () 方法,這個方法從輸入流中讀取數據的下一個字節。返回 0 到 255 范圍內的 int 字節值。如果因為已經到達流末尾而沒有可用的字節,則返回值 -1 。
② read (byte[] b,int off,int len) 方法,將輸入流中最多 len 個數據字節讀入 byte 數組。嘗試讀取 len 個字節,但讀取的字節也可能小於該值。以整數形式返回實際讀取的字節數。
③ read (byte[] b) 方法, 從輸入流中讀取一定數量的字節,並將其存儲在緩沖區數組 b 中。以整數形式返回實際讀取的字節數。

對於三種方法的選擇,需要看具體項目的需求,如果你能夠通過某種方法知道數據的長度,那麼建議用第一種方法,每次讀取一個字節,保證數據的完整性;如果數據長度不知道,那麼就用②或者③,一般③用的比較多,這一方法效率高但是讀取數據的長度不確定—-不超過數組b的長度,所以就需要多次讀取直到把數據全部讀完。

(5)修改藍牙密碼

本項目中用的是HC-05藍牙模塊,該模塊有接收藍牙指令模式(即通信模式),和AT指令集模式,一般默認狀態為藍牙通信模式,要想修改藍牙連接密碼,需要將藍牙模塊切換到AT指令集模式,具體過程見下面的流程圖:
這裡寫圖片描述

(6)解除藍牙綁定(配對)

在真實場景中,要想在程序修改完密碼後,之前連接的藍牙設備都無法與該藍牙模塊建立連接,需要解除該模塊與手機的綁定,即取消配對。要想解除所有的配對,當然是需要下位機控制藍牙模塊進入AT指令集模式,解除所有綁定,而與此同時,當前修改密碼的手機也需要在軟件層面解除綁定(配對),這樣交互性更強。

用過Android系統設置(Setting)的人都知道藍牙搜索之後可以建立配對和解除配對,但是這兩項功能的函數沒有在SDK中給出,本項目利用Java的反射機制去調用removeBond解除綁定,從而取消本機與該藍牙模塊的配對。具體實現程序如下:當程序接收到下位機傳來的修改密碼成功的指令後,程序會彈出一個強提示,當用戶點擊確認按鈕之後,程序解除綁定並退出程序。

if(modify_flag){//修改密碼成功
      AlertDialog.Builder builder = new Builder(MainActivity.this);
      builder.setTitle("密碼修改成功");
      builder.setMessage("點擊確定按鈕重新啟動!");
      builder.setCancelable(false);
      builder.setPositiveButton("確認", new OnClickListener() {
           @Override
           public void onClick(DialogInterface dialog, int which) {
           try {//接觸綁定
               Method m = device.getClass().getMethod("removeBond", (Class[]) null);
               m.invoke(device, (Object[]) null);
           } catch (Exception e) {
                Log.e("erro", e.getMessage());
           }
           setting_thread=false;
           dialog.dismiss();
           mBluetoothAdapter.disable();//關閉藍牙
           finish();
           System.exit(0);//銷毀程序
           }
      });
      builder.setCancelable(false);
      builder.create().show();
}else {
     Toast.makeText(MainActivity.this, "set failed!", Toast.LENGTH_SHORT).show();
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved