[Android執行個體]通話接通後震動提示

來源:互聯網
上載者:User


今天介紹一下在Android中實現通話接通後震動提示,這裡通話主要是針對撥出的電話.想要在接通的時候給出震動提示那麼我們就需要知道通話何時是被接通的.這樣才能在進入該狀態後給出提示.但SDK中並沒有直接獲得這種狀態的方式.首先我們看一下SDK中電話語音類為我們提供了哪些通話狀態.

SDK中的TelephonyManager類提供了3種電話的狀態.

CALL_STATE_IDLE 空閑狀態

CALL_STATE_OFFHOOK 摘機狀態

CALL_STATE_RINGING  響鈴狀態

這幾個狀態很容易理解,其中摘機狀態即拿起話筒(對於有線電話電話而言的動作),但這個狀態可能發生在撥入電話接通時,也可能是已撥電話時.但是卻不能說明已撥電話接通時.通過以上3種狀態我們僅能組合出:掛機,來電接通.這兩個狀態.而今天我們要實現的功能卻無法做到.

看來我們需要尋找其他方法來實現了,SDK靠不住啊……

 

還好Android在運行時會有大量的log產生,看看我們能不能從這上面找到突波口呢.我們選擇Android的Radio模組的日誌來分析.首先我們需要寫一段代碼來讀取Radio相關的log.讀取log就不得不用到logcat了.

Process process;<br />InputStream inputstream;<br />BufferedReader bufferedreader;<br />try {<br />process = Runtime.getRuntime().exec("logcat -v time -b radio");<br />inputstream = process.getInputStream();<br />InputStreamReader inputstreamreader = new InputStreamReader(<br />inputstream);<br />bufferedreader = new BufferedReader(inputstreamreader);<br />String str = "";<br />while ((str = bufferedreader.readLine()) != null) {<br /> log.i("mLogcat",str);<br />}<br />} catch (Exception e) {</p><p>} 

另外,要讓程式能夠讀取系統log需要指定許可權,在AndroidManifest.xml檔案中加入一下內容.

<uses-permission android:name="android.permission.READ_LOGS"></uses-permission> 

 

通過上面這段代碼我們就可以將Radio的log輸出到了,這樣我們就可以通過在DDMS中查看這些log,分析其中的通話過程.具體抓到的log就不貼出來了.大家可以自己編寫程式通過上面的代碼來抓取和分析.我只說一下我的分析結果.

通過分析log發現了一些蛛絲馬跡.其中有幾條日誌很有用.

GET_CURRENT_CALLS  id=1,DIALING

GET_CURRENT_CALLS  id=1,ALERTING

GET_CURRENT_CALLS  id=1,ACTIVE

由於log較長我只拿了每條log的開頭部分,真實的會多很多內容.當我們已撥電話的時候,會輸入這麼幾條log.

撥號->提醒->活動.

 

大致是這麼個過程.經過幾次測試發現,電話接通時會進入活動狀態,並會輸出:GET_CURRENT_CALLS  id=1,ACTIVE 
這條log,至此我們已經接近成功了.

不過之後我又發現在撥號開始到電話接通這段時間內會經過多次的

撥號->提醒->活動,這樣的狀態變化,僅當話筒中嘟聲響起後GET_CURRENT_CALLS這條日誌會鎖定在ALERTING.在電話接通前便不再出現

GET_CURRENT_CALLS日誌了.

可能上面的這段表述大家不是很清楚,換句話說在通話接通之前會出現多次的

GET_CURRENT_CALLS ACTIVE 這樣的日誌,而僅有一次是電話接通產生的.這就給我們造成了麻煩.不能只是單純的抓取GET_CURRENT_CALLS ACTIVE 這樣的資訊來判斷了.

我們只能通過一些邏輯上的判斷來實現了.下面看My Code.

class TestThread implements Runnable {<br />//震動器<br />Vibrator mVibrator;<br />//電話語音<br />TelephonyManager telManager;<br />public TestThread(Vibrator mVibrator, TelephonyManager telManager) {<br />this.mVibrator = mVibrator;<br />this.telManager = telManager;<br />}<br />@Override<br />public void run() {<br />//擷取當前話機狀態<br />int callState = telManager.getCallState();<br />Log.i("TestService", "開始.........." + Thread.currentThread().getName());<br />//記錄撥號開始時間<br />long threadStart = System.currentTimeMillis();<br />Process process;<br />InputStream inputstream;<br />BufferedReader bufferedreader;<br />try {<br />process = Runtime.getRuntime().exec("logcat -v time -b radio");<br />inputstream = process.getInputStream();<br />InputStreamReader inputstreamreader = new InputStreamReader(<br />inputstream);<br />bufferedreader = new BufferedReader(inputstreamreader);<br />String str = "";<br />long dialingStart = 0;<br />boolean enableVibrator = false;<br />boolean isAlert = false;<br />while ((str = bufferedreader.readLine()) != null) {<br />//如果話機狀態從摘機變為空白閑,銷毀線程<br />if (callState == TelephonyManager.CALL_STATE_OFFHOOK<br />&& telManager.getCallState() == TelephonyManager.CALL_STATE_IDLE) {<br />break;<br />}<br />// 線程運行5分鐘自動銷毀<br />if (System.currentTimeMillis() - threadStart > 300000) {<br />break;<br />}<br />Log.i("TestService", Thread.currentThread().getName() + ":"<br />+ str);<br />// 記錄GSM狀態DIALING<br />if (str.contains("GET_CURRENT_CALLS")<br />&& str.contains("DIALING")) {<br />// 當DIALING開始並且已經經過ALERTING或者首次DIALING<br />if (!isAlert || dialingStart == 0) {<br />//記錄DIALING狀態產生時間<br />dialingStart = System.currentTimeMillis();<br />isAlert = false;<br />}<br />continue;<br />}<br />if (str.contains("GET_CURRENT_CALLS")<br />&& str.contains("ALERTING")&&!enableVibrator) {</p><p>long temp = System.currentTimeMillis() - dialingStart;<br />isAlert = true;<br />//這個是關鍵,當第一次DIALING狀態的時間,與當前的ALERTING間隔時間在1.5秒以上並且在20秒以內的話<br />//那麼認為下次的ACTIVE狀態為通話接通.<br />if (temp > 1500 && temp < 20000) {<br />enableVibrator = true;<br />Log.i("TestService", "間隔時間....." + temp + "....."<br />+ Thread.currentThread().getName());<br />}<br />continue;<br />}<br />if (str.contains("GET_CURRENT_CALLS") && str.contains("ACTIVE")<br />&& enableVibrator) {<br />mVibrator.vibrate(100);<br />enableVibrator = false;<br />break;<br />}<br />}<br />Log.i("TestService", "結束.........."<br />+ Thread.currentThread().getName());<br />} catch (Exception e) {<br />// TODO: handle exception<br />}<br />}<br />}<br /> 

我的這個方法比較牽強,是通過判斷第一次DIALING與每一次ALERTING之間的間隔,當間隔大於1.5秒.那麼認為已經進入了"嘟"聲提示的時候了,那麼下一個ACTIVE將是電話接通.這個1.5秒是通過分析日誌得出的.但是這種方法我始終覺得不太靠譜.如果大家有好的方法可以交流交流.

剩下的就是讓這個線程在電話撥出時觸發,並且常駐在電話中時候準備這就可以了.可以採用Service配合Receiver來實現.Service來實現常駐,Receiver來實現監聽已撥電話.基本就可以完成,我們想要的功能了.

以上代碼我都測試過99%有效,哈哈.這裡面提到了一些Android的基礎內容像logcat,Service,Receiver.這些如果大家不瞭解的話可以到網上搜一下.有很多寫的很不錯的文章介紹Android的基礎內容.我這裡就不一一介紹了.

希望我寫的東西對大家有所協助.OK,就到這裡吧.

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.