1、藍牙文件傳輸彈窗java
Android原生藍牙傳輸文件時,會彈出藍牙文件接收的確認框且默認是以notification的形式顯示在狀態欄,當用戶點擊以後纔會彈出一個dialog。那麼當狀態欄被禁用時,如何實現文件接受全程不需用戶點擊而自動接收呢?android
1.如何不讓用戶點擊狀態欄直接彈確認的dialog?ide
在BluetoothOppNotification.java的updateIncomingFileConfirmNotification()方法中會對接受到來的文件進行必定的處理同時會構造一個Notification,來顯示接受和拒絕的信息,那麼解決的思路就在這裏。post
private void updateIncomingFileConfirmNotification() { //省略若干… Intent intent = new Intent(Constants.ACTION_INCOMING_FILE_CONFIRM);//這句比較關鍵,傳遞一個action到BluetoothOppReceiver intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); intent.setDataAndNormalize(contentUri);
intent構造了以後在這裏並無發送廣播出去,而是在下面構造notification以後,點擊時纔將廣播發送出去,因此問題的解決點就在這裏。若是不須要用戶點擊狀態欄直接顯示文件接收和拒絕的確認界面能夠直接在這裏mContext.sendBroadcast(intent);將廣播發送出去ui
//省略若干… { //構造notification Notification n = new Notification(); n.icon = R.drawable.bt_incomming_file_notification; n.flags |= Notification.FLAG_ONLY_ALERT_ONCE; n.flags |= Notification.FLAG_ONGOING_EVENT; n.defaults = Notification.DEFAULT_SOUND; n.tickerText = title; n.when = timeStamp; n.color = mContext.getResources().getColor( com.android.internal.R.color.system_notification_accent_color); n.setLatestEventInfo(mContext, title, caption, PendingIntent.getBroadcast(mContext, 0, intent, 0)); intent = new Intent(Constants.ACTION_HIDE); intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); intent.setDataAndNormalize(contentUri); n.deleteIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);//用戶點擊以後將廣播發送出去 mNotificationMgr.notify(id, n); } } }
2.用戶不點擊確認文件接收的按鈕如何直接進行文件接收?this
繼續上面說的,當廣播發送以後在BluetoothOppReceiver.java直接啓動BluetoothOppIncomingFileConfirmActivity。在這個activity中做進一步的處理。spa
能夠看到的是在這個activity中主要是構造上面所說的接收文件確認和拒絕的dialog。code
要想達到須要的效果,只須要將確認接收按鈕事件的代碼外移便可。能夠直接移動的oncreate中執行,完了以後將dialog dismiss掉。主要就是以下幾句代碼orm
if (!mTimeout) { // Update database mUpdateValues = new ContentValues(); mUpdateValues.put(BluetoothShare.USER_CONFIRMATION, BluetoothShare.USER_CONFIRMATION_CONFIRMED); this.getContentResolver().update(mUri, mUpdateValues, null, null); Toast.makeText(this, getString(R.string.bt_toast_1), Toast.LENGTH_SHORT).show(); }
3.如何顯示進度條?blog
當上面的文件開始接受之時就須要彈出進度條進行顯示進度,因此在上面的代碼中還須要加入啓動進度條界面的代碼:
Intent in = new Intent(this, BluetoothOppTransferActivity.class); in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); in.setDataAndNormalize(mUri); this.startActivity(in);
至此,單文件就開始傳輸而且已經顯示進度條。
4.文件傳輸完成後,進度條界面如何三秒以後自動消失?
進入BluetoothOppTransferActivity這個activity,首先先定義一個消失的方法:
private void dismissNowDialog(){ new Handler().postDelayed(new Runnable() { @Override public void run() { dismiss(); } }, 2000); }
以後再setUpDialog()中mWhichDialog == DIALOG_RECEIVE_COMPLETE_SUCCESS和mWhichDialog == DIALOG_RECEIVE_COMPLETE_FAIL時調用這個方法便可。
寫到這裏,單文件文件傳輸全程不須要用戶進行任何點擊就能夠自動接收完成。
可是不知道您有沒有想過一個問題,在接受完以後dismiss掉了界面,那麼在多文件傳輸時後面的那些文件進度條是否還會顯示呢?答案是不會的。
5.多文件時如何顯示全部文件傳輸的進度條?
思路就是,再多文件傳輸時,單個文件傳輸完,狀態欄會進行更新顯示其餘文件的進度信息,考慮到這裏,繼續進入BluetoothOppNotification.java這個類,在updateActiveNotification()方法中能夠看到多文件在傳輸時,它是經過Notification.Builder來進行刷新顯示的,咱們的需求並非這樣,因此這些並不可取。繼續往下看能夠看到重點是Intent intent = new Intent(Constants.ACTION_LIST);這個能夠理解爲處理多文件的。原生的代碼並無很好地辦法來區分多文件仍是單文件,因此須要在這裏想辦法進行處理。筆者在作的時候看到這個非常興奮,一想這不很簡單嗎,和單文件傳輸一模一樣我只須要將廣播手動發送一遍便可。結果會讓你崩潰的,這裏簡單說下,假如十個文件在傳輸時那麼這個廣播他會發幾遍呢?最終的結果就是後面的界面不停的閃爍加劇疊。因此這裏要作的就是在文件傳輸時只將這個廣播發送一次,可是並無現成的方法或變量來標示是否多文件傳輸。
筆者這裏採用的思路是定義一個任意類型的變量,給定一個初始值,找一個在文件接收時確定會調用的一個方法,在這個方法中改變該變量的值,再在發送廣播時加上對這個變量的判斷,所有傳輸完後將該變量恢復默認值,以此保證廣播只發送了一次,便可達到需求。
Private Int temp =0; private void updateActiveNotification() { …… if(temp==1){//經過這個判斷保證廣播只會發送一次 mContext.sendBroadcast(intent); temp=temp+1; } …… } rivate void updateIncomingFileConfirmNotification() { //這個方法中加入以下代碼 if(temp==1){ temp=temp+1; return; } …… temp=1; }
至此,整個需求處理完畢。當讓若是在接受完畢以後還想顯示多少文件傳輸完成,多少文件傳輸失敗的話能夠經過在代碼中BluetoothOppTransferActivity.java中動態的改變dialog的顯示信息來進行處理,須要注意的是在這個類裏面是不知道有多少文件傳輸完成和失敗的,須要從BluetoothOppNotification.java 的updateCompletedNotification()方法中,將
int outboundSuccNumber = 0; int outboundFailNumber = 0; int outboundNum; int inboundNum; int inboundSuccNumber = 0; int inboundFailNumber = 0;
參數選擇性的進行傳輸或者保存,從而在上面說的界面顯示出來。
最後再來一個小知識點:不知有沒有想過,藍牙文件在傳輸時如何判斷文件是正在傳輸仍是已經傳輸完畢呢?原生的藍牙代碼以後提供藍牙的配對,鏈接等狀態,並不會提供文件傳輸的狀態,那麼就須要本身來實現。思路就是藍牙文件的傳輸是經過流來進行的,那麼我只須要知道它所對應的劉是否關閉便可知道文件是否傳輸完成。
在framework\base\obex\javax\obex下面有個ServerSession類,在這個裏面會經過判斷ObexTransport; InputStream OutputStream來判斷是否關閉,能夠本身在這裏加接口提供給外部,用來判斷藍牙文件是否傳輸完成,比較簡單。