首先压彭,android原生的藍(lán)牙接收流程是,在有文件從其他設(shè)備傳過來時(shí)渗常,會(huì)彈出藍(lán)牙文件接收的缺人框且默認(rèn)是以notification的形式顯示在狀態(tài)欄壮不,當(dāng)用戶點(diǎn)擊之后才會(huì)彈出一個(gè)dialog。那么當(dāng)狀態(tài)欄被禁用時(shí)皱碘,如何實(shí)現(xiàn)文件接受全程不需用戶點(diǎn)擊而自動(dòng)接收呢询一?
第一個(gè)問題:
如何不讓用戶點(diǎn)擊狀態(tài)欄直接彈確認(rèn)的dialog。
在BluetoothOppNotification.java的updateIncomingFileConfirmNotification()方法中會(huì)對(duì)接受到來的文件進(jìn)行一定的處理同時(shí)會(huì)構(gòu)造一個(gè)Notification癌椿,來顯示接受和拒絕的信息健蕊,那么解決的思路就在這里。
private void updateIncomingFileConfirmNotification() {
//省略若干…
Intent intent = new Intent(Constants.ACTION_INCOMING_FILE_CONFIRM);//這句比較關(guān)鍵踢俄,傳遞一個(gè)action到BluetoothOppReceiver
intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
intent.setDataAndNormalize(contentUri);
intent構(gòu)造了之后在這里并沒有發(fā)送廣播出去缩功,而是在下面構(gòu)造notification之后,點(diǎn)擊時(shí)才將廣播發(fā)送出去都办,所以問題的解決點(diǎn)就在這里嫡锌。如果不需要用戶點(diǎn)擊狀態(tài)欄直接顯示文件接收和拒絕的確認(rèn)界面可以直接在這里mContext.sendBroadcast(intent);將廣播發(fā)送出去
//省略若干…
{
//構(gòu)造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);//用戶點(diǎn)擊之后將廣播發(fā)送出去
mNotificationMgr.notify(id, n);
}
}
}
第二個(gè)問題
用戶不點(diǎn)擊確認(rèn)文件接收的按鈕直接進(jìn)行文件接收虑稼。這個(gè)相對(duì)來說比較簡(jiǎn)單
繼續(xù)上面說的,當(dāng)廣播發(fā)送之后在BluetoothOppReceiver.java直接啟動(dòng)BluetoothOppIncomingFileConfirmActivity势木。在這個(gè)activity中作進(jìn)一步的處理蛛倦。
可以看到的是在這個(gè)activity中主要是構(gòu)造上面所說的接收文件確認(rèn)和拒絕的dialog。
要想達(dá)到需要的效果啦桌,只需要將確認(rèn)接收按鈕事件的代碼外移即可溯壶。可以直接移動(dòng)的oncreate中執(zhí)行甫男,完了之后將dialog dismiss掉且改。主要就是如下幾句代碼
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();
}
第三個(gè)問題
如何顯示進(jìn)度條。
當(dāng)上面的文件開始接受之時(shí)就需要彈出進(jìn)度條進(jìn)行顯示進(jìn)度板驳。所以在上面的代碼中還需要加入啟動(dòng)進(jìn)度條界面的代碼又跛。具體是
Intent in = new Intent(this, BluetoothOppTransferActivity.class);
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
in.setDataAndNormalize(mUri);
this.startActivity(in);
至此,單文件就開始傳輸并且已經(jīng)顯示進(jìn)度條笋庄。
第四個(gè)問題
文件傳輸完場(chǎng)之后,進(jìn)度條界面如何三秒之后自動(dòng)消失倔监。
進(jìn)入BluetoothOppTransferActivity這個(gè)activity直砂,首先先定義一個(gè)消失的方法。如下
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時(shí)調(diào)用這個(gè)方法即可浩习。
寫到這里静暂,單文件文件傳輸全程不需要用戶進(jìn)行任何點(diǎn)擊就可以自動(dòng)接收完成。
但是不知道您有沒有想過一個(gè)問題谱秽,在接受完之后dismiss掉了界面洽蛀,那么在多文件傳輸時(shí)后面的那些文件進(jìn)度條是否還會(huì)顯示呢?答案是不會(huì)的疟赊。
第五個(gè)問題
多文件時(shí)如何顯示所有文件傳輸?shù)倪M(jìn)度條郊供。
思路就是,再多文件傳輸時(shí)近哟,單個(gè)文件傳輸完驮审,狀態(tài)欄會(huì)進(jìn)行更新顯示其他文件的進(jìn)度信息,考慮到這里吉执,繼續(xù)進(jìn)入BluetoothOppNotification.java這個(gè)類疯淫,在updateActiveNotification()方法中可以看到多文件在傳輸時(shí),它是通過Notification.Builder來進(jìn)行刷新顯示的戳玫,我們的需求并不是這樣熙掺,所以這些并不可取。繼續(xù)往下看可以看到重點(diǎn)是Intent intent = new Intent(Constants.ACTION_LIST);這個(gè)可以理解為處理多文件的咕宿。原生的代碼并沒有很好地辦法來區(qū)分多文件還是單文件币绩,所以需要在這里想辦法進(jìn)行處理蜡秽。筆者在做的時(shí)候看到這個(gè)很是興奮,一想這不很簡(jiǎn)單嗎类浪,和單文件傳輸如出一轍我只需要將廣播手動(dòng)發(fā)送一遍即可载城。結(jié)果會(huì)讓你崩潰的,這里簡(jiǎn)單說下费就,假如十個(gè)文件在傳輸時(shí)那么這個(gè)廣播他會(huì)發(fā)幾遍呢诉瓦?最終的結(jié)果就是后面的界面不停的閃爍加重疊。所以這里要做的就是在文件傳輸時(shí)只將這個(gè)廣播發(fā)送一次力细,但是并沒有現(xiàn)成的方法或變量來標(biāo)示是否多文件傳輸睬澡。
第六個(gè)問題
如何在一個(gè)循環(huán)中只根據(jù)自己的需求將廣播發(fā)送一次出去呢?
筆者這里采用的思路是定義一個(gè)任意類型的變量眠蚂,給定一個(gè)初始值煞聪,找一個(gè)在文件接收時(shí)肯定會(huì)調(diào)用的一個(gè)方法,在這個(gè)方法中改變變臉的值逝慧,完了之后在發(fā)送廣播時(shí)加上對(duì)這個(gè)變量的判斷昔脯,完了之后將變量的值回復(fù)默認(rèn)值。下次的話笛臣,他肯定就不會(huì)再發(fā)廣播出去云稚,保證廣播只發(fā)送了一次,即可達(dá)到需求沈堡。
Private Int temp =0;
private void updateActiveNotification() {
……
if(temp==1){//通過這個(gè)判斷保證廣播只會(huì)發(fā)送一次
mContext.sendBroadcast(intent);
temp=temp+1;
}
……
}
rivate void updateIncomingFileConfirmNotification() {
//這個(gè)方法中加入如下代碼
if(temp==1){
temp=temp+1;
return;
}
……
temp=1;
}
至此静陈,整個(gè)需求處理完畢。當(dāng)讓如果在接受完畢之后還想顯示多少文件傳輸完成诞丽,多少文件傳輸失敗的話可以通過在代碼中BluetoothOppTransferActivity.java中動(dòng)態(tài)的改變dialog的顯示信息來進(jìn)行處理鲸拥,需要注意的是在這個(gè)類里面是不知道有多少文件傳輸完成和失敗的,需要從BluetoothOppNotification.java 的updateCompletedNotification()方法中僧免,將
int outboundSuccNumber = 0;
int outboundFailNumber = 0;
int outboundNum;
int inboundNum;
int inboundSuccNumber = 0;
int inboundFailNumber = 0;
參數(shù)選擇性的進(jìn)行傳輸或者保存刑赶,從而在上面說的界面顯示出來。
最后再來一個(gè)小知識(shí)點(diǎn)結(jié)束懂衩。不知有沒有想過角撞,藍(lán)牙文件在傳輸時(shí)如何判斷文件是正在傳輸還是已經(jīng)傳輸完畢呢?原生的藍(lán)牙代碼之后提供藍(lán)牙的配對(duì)勃痴,連接等狀態(tài)谒所,并不會(huì)提供文件傳輸?shù)臓顟B(tài),那么就需要自己來實(shí)現(xiàn)沛申。思路就是藍(lán)牙文件的傳輸是通過流來進(jìn)行的劣领,那么我只需要知道它所對(duì)應(yīng)的劉是否關(guān)閉即可知道文件是否傳輸完成。
在framework\base\obex\javax\obex下面有個(gè)ServerSession類铁材,在這個(gè)里面會(huì)通過判斷ObexTransport; InputStream OutputStream來判斷是否關(guān)閉尖淘,可以自己在這里加接口提供給外部奕锌,用來判斷藍(lán)牙文件是否傳輸完成,比較簡(jiǎn)單村生。