http://blog.csdn.net/tyfjy/article/details/6452126
今天介紹一下在Android中實(shí)現(xiàn)通話接通后震動(dòng)提示,這里通話主要是針對(duì)撥出的電話.想要在接通的時(shí)候給出震動(dòng)提示那么我們就需要知道通話何時(shí)是被接通的.這樣才能在進(jìn)入該狀態(tài)后給出提示.但SDK中并沒(méi)有直接獲得這種狀態(tài)的方式.首先我們看一下SDK中電話服務(wù)類(lèi)為我們提供了哪些通話狀態(tài).
SDK中的TelephonyManager類(lèi)提供了3種電話的狀態(tài).
CALL_STATE_IDLE 空閑狀態(tài)
CALL_STATE_OFFHOOK 摘機(jī)狀態(tài)
CALL_STATE_RINGING 響鈴狀態(tài)
這幾個(gè)狀態(tài)很容易理解,其中摘機(jī)狀態(tài)即拿起話筒(對(duì)于座機(jī)電話而言的動(dòng)作),但這個(gè)狀態(tài)可能發(fā)生在撥入電話接通時(shí),也可能是撥出電話時(shí).但是卻不能說(shuō)明撥出電話接通時(shí).通過(guò)以上3種狀態(tài)我們僅能組合出:掛機(jī),來(lái)電接通.這兩個(gè)狀態(tài).而今天我們要實(shí)現(xiàn)的功能卻無(wú)法做到.
看來(lái)我們需要尋找其他方法來(lái)實(shí)現(xiàn)了,SDK靠不住啊……
還好Android在運(yùn)行時(shí)會(huì)有大量的log產(chǎn)生,看看我們能不能從這上面找到突波口呢.我們選擇Android的Radio模塊的日志來(lái)分析.首先我們需要寫(xiě)一段代碼來(lái)讀取Radio相關(guān)的log.讀取log就不得不用到logcat了.
- Process process;
- InputStream inputstream;
- BufferedReader bufferedreader;
- try {
- process = Runtime.getRuntime().exec("logcat -v time -b radio");
- inputstream = process.getInputStream();
- InputStreamReader inputstreamreader = new InputStreamReader(
- inputstream);
- bufferedreader = new BufferedReader(inputstreamreader);
- String str = "";
- while ((str = bufferedreader.readLine()) != null) {
- log.i("mLogcat",str);
- }
- } catch (Exception e) {
-
- }
另外,要讓程序能夠讀取系統(tǒng)log需要指定權(quán)限,在AndroidManifest.xml文件中加入一下內(nèi)容.
- <uses-permission android:name="android.permission.READ_LOGS"></uses-permission>
通過(guò)上面這段代碼我們就可以將Radio的log輸出到了,這樣我們就可以通過(guò)在DDMS中查看這些log,分析其中的通話過(guò)程.具體抓到的log就不貼出來(lái)了.大家可以自己編寫(xiě)程序通過(guò)上面的代碼來(lái)抓取和分析.我只說(shuō)一下我的分析結(jié)果.
通過(guò)分析log發(fā)現(xiàn)了一些蛛絲馬跡.其中有幾條日志很有用.
GET_CURRENT_CALLS id=1,DIALING
GET_CURRENT_CALLS id=1,ALERTING
GET_CURRENT_CALLS id=1,ACTIVE
由于log較長(zhǎng)我只拿了每條log的開(kāi)頭部分,真實(shí)的會(huì)多很多內(nèi)容.當(dāng)我們撥出電話的時(shí)候,會(huì)輸入這么幾條log.
撥號(hào)->提醒->活動(dòng).
大致是這么個(gè)過(guò)程.經(jīng)過(guò)幾次測(cè)試發(fā)現(xiàn),電話接通時(shí)會(huì)進(jìn)入活動(dòng)狀態(tài),并會(huì)輸出:GET_CURRENT_CALLS id=1,ACTIVE 這條log,至此我們已經(jīng)接近成功了.
不過(guò)之后我又發(fā)現(xiàn)在撥號(hào)開(kāi)始到電話接通這段時(shí)間內(nèi)會(huì)經(jīng)過(guò)多次的
撥號(hào)->提醒->活動(dòng),這樣的狀態(tài)變化,僅當(dāng)話筒中嘟聲響起后GET_CURRENT_CALLS這條日志會(huì)鎖定在ALERTING.在電話接通前便不再出現(xiàn)
GET_CURRENT_CALLS日志了.
可能上面的這段表述大家不是很清楚,換句話說(shuō)在通話接通之前會(huì)出現(xiàn)多次的
GET_CURRENT_CALLS ACTIVE 這樣的日志,而僅有一次是電話接通產(chǎn)生的.這就給我們?cè)斐闪寺闊?span lang="EN-US">.不能只是單純的抓取GET_CURRENT_CALLS ACTIVE 這樣的信息來(lái)判斷了.
我們只能通過(guò)一些邏輯上的判斷來(lái)實(shí)現(xiàn)了.下面看我的代碼.
- class TestThread implements Runnable {
-
- Vibrator mVibrator;
-
- TelephonyManager telManager;
- public TestThread(Vibrator mVibrator, TelephonyManager telManager) {
- this.mVibrator = mVibrator;
- this.telManager = telManager;
- }
- @Override
- public void run() {
-
- int callState = telManager.getCallState();
- Log.i("TestService", "開(kāi)始.........." + Thread.currentThread().getName());
-
- long threadStart = System.currentTimeMillis();
- Process process;
- InputStream inputstream;
- BufferedReader bufferedreader;
- try {
- process = Runtime.getRuntime().exec("logcat -v time -b radio");
- inputstream = process.getInputStream();
- InputStreamReader inputstreamreader = new InputStreamReader(
- inputstream);
- bufferedreader = new BufferedReader(inputstreamreader);
- String str = "";
- long dialingStart = 0;
- boolean enableVibrator = false;
- boolean isAlert = false;
- while ((str = bufferedreader.readLine()) != null) {
-
- if (callState == TelephonyManager.CALL_STATE_OFFHOOK
- && telManager.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
- break;
- }
-
- if (System.currentTimeMillis() - threadStart > 300000) {
- break;
- }
- Log.i("TestService", Thread.currentThread().getName() + ":"
- + str);
-
- if (str.contains("GET_CURRENT_CALLS")
- && str.contains("DIALING")) {
-
- if (!isAlert || dialingStart == 0) {
-
- dialingStart = System.currentTimeMillis();
- isAlert = false;
- }
- continue;
- }
- if (str.contains("GET_CURRENT_CALLS")
- && str.contains("ALERTING")&&!enableVibrator) {
-
- long temp = System.currentTimeMillis() - dialingStart;
- isAlert = true;
-
-
- if (temp > 1500 && temp < 20000) {
- enableVibrator = true;
- Log.i("TestService", "間隔時(shí)間....." + temp + "....."
- + Thread.currentThread().getName());
- }
- continue;
- }
- if (str.contains("GET_CURRENT_CALLS") && str.contains("ACTIVE")
- && enableVibrator) {
- mVibrator.vibrate(100);
- enableVibrator = false;
- break;
- }
- }
- Log.i("TestService", "結(jié)束.........."
- + Thread.currentThread().getName());
- } catch (Exception e) {
-
- }
- }
- }
我的這個(gè)方法比較牽強(qiáng),是通過(guò)判斷第一次DIALING與每一次ALERTING之間的間隔,當(dāng)間隔大于1.5秒.那么認(rèn)為已經(jīng)進(jìn)入了"嘟"聲提示的時(shí)候了,那么下一個(gè)ACTIVE將是電話接通.這個(gè)1.5秒是通過(guò)分析日志得出的.但是這種方法我始終覺(jué)得不太靠譜.如果大家有好的方法可以交流交流.
剩下的就是讓這個(gè)線程在電話撥出時(shí)觸發(fā),并且常駐在電話中時(shí)候準(zhǔn)備這就可以了.可以采用Service配合Receiver來(lái)實(shí)現(xiàn).Service來(lái)實(shí)現(xiàn)常駐,Receiver來(lái)實(shí)現(xiàn)監(jiān)聽(tīng)撥出電話.基本就可以完成,我們想要的功能了.
以上代碼我都測(cè)試過(guò)99%有效,哈哈.這里面提到了一些Android的基礎(chǔ)內(nèi)容像logcat,Service,Receiver.這些如果大家不了解的話可以到網(wǎng)上搜一下.有很多寫(xiě)的很不錯(cuò)的文章介紹Android的基礎(chǔ)內(nèi)容.我這里就不一一介紹了.
希望我寫(xiě)的東西對(duì)大家有所幫助.OK,就到這里吧.