編輯:關於Android編程
系統框架簡介 軟件界面設計 藍牙開發本文根據自己的實踐總結而來,參考前人博客之余,也自己總結和開發了一些功能,在這裡給自己備份也分享給大家。不同之處在於:自動打開並搜索藍牙、修改藍牙名字、完整接收藍牙傳輸數據、修改藍牙密碼、解除藍牙綁定。
系統由上、下位機兩部分構成,旨在實現移動端app通過藍牙通信,將app發送過來的數據存儲在下位機的存儲單元,與此同時,app也可以通過指令查詢下位機的參數設置。系統框架圖如下:
界面主要涉及到按鍵的監聽和Activity的跳轉:
①按鍵監聽有四種方法,詳情可以參考博客;
②Activity的跳轉包括:直接跳startActivity轉和帶返回跳startActivityForResult轉,詳情可以參考博客
本系統中實現的功能如表所示,這裡不打算贅述已經開發成熟的功能,可以參考這篇博客,講得比較清晰,這裡只針對自己在開發中添加的功能做一下記錄,開發之前需要提醒的有兩點:
①不要忘記藍牙權限的設置:
②讓主程序彈出搜索對話框時,不要忘了intent設置;
一般的做法都是監聽按鍵(打開藍牙按鍵和搜索設備按鍵),先打開藍牙,接著搜索藍牙。但是,這樣做無疑使操作更加復雜,在實際生產和用戶使用時並不方便,我要做的效果是程序啟動的時候自動打開藍牙並開始搜索設備,於是乎,出問題了,藍牙雖然打開了,但是不接著搜索設備了,汗。。。解決辦法是,打開藍牙後延時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);
這一功能有兩種實現方式,一種是通過藍牙傳輸將名字傳輸給下位機,用單片機操作藍牙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();
在開發藍牙數據接收時,發現一個問題:數據有時候會接收不完整。由於項目中的每一位數據返回都十分重要,所以必須保證數據的完整性,要解決這一問題需要清楚的了解如何從InputStream中讀取數據,從輸入流中讀取數據最常用的方法基本上就是如下 3 個 read() 方法:
① read () 方法,這個方法從輸入流中讀取數據的下一個字節。返回 0 到 255 范圍內的 int 字節值。如果因為已經到達流末尾而沒有可用的字節,則返回值 -1 。
② read (byte[] b,int off,int len) 方法,將輸入流中最多 len 個數據字節讀入 byte 數組。嘗試讀取 len 個字節,但讀取的字節也可能小於該值。以整數形式返回實際讀取的字節數。
③ read (byte[] b) 方法, 從輸入流中讀取一定數量的字節,並將其存儲在緩沖區數組 b 中。以整數形式返回實際讀取的字節數。
對於三種方法的選擇,需要看具體項目的需求,如果你能夠通過某種方法知道數據的長度,那麼建議用第一種方法,每次讀取一個字節,保證數據的完整性;如果數據長度不知道,那麼就用②或者③,一般③用的比較多,這一方法效率高但是讀取數據的長度不確定—-不超過數組b的長度,所以就需要多次讀取直到把數據全部讀完。
本項目中用的是HC-05藍牙模塊,該模塊有接收藍牙指令模式(即通信模式),和AT指令集模式,一般默認狀態為藍牙通信模式,要想修改藍牙連接密碼,需要將藍牙模塊切換到AT指令集模式,具體過程見下面的流程圖:
在真實場景中,要想在程序修改完密碼後,之前連接的藍牙設備都無法與該藍牙模塊建立連接,需要解除該模塊與手機的綁定,即取消配對。要想解除所有的配對,當然是需要下位機控制藍牙模塊進入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(); }
Android:AIDL和遠程Service調用本講的內容,理解起來很難,也許你看了很多資料也看不明白,但是用起來缺簡單的要命。所以我們干脆拿一個音樂播放器中進度條的實例
電腦版qq能夠創建討論組,那手機qq呢?答案是肯定的,手機qq討論組怎麼建?手機qq討論組怎麼刪人?下面我們就來看看相關的操作吧!手機qq討論組怎麼建1、首
這一年都在使用ExtJS 5.0開發系統,經常會遇到的一個場景就是時間日期的選擇了。比如說,預定場地的時候就必須由用戶選擇預定的日期和時間。可惜的是,ExtJS 5.0沒
寫在前面一家移動互聯網公司,說到底,要盈利總是需要付費用戶的,自己開發支付系統顯然是不明智的,國內已經有多家成熟的移動支付提供商,騰訊就是其中之一。梳理了下微信支付的接入