[Android例項]通話接通後震動提示
今天介紹一下在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;
- 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) {
- }
另外,要讓程式能夠讀取系統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 這樣的資訊來判斷了.
我們只能通過一些邏輯上的判斷來實現了.下面看我的程式碼.
- 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", "開始.........." + 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;
- }
- // 執行緒執行5分鐘自動銷燬
- if (System.currentTimeMillis() - threadStart > 300000) {
- break;
- }
- Log.i("TestService", Thread.currentThread().getName() + ":"
- + str);
- // 記錄GSM狀態DIALING
- if (str.contains("GET_CURRENT_CALLS")
- && str.contains("DIALING")) {
- // 當DIALING開始並且已經經過ALERTING或者首次DIALING
- if (!isAlert || dialingStart == 0) {
- //記錄DIALING狀態產生時間
- dialingStart = System.currentTimeMillis();
- isAlert = false;
- }
- continue;
- }
- if (str.contains("GET_CURRENT_CALLS")
- && str.contains("ALERTING")&&!enableVibrator) {
- long temp = System.currentTimeMillis() - dialingStart;
- isAlert = true;
- //這個是關鍵,當第一次DIALING狀態的時間,與當前的ALERTING間隔時間在1.5秒以上並且在20秒以內的話
- //那麼認為下次的ACTIVE狀態為通話接通.
- if (temp > 1500 && temp < 20000) {
- enableVibrator = true;
- Log.i("TestService", "間隔時間....." + temp + "....."
- + Thread.currentThread().getName());
- }
- continue;
- }
- if (str.contains("GET_CURRENT_CALLS") && str.contains("ACTIVE")
- && enableVibrator) {
- mVibrator.vibrate(100);
- enableVibrator = false;
- break;
- }
- }
- Log.i("TestService", "結束.........."
- + Thread.currentThread().getName());
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- }
我的這個方法比較牽強,是通過判斷第一次DIALING與每一次ALERTING之間的間隔,當間隔大於1.5秒.那麼認為已經進入了"嘟"聲提示的時候了,那麼下一個ACTIVE將是電話接通.這個1.5秒是通過分析日誌得出的.但是這種方法我始終覺得不太靠譜.如果大家有好的方法可以交流交流.
剩下的就是讓這個執行緒在電話撥出時觸發,並且常駐在電話中時候準備這就可以了.可以採用Service配合Receiver來實現.Service來實現常駐,Receiver來實現監聽撥出電話.基本就可以完成,我們想要的功能了.
以上程式碼我都測試過99%有效,哈哈.這裡面提到了一些Android的基礎內容像logcat,Service,Receiver.這些如果大家不瞭解的話可以到網上搜一下.有很多寫的很不錯的文章介紹Android的基礎內容.我這裡就不一一介紹了.
希望我寫的東西對大家有所幫助.OK,就到這裡吧.
相關文章
- js元素的震動效果程式碼例項JS
- freeswitch 接通後再錄音
- 模擬阻塞會話例項會話
- Oracle11g RAC在例項關閉後自動在啟動例項上歸檔Oracle
- Android 動態載入資源例項解析Android
- 移動端點選彈出提示視窗程式碼例項
- android ShapeDrawable例項Android
- android Dialog例項Android
- Android hello world例項Android
- java串列埠通訊例項 -Java串列埠
- js通過拖動調整元素位置程式碼例項JS
- 表單提示美化效果程式碼例項
- 密碼框提示文字程式碼例項密碼
- Android 網路通訊API的選擇和實現例項AndroidAPI
- android 視訊通話相關Android
- android 多項對話方塊Android
- android view 自定義viewgroup 例項--螢幕滑動AndroidView
- android移動開發簡單的開發例項Android移動開發
- 通過滑鼠拖動選取指定數字程式碼例項
- 通過SQL*Plus遠端啟動Oracle資料庫例項SQLOracle資料庫
- Android uiautomator例項使用AndroidUI
- 通過例項學習 PyTorchPyTorch
- C# 通過反射建立例項C#反射
- 通過例項學習 tcpdump 命令TCP
- 三通基礎與例項
- js實現文字框提示程式碼例項JS
- [android]android自動化測試十之單元測試例項Android
- jQuery 數秒後自動提交form表單程式碼例項jQueryORM
- Android native程式間通訊例項-binder結合共享記憶體Android記憶體
- Android獲取其他包的Context例項然後XX(轉載)AndroidContext
- Android -- 與WEB互動在同一個會話Session中通訊AndroidWeb會話Session
- 手動建立Oracle例項Oracle
- led驅動程式例項
- [Android]Gank 元件化例項AppAndroid元件化APP
- android socket程式設計例項Android程式設計
- [Android]單元測試例項Android
- android的Log輸出(例項)Android
- Android RecyclerView 簡介與例項AndroidView