日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 关闭蓝牙打电话功能,Android蓝牙开发【八】hfp接听、挂断电话

發布時間:2023/12/1 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 关闭蓝牙打电话功能,Android蓝牙开发【八】hfp接听、挂断电话 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

繼續研究hfp相關功能。藍牙耳機可以控制手機接聽、拒接、掛斷電話,撥打電話等功能。本文主要分析下起這些操作的大致流程。

在系統應用Bluetooth中com_android_bluetooth.cpp提供了多個回調方法,由hardware、協議棧回調過來。藍牙耳機的一些控制命令都會發到這里。

本文基于Android4.3源碼。

1 接通電話

藍牙耳機控制手機接通電話,回掉com_android_bluetooth.cpp中的answer_call_callback()函數,該函數主要操作是調用HeadsetStateMachine的onAnswerCall()函數,代碼如下:

在onAnswerCall()中發送消息(消息類型STACK_EVENT,StackEvent事件類型EVENT_TYPE_ANSWER_CALL)向狀體機,此時通話尚未接通,audio沒有連接,所以此時處于Connected狀態。狀態機收到該消息后調用processAnswerCall()函數。processAnswerCall()代碼如下:

private void processAnswerCall() {

if (mPhoneProxy != null) {

try {

//mPhoneProxy是通過bindservice 獲取的。

mPhoneProxy.answerCall();

} catch (RemoteException e) {

}

} else {

}

}

初始化的時候會bind service,綁定的該service為系統應用Phone下的BluetoothPhoneService(AndroidManifest中該service的action為android.bluetooth.IBluetoothHeadsetPhone),代碼如下:

//參數為android.bluetooth.IBluetoothHeadsetPhone

Intent intent = new Intent(IBluetoothHeadsetPhone.class.getName());

//resolveSystemService該方法是hide的,由系統使用的特殊功能來解決系統應用程序的服務意圖。

intent.setComponent(intent.resolveSystemService(context.getPackageManager(), 0));

if (intent.getComponent() == null || !context.bindService(intent, mConnection, 0)) {

Log.e(TAG, "Could not bind to Bluetooth Headset Phone Service");

}

綁定service成功回調mConnection,在其成功回調中設置的mPhoneProxy。通過mPhoneProxy來調用service中提供的接口。mPhoneProxy.answerCall()跳到BluetoothPhoneService中answerCall。

public boolean answerCall() {

//申請權限,修改電話狀態

enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);

return PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());

}

PhoneUtils調用answerCall,在這里面去接通電話。answerCall()就不具體分析了。

2 拒接、掛斷電話

藍牙耳機控制手機拒接、掛斷電話,回掉com_android_bluetooth.cpp中的hangup_call_callback()函數,該函數主要操作是調用HeadsetStateMachine的onHangupCall()函數,代碼如下:

private void onHangupCall() {

StackEvent event = new StackEvent(EVENT_TYPE_HANGUP_CALL);

sendMessage(STACK_EVENT, event);

}

此時HeadsetStateMachine可能處于Conneted或AudioOn狀態,這兩種狀態收到該消息的處理一樣,都是調用processHangupCall(),代碼如下:

private void processHangupCall() {

if (isVirtualCallInProgress()) {

//對于虛擬電話,結束。

terminateScoUsingVirtualVoiceCall();

} else {

if (mPhoneProxy != null) {

try { //掛斷電話

mPhoneProxy.hangupCall();

} catch (RemoteException e) {

}

} else {

}

}

}

對于虛擬電話則直接將其結束。真實的通話跳到BluetoothPhoneService的hangupCall。

public boolean hangupCall() {

enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null);

if (mCM.hasActiveFgCall()) { //掛斷正在進行的通話

return PhoneUtils.hangupActiveCall(mCM.getActiveFgCall());

} else if (mCM.hasActiveRingingCall()) { //停止正在響鈴的電話

return PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());

} else if (mCM.hasActiveBgCall()) { //掛斷保持的電話

return PhoneUtils.hangupHoldingCall(mCM.getFirstActiveBgCall());

}

return false;

}

hangupCall中會根據狀態處理通話,優先處理正在進行的通話、其次是尚未接通的電話、最后是保持的電話。

3 更改通話音量

藍牙耳機更改通話的音量,回掉com_android_bluetooth.cpp中的volume_control_callback()函數,該函數主要操作是調用HeadsetStateMachine的onVolumeChnaged()函數,代碼如下:

private void onVolumeChanged(int type, int volume) {

StackEvent event = new StackEvent(EVENT_TYPE_VOLUME_CHANGED);

event.valueInt = type;

event.valueInt2 = volume;

sendMessage(STACK_EVENT, event);

}

此時HeadsetStateMachine可能處于Conneted或AudioOn狀態,這兩種狀態收到該消息的處理一樣,都是調用processVolumeEvent,代碼如下:

private void processVolumeEvent(int volumeType, int volume) {

if (volumeType == HeadsetHalConstants.VOLUME_TYPE_SPK) {

mPhoneState.setSpeakerVolume(volume);

//是否在ui上顯示

int flag = (getCurrentState() == mAudioOn) ? AudioManager.FLAG_SHOW_UI : 0;

//設置SCO通道聲音大小。

mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, volume, flag);

} else if (volumeType == HeadsetHalConstants.VOLUME_TYPE_MIC) {

// 只是存了下該volume值,并沒有設置mic。

mPhoneState.setMicVolume(volume);

} else {

}

}

更改音量兩種類型,VOLUME_TYPE_MIC類型,保存了下該值,并沒有看到具體用該值的地方。對于VOLUME_TYPE_SPK類型的,會設置SCO聲音大小。如果此時處于AudioOn狀態,則會在UI上顯示。

4 撥打電話

藍牙耳機進行撥打電話,回掉com_android_bluetooth.cpp中的dial_call_callback函數,該函數主要操作是調用HeadsetStateMachine的onDialCall()函數,代碼如下:

private void onDialCall(String number) {

StackEvent event = new StackEvent(EVENT_TYPE_DIAL_CALL);

event.valueString = number;

sendMessage(STACK_EVENT, event);

}

此時HeadsetStateMachine可能處于Conneted或AudioOn狀態,這兩種狀態收到該消息的處理一樣,都是調用processDialCall,代碼如下:

private void processDialCall(String number) {

String dialNumber;

if ((number == null) || (number.length() == 0)) {

//獲取最近向外打的電話號碼

dialNumber = mPhonebook.getLastDialledNumber();

if (dialNumber == null) { //沒有最近撥打的電話,回應error

atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_ERROR, 0);

return;

}

} else if (number.charAt(0) == '>') {

//測試

} else {

// Remove trailing ';'

if (number.charAt(number.length() - 1) == ';') {

number = number.substring(0, number.length() - 1);

}

dialNumber = PhoneNumberUtils.convertPreDial(number);

}

terminateScoUsingVirtualVoiceCall(); // 終止虛擬呼叫

Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,

Uri.fromParts(SCHEME_TEL, dialNumber, null));

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

mService.startActivity(intent); //開啟撥打電話的界面

mDialingOut = true;

sendMessageDelayed(DIALING_OUT_TIMEOUT, DIALING_OUT_TIMEOUT_VALUE);

}

藍牙耳機發過來的命令可能攜帶電話號碼,也可能不帶,對于沒有電話號碼則查詢最近的撥打電話記錄,撥打最近撥打的電話。對于有號碼,則撥打該號碼。

Intent.ACTION_CALL_PRIVILEGED(該變量是hide的,執行任何號碼的呼叫,緊急或不緊急):”android.intent.action.CALL_PRIVILEGED”

通過該action打開系統應用Phone中的OutgoingCallBroadcaster界面,向外進行撥打電話。

總結

以上是生活随笔為你收集整理的android 关闭蓝牙打电话功能,Android蓝牙开发【八】hfp接听、挂断电话的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。