最近在做的一個crm項目要求實現(xiàn)實時上傳通話記錄和自動撥打電話功能,研究了一下電話相關(guān)的一系列功能墙基,趁著今天不忙在此總結(jié)下软族,做個備忘。
一残制、讀取通話記錄:
? ? ? ? 1立砸、首先android讀取通話記錄需要在清單文件添加相關(guān)權(quán)限<uses-permission android:name="android.permission.READ_CALL_LOG"/>
? ? ? ? 2、獲取通話記錄
Cursor:Cursor cursor= ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
getContentResolver().query(CallLog.Calls.CONTENT_URI,newString[{CallLog.Calls.DURATION,CallLog.Calls.TYPE,CallLog.
Calls.DATE,CallLog.Calls.NUMBER},null,null,CallLog.Calls.DEFAULT_SORT_ORDER);
? ? ? ? 3初茶、從每個cursor讀取對應每條通話記錄內(nèi)容:
while(cursor.moveToNext()) {
?type=cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));//1來電颗祝;2去電
?duration=cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DURATION));//時長
?date=cursor.getString(cursor.getColumnIndex(CallLog.Calls.DATE));//時間
?telnum=cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));//號碼
?}
? ? ? ? ? 4、拿到數(shù)據(jù)按需求做你想做的事恼布,就這么簡單
二螺戳、自動撥號:
? ? ? 1、添加權(quán)限 android.permission.CALL_PHONE
? ? ? 2折汞、調(diào)用打電話代碼一個intent即可實現(xiàn)
Uri uri=Uri.parse("tel:"+ phoneNum.trim());
Intent intent=newIntent(Intent.ACTION_CALL,uri);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
mActivity.startActivityForResult(intent,520);
? ? ? ? 3倔幼、正常情況當你調(diào)用這幾行代碼的確可以播出電話,但是問題來啦字支,android手機對自動撥號是有權(quán)限詢問的凤藏,更有甚者用戶在系統(tǒng)設置禁 止了該權(quán)限奸忽。這兩種情況最終造成我們的功能體驗都不太好。所以解決思路就是引導用戶去系統(tǒng)設置給我們的應用自動撥號權(quán)限添加允 ? ? ? ? ? ? ? ? 許揖庄。這種情況就要求我們在撥號之前檢查是否有該權(quán)限栗菜,但是api23之前是沒有直接的方法可以調(diào)用查詢的至于23之后有沒有我沒有去確? ? ? ? ? ? ? ? 認,但是在我后來做手機通話狀態(tài)監(jiān)聽的時候我發(fā)現(xiàn)蹄梢,當有允許權(quán)限的時候startActivityForResult(intent,520)之后系統(tǒng)會發(fā)一個去電的廣 ? ? ? ? ? ? ?播android.intent.action.NEW_OUTGOING_CALL疙筹,而后會再調(diào)用mActivity的onActivityResult方法,如果權(quán)限被禁止或者處于詢問(小 ? ? ? ? ? ? ? 米)就會直接(或先)調(diào)用onActivityResult方法禁炒。這樣我們就可以在onActivityResult判斷是否開啟了允許權(quán)限而咆,若果沒有就可一彈框引導? ? ? ? ? ? ? 用戶去開起了。
三幕袱、自動掛斷:android掛斷電話的調(diào)用方法在ITelephony.java里而ITelephony.java是隱藏的暴备,我們不能直接調(diào)用endCall()方法所以我們要實現(xiàn)就緒做如下操作。
1们豌、由于ITelephony.java的包名是com.android.internal.telephony在自己項目src/main下創(chuàng)建aidl文件夾在該文件下創(chuàng)建包com.android.internal.telephony然后copy android源碼中的ITelephony.aidl文件到com.android.internal.telephony
2涯捻、由于ITelephony.aidl關(guān)聯(lián)了NeighboringCellInfo.aidl所以也一起copy過來包名android.telephony
3、兩個文件copy完之后clean一下望迎,你就會在你的gen目錄下發(fā)現(xiàn)已經(jīng)生成了ITelephony.java這個接口文件障癌,雖然生成了.java文件但是我們并不能直接調(diào)用,這是因為ITelephony對象是以一個系統(tǒng)服務的形式存在系統(tǒng)中的辩尊,所一要通過ServiceManager來拿到ITelephony對象涛浙,but? ServiceManager也是隱藏的。我們可以通過反射先拿到ServiceManager在通過ServiceManager.getService(String name)方法來取得ITelephony對象摄欲,而這個name就是當時addService()的時候使用的name(也就是phone)
Method method=null;
try{
method=Class.forName("android.os.ServiceManager").getMethod("getService",String.class);
IBinder binder= (IBinder)method.invoke(null,newObject[]{"phone"});
ITelephony telephony=ITelephony.Stub.asInterface(binder);
telephony.endCall();
}catch(NoSuchMethodExceptione) {
e.printStackTrace();
}catch(ClassNotFoundExceptione) {
e.printStackTrace();
}catch(InvocationTargetExceptione) {
e.printStackTrace();
}catch(IllegalAccessExceptione) {
e.printStackTrace();
}catch(RemoteExceptione) {
e.printStackTrace();
}
四轿亮、自動接聽
? ? ? ?1、由于自動接聽也是用到ITelephony所以基本準備工作與三相同
? ? ? 2胸墙、添加權(quán)限android.permission.CALL_PHONE和android.permission.MODIFY_PHONE_STATE
? ? ? 3哀托、廢話不再多說直接上代碼
Method method=null;
try{
method=Class.forName("android.os.ServiceManager").getMethod("getService",String.class);
IBinder binder= (IBinder)method.invoke(null,newObject[]{"phone"});
ITelephony telephony=ITelephony.Stub.asInterface(binder);
telephony.answerRingingCall();
}catch(NoSuchMethodExceptione) {
e.printStackTrace();
}catch(ClassNotFoundExceptione) {
e.printStackTrace();
}catch(InvocationTargetExceptione) {
e.printStackTrace();
}catch(IllegalAccessExceptione) {
e.printStackTrace();
}catch(RemoteExceptione) {
e.printStackTrace();
}
4、但是answerRingingCall()在4.1之后增加了權(quán)限檢查(自動掛斷電話沒有)劳秋,這個時候再調(diào)用上面的方法會catch到一個Exception仓手,我們可以在catch里走另外一套自動接聽的方法,可以看一下packages/apps/Phone/src/com/android/phone/PhoneGlobals.java的源碼玻淑,你會發(fā)現(xiàn)里面注冊一個廣播接收器MediaButtonBroadcastReceiver嗽冒,action就是“android.intent.action.MEDIA_BUTTON”并且在receiver方法里做了answerCall(phone.getRingingCall());接聽電話的操作,所以我們在catch里只需發(fā)一個相應的廣播就可以啦补履,是的你沒看錯就是發(fā)一個廣播就可以啦就是這么逗添坊。