版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android源碼個(gè)個(gè)擊破之撥號(hào)源碼
#############需求#############最近我的一位同事大概是利用下面的方法監(jiān)聽(tīng)電話的狀態(tài)
/20110725/417.html
/lyen2010/article/details/42590099
相關(guān)demo下載鏈接:/download/weiyirong/6872889本來(lái)我是將系統(tǒng)的ITelephony.aidl復(fù)制進(jìn)去,但是編譯會(huì)報(bào)notfounttheimportclassxx錯(cuò)誤,于是看了一下上面的demo,對(duì)aidl作了簡(jiǎn)化:interface
ITelephony
{
boolean
endCall();
void
answerRingingCall();
boolean
enableDataConnectivity();
boolean
disableDataConnectivity();
boolean
isDataConnectivityPossible();
}
aidl文件及目錄建好,重新rebuild工程,就會(huì)在對(duì)應(yīng)的build目錄下生成對(duì)應(yīng)的java文件
然后我同事說(shuō)遇到兩個(gè)問(wèn)題
1.電話接通之后,無(wú)法掛斷
2.通話狀態(tài)無(wú)法正常顯示(準(zhǔn)確的說(shuō)是:通話中的狀態(tài)不顯示)
我寫(xiě)了個(gè)測(cè)試demo
掛斷方法:
public
void
hangup_call(View
view)
{
Log.e(TAG,"hangup_call
START");
...
}
接通電話之后,點(diǎn)擊掛斷按鈕:無(wú)響應(yīng),日志也沒(méi)有打。
我隱隱約約感覺(jué)線程阻塞了,果然接聽(tīng)加上線程就解決了問(wèn)題。上面的問(wèn)題就是接聽(tīng)電話阻塞了主線程,所以掛斷按鈕點(diǎn)擊不了,廣播也阻塞了。
#############源碼研究#############以下源碼基于android6.0.1撥號(hào)源碼詳解:
/so/search/s.do?q=Android6.0%E7%9A%84phone%E5%BA%94%E7%94%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90&t=blog&u=u014386544撥號(hào)源碼架構(gòu):
/p/ca4ab4e9817f/
(一個(gè)電話應(yīng)用,實(shí)際由多個(gè)代碼模塊組成。由dialer下的Android.mk可以看出)
/wds1181977/article/details/61920067
(介紹各個(gè)模塊的作用)一、撥號(hào)
假如我不想調(diào)用系統(tǒng)的INTENT來(lái)打電話(最直接的方法就是調(diào)用ITelephony,文章開(kāi)頭已經(jīng)介紹過(guò)),那么就得對(duì)系統(tǒng)打電話的INTENT做一番探索了。
通過(guò)調(diào)用Intent.ACTION_CALL,會(huì)打開(kāi)系統(tǒng)的撥號(hào)引用。
向外撥號(hào),發(fā)現(xiàn)當(dāng)前顯示的activity是(通過(guò)sdk工具):
InCallActivity.java
現(xiàn)在,我們需求是想自己實(shí)現(xiàn)撥號(hào)級(jí)來(lái)電接聽(tīng),不走系統(tǒng)UI。
所以,我的思路是先確定Intent.ACTION_CALL是被誰(shuí)處理了,怎么處理的,如何調(diào)起InCallActivity,InCallActivity又干了啥。
InCallActivity被誰(shuí)打開(kāi)的
在xref全局搜索,發(fā)現(xiàn)InCallPresenter.java這個(gè)類(lèi)
通過(guò)官方的解釋,可以知道此類(lèi)正是管理通話狀態(tài),開(kāi)啟InCallActivity。搜索InCallPresenter又會(huì)被很多類(lèi)調(diào)用,可見(jiàn)此類(lèi)是集中處理通話狀態(tài)的核心類(lèi)。其中有
InCallServiceImpl,InCallServiceImpl注冊(cè)在dialer的清單文件里:
二、屏蔽原始UI
1./zuiaikg703/article/details/8178028
電話的UI都是通過(guò)InCallActivity添加Fragment實(shí)現(xiàn)的,所以,只要把其UI屏蔽掉就可以了。(修改源碼要一針見(jiàn)血,找到最佳修改位置。這樣既能減少工作量又能避免修改錯(cuò)誤)
2.但是來(lái)電時(shí)顯示的那個(gè)懸浮窗是如何出現(xiàn)的呢?如何屏蔽掉?
/u012439416/article/details/78946337
首先,得從“來(lái)電”來(lái)出發(fā)尋找,其實(shí)這個(gè)UI就叫做StatusBarNotifier
在InCallPresenter里找到一些蛛絲馬跡:
看看官方對(duì)此類(lèi)的解釋:
準(zhǔn)備把下面的方法注釋掉,應(yīng)該就不會(huì)顯示通知欄
經(jīng)測(cè)試,注釋上面的方法,確實(shí)可以屏蔽來(lái)電時(shí)顯示的通知欄。
三、主動(dòng)撥號(hào)之后無(wú)法掛斷的問(wèn)題
在(二.1),屏蔽IncallUI之后,發(fā)現(xiàn)主動(dòng)往外打電話之后,其他的按鈕沒(méi)法點(diǎn)擊。
public
void
call(View
view)
{
Log.d(TAG,
"call:
");
/*
//取得一個(gè)Callintent
final
Intent
intent
=
CallUtil.getCallIntent();
//交給DialerUtils去處理
DialerUtils.startActivityWithErrorToast(this,
intent);*/
callThread
=
new
Thread(){
@Override
public
void
run()
{
try
{
ITelephony
iTelephony
=
PhoneUtils.getITelephony((TelephonyManager)MainActivity.this.getSystemService(
Context.TELEPHONY_SERVICE));
iTelephony.call(getPackageName(),);
}
catch
(Exception
e)
{
Log.e(TAG,
"[Broadcast]Exception111="+e.getMessage(),
e);
}
}
};
callThread.start();
}
所以我猜想有2種原因:
1)打電話時(shí)InCallActivity彈出來(lái)了(眼睛看不見(jiàn)),擋住了我的Activity
2)系統(tǒng)電話的call方法阻塞了UI線程
是否是系統(tǒng)的UI擋住了我的Activity:
將上面的InCallActivity的布局顯示出來(lái),果然,是有個(gè)系統(tǒng)的撥打電話的界面。
那么如何隱藏并這個(gè)activity界面并屏蔽它的所有時(shí)間
1)將InCallActivity的theme變成透明
↓↓↓
2)屏蔽InCallActivity的點(diǎn)擊事件
在InCallActivity的onCreate方法里加上下面代碼
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
3)屏蔽InCallActivity對(duì)狀態(tài)欄的改變
對(duì)系統(tǒng)電話的call方法發(fā)起追蹤研究:
1.找service
↓↓↓
↓↓↓
注意Context.TELEPHONY_SERVICE的值是“phone”
通過(guò)搜索“extendsITelephony.Stub
”或者“phone”可以找到ITelephony的Service類(lèi)/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java:
可以看到這個(gè)service
上面的init方法在PhoneGlobals的onCreate方法里被調(diào)用
2.分析service的相應(yīng)call方法
↓↓↓
可以看到最終也是通過(guò)Intent去打開(kāi)撥號(hào)頁(yè)面的。
三、主動(dòng)撥號(hào)之后對(duì)方?jīng)]有接聽(tīng)直接掛斷,ITelephony沒(méi)有回調(diào)的問(wèn)題。
此種情況雖然ITelephony沒(méi)有回調(diào),但是系統(tǒng)會(huì)有個(gè)無(wú)人接聽(tīng)的提示語(yǔ)音,可以在此處修改系統(tǒng)源碼,人工發(fā)一個(gè)空閑狀態(tài)廣播。
四、去電,PhoneListener的狀態(tài)瞎回調(diào)的問(wèn)題。
去電時(shí):android6.0系統(tǒng)會(huì)立馬發(fā)一個(gè)通話中和空閑的狀態(tài),這些其實(shí)都是錯(cuò)誤的回調(diào)。需要人為的去處理,可以根據(jù)時(shí)間來(lái)過(guò)濾判斷,但是具有不可靠性。
一般對(duì)方接通電話之后,會(huì)再回調(diào)一個(gè)正確的通話中狀態(tài)。但有時(shí)候不會(huì)回調(diào)。
第一個(gè)錯(cuò)誤的空閑的狀態(tài)很好解決:
點(diǎn)擊撥打電話的按鈕時(shí),將Constants.isPhoneOut設(shè)置為true。 case
TelephonyManager.CALL_STATE_IDLE:
//
空閑
0
Log.d(tag,
"CALL_STATE_IDLE00isPhoneOut
=
"
+
Constants.isPhoneOut);
if(Constants.isPhoneOut
==
true){
//撥打電話時(shí),系統(tǒng)會(huì)誤發(fā)一個(gè)掛斷的廣播,需要自己區(qū)分處理
Constants.isPhoneOut
=
false;
return;
}
但是如果主動(dòng)往外撥打,對(duì)方?jīng)]有接通或者掛斷,是不會(huì)收到空閑回調(diào)的。上面這種判斷就會(huì)有缺陷,所以準(zhǔn)備找到撥打電話的源碼,去掉撥打電話前誤發(fā)的空閑狀態(tài)。
發(fā)現(xiàn)底層的回調(diào)是這樣的:07-15
17:16:28.591
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
NO_CALLS
->
NO_CALLS
07-15
17:16:28.666
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
OUTGOING
07-15
17:16:28.725
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
PENDING_OUTGOING
07-15
17:16:28.774
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
PENDING_OUTGOING
->
INCALL
07-15
17:16:28.791
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
INCALL
->
INCALL
07-15
17:16:28.819
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
INCALL
->
INCALL
07-15
17:16:28.828
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
INCALL
->
INCALL
07-15
17:16:28.830
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
INCALL
->
INCALL
07-15
17:16:29.111
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
INCALL
->
OUTGOING
07-15
17:16:30.776
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
OUTGOING
07-15
17:16:30.833
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
OUTGOING
07-15
17:16:30.849
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
OUTGOING
07-15
17:16:30.863
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
OUTGOING
07-15
17:16:30.878
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
OUTGOING
07-15
17:16:30.892
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
OUTGOING
07-15
17:18:13.357
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
OUTGOING
->
INCALL
07-15
17:18:13.416
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
INCALL
->
INCALL
07-15
17:18:15.404
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
INCALL
->
NO_CALLS
07-15
17:18:15.448
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
NO_CALLS
->
NO_CALLS
07-15
17:18:15.499
5456-5456/com.android.dialer
I/InCall:
InCallPresenter
-
Phone
switching
state22222:
NO_CALLS
->
NO_CALLS
撥打電話,系統(tǒng)立馬會(huì)發(fā)NO_CALLS->NO_CALLS狀態(tài),也就是app會(huì)無(wú)緣無(wú)故收到空閑狀態(tài)的原因。但是這個(gè)狀態(tài)不好限制。
等了很久,系統(tǒng)會(huì)發(fā)送OUTGOING->INCALL,也就是通話中狀態(tài),這也是個(gè)誤發(fā)。app不應(yīng)做處理。
最后會(huì)發(fā)個(gè)INCALL->NO_CALLS狀態(tài),也就是對(duì)方未接聽(tīng)或者拒接后系統(tǒng)的一個(gè)超時(shí)回調(diào),這里可以發(fā)一個(gè)空閑廣播。app處理這個(gè)空閑廣播,屏蔽api的空閑回調(diào)即可解決空閑問(wèn)題。
但是此時(shí)mInCallActivity為null,所以無(wú)法通過(guò)mInCallActivity發(fā)空閑廣播,改由mContext發(fā)送廣播。經(jīng)驗(yàn)證,mContext果然不為空。
**Log.d在logcat上不輸出日志,但是Log.i可以輸出日志。**
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
但是通話中狀態(tài)回調(diào)不準(zhǔn)確的問(wèn)題則不好解決,但是經(jīng)測(cè)試,發(fā)現(xiàn)系統(tǒng)電話應(yīng)用關(guān)于電話狀態(tài)的判斷則十分準(zhǔn)確,只有從源碼入手了。
網(wǎng)絡(luò)上搜到的關(guān)于通話中狀態(tài)判斷的解決方案:/qwe749082787/article/details/78364112
/qwe749082787/article/details/78364112
(可以修改源碼,此處發(fā)一個(gè)廣播),事實(shí)證明此方法行不通,撥打電話還沒(méi)有通話就回調(diào)了。
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
突然我腦洞大開(kāi),查看了一下電話應(yīng)用com.android.dialer的日志,發(fā)現(xiàn),在InCallPresenter類(lèi)里,在來(lái)電接聽(tīng)會(huì)有系統(tǒng)日志:
Phoneswitchingstate:INCOMING->INCALL
去電時(shí)會(huì)有系統(tǒng)日志:
Phoneswitchingstate:OUTGOING->INCALL
而且這個(gè)日志不會(huì)重復(fù),可以在上面發(fā)送兩個(gè)自定義廣播,就能準(zhǔn)確監(jiān)聽(tīng)到通話中狀態(tài)了。
在測(cè)試中發(fā)現(xiàn)
OUTGOING->INCALL,這個(gè)不一定只有去電通話中才會(huì)回調(diào),需要結(jié)合前一個(gè)狀態(tài)變化聯(lián)合判斷:
所以修改InCallPresenter類(lèi),緩存上一次的通話狀態(tài)變化,然后對(duì)比方能準(zhǔn)確判斷通話中的狀態(tài)
InCallState
newState
=
getPotentialStateFromCallList(callList);
InCallState
oldState
=
mInCallState;
Log.d(this,
"onCallListChange
oldState=
"
+
oldState
+
"
newState="
+
newState);
newState
=
startOrFinishUi(newState);
Log.d(this,
"onCallListChange
newState
changed
to
"
+
newState);
String
oldStateLast
=
phone_state_cacheSp.getString("oldState",
"");
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 特殊教育學(xué)校個(gè)性化音樂(lè)教學(xué)的初探
- 【初中物理】2024-2025學(xué)年蘇科版初中物理八年級(jí)上冊(cè) 期中復(fù)習(xí)單選題練習(xí)
- 蘭州2024年統(tǒng)編版小學(xué)英語(yǔ)第3單元真題試卷
- 2024年高考數(shù)學(xué)復(fù)習(xí)試題專項(xiàng)匯編:函數(shù)與導(dǎo)數(shù)
- 2024年阻燃ABS熱塑性彈性體項(xiàng)目投資申請(qǐng)報(bào)告代可行性研究報(bào)告
- 2023年礦山施工設(shè)備:鑿巖機(jī)械投資申請(qǐng)報(bào)告
- 2024年玻璃纖維網(wǎng)墊項(xiàng)目資金申請(qǐng)報(bào)告代可行性研究報(bào)告
- 2023年抗生素類(lèi)藥品資金需求報(bào)告
- 臨床消化道出血高發(fā)年齡、出血征象、生命指癥評(píng)估、診斷鑒別及急診處理
- 監(jiān)督管理制度
- 2024版抗菌藥物DDD值速查表
- 小學(xué)二年級(jí)數(shù)學(xué)上冊(cè)期中試卷(全套)
- DB11T 1580-2018 生產(chǎn)經(jīng)營(yíng)單位安全生產(chǎn)應(yīng)急資源調(diào)查規(guī)范
- 各省中國(guó)鐵路限公司2024招聘(目前38183人)高頻難、易錯(cuò)點(diǎn)500題模擬試題附帶答案詳解
- 猜想04整式的乘法與因式分解(易錯(cuò)必刷30題10種題型專項(xiàng)訓(xùn)練)
- 大學(xué)實(shí)訓(xùn)室虛擬仿真平臺(tái)網(wǎng)絡(luò)VR實(shí)訓(xùn)室方案(建筑學(xué)科)
- 體育賽事組織與執(zhí)行手冊(cè)
- 北師大版(2024新版)七年級(jí)上冊(cè)數(shù)學(xué)期中學(xué)情評(píng)估檢測(cè)試卷(含答案解析)
- 【課件】跨學(xué)科實(shí)踐:制作隔音房間模型人教版物理八年級(jí)上冊(cè)
- 2024-2025學(xué)年高二英語(yǔ)選擇性必修第二冊(cè)(譯林版)UNIT 4 Grammar and usage教學(xué)課件
- 二十屆三中全會(huì)精神學(xué)習(xí)試題及答案(100題)
評(píng)論
0/150
提交評(píng)論