Android 來去電自動錄音 (二)

 二、介紹完了來電自動錄音,下面就來介紹去電自動錄音的實現方法。上面說過,相比來電狀態的監聽,去電的要麻煩些,甚至這種方法不是通用的,這個主要是由於android api 中沒有提供去電狀態監聽的相應類和方法(也許我剛接觸,沒有找到)。剛開始網上搜索了一通也沒有找到對應的解決方法,大可能是 來電監聽的,也就是上面的方法。不過中途發現一篇博文(後來就搜不到了),記得是查詢系統日誌的方式,從中找到去電過程當中的各個狀態的關鍵詞。無奈之中,最終妥協了此方法。java

個人(聯想A65上的)去電日誌內容以下

過濾關鍵詞爲 mforegroundandroid

  
  
  
  
  1. 01-06 16:29:54.225: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  2. 01-06 16:29:54.245: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  3. 01-06 16:29:54.631: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  4. 01-06 16:29:54.645: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  5. 01-06 16:29:54.742: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  6. 01-06 16:29:54.766: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  7. 01-06 16:29:54.873: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  8. 01-06 16:29:54.877: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  9. 01-06 16:29:55.108: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  10. 01-06 16:29:55.125: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : DIALING 
  11. 01-06 16:29:57.030: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : ACTIVE 
  12. 01-06 16:29:57.155: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : ACTIVE 
  13. 01-06 16:29:57.480: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : ACTIVE 
  14. 01-06 16:29:57.598: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : ACTIVE 
  15. 01-06 16:29:59.319: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : DISCONNECTING 
  16. 01-06 16:29:59.373: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : DISCONNECTING 
  17. 01-06 16:30:00.392: D/InCallScreen(251): - onDisconnect: currentlyIdle:true ; mForegroundCall.getState():DISCONNECTED 
  18. 01-06 16:30:00.399: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): - onDisconnect: currentlyIdle:true ; mForegroundCall.getState():DISCONNECTED 
  19. 01-06 16:30:01.042: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : IDLE 
  20. 01-06 16:30:01.070: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : IDLE 
  21. 01-06 16:30:01.558: D/InCallScreen(251): onPhoneStateChanged: mForegroundCall.getState() : IDLE 
  22. 01-06 16:30:01.572: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mForegroundCall.getState() : IDLE 

 

過濾關鍵詞  mbackground
 sql

  
  
  
  
  1. 01-06 16:29:54.226: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  2. 01-06 16:29:54.256: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  3. 01-06 16:29:54.638: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  4. 01-06 16:29:54.652: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  5. 01-06 16:29:54.743: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  6. 01-06 16:29:54.770: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  7. 01-06 16:29:54.875: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  8. 01-06 16:29:54.882: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  9. 01-06 16:29:55.109: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  10. 01-06 16:29:55.142: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  11. 01-06 16:29:57.031: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  12. 01-06 16:29:57.160: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  13. 01-06 16:29:57.481: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  14. 01-06 16:29:57.622: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  15. 01-06 16:29:59.319: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  16. 01-06 16:29:59.373: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  17. 01-06 16:30:01.042: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  18. 01-06 16:30:01.070: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  19. 01-06 16:30:01.559: D/InCallScreen(251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 
  20. 01-06 16:30:01.573: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): onPhoneStateChanged: mBackgroundCall.getState() : IDLE 

從上面的日誌能夠看到,每一行的末尾的大寫英文詞就是去電的狀態,狀態說明以下:
DIALING 撥號,對方還未響鈴
ACTIVE   對方接通,通話創建
DISCONNECTING 通話斷開時
DISCONNECTED  通話已斷開,能夠認爲是掛機了
因爲我撥打的是10010,沒有響鈴過程(電腦自動接通的夠快),還少了一個狀態,狀態是ALERTING  這個就是對方正在響鈴的狀態
有了這幾個去電狀態就好辦了,如今咱們要作的就是讀取系統日誌,而後找到這些狀態,提取的關鍵詞就是上面提到的 mforeground(前臺通話狀態) 和 mbackground (後臺通話狀態)(可能不同的設備生成的不同,根據本身具體設備設置,這裏只提取前臺的),若是讀取的這一行日誌中 包含 mforground ,再看看是否包含上面的狀態的 單詞。既然說的如此,那麼看看讀取系統日誌的代碼吧
 api

  
  
  
  
  1. package com.sdvdxl.phonerecorder; 
  2.  
  3. import java.io.BufferedReader; 
  4. import java.io.IOException; 
  5. import java.io.InputStream; 
  6. import java.io.InputStreamReader; 
  7.  
  8. import com.sdvdxl.outgoingcall.OutgoingCallState; 
  9.  
  10. import android.content.Context; 
  11. import android.content.Intent; 
  12. import android.util.Log; 
  13.  
  14. /** 
  15.  *  
  16.  * @author sdvdxl 
  17.  *  找到 日誌中的 
  18.  *  onPhoneStateChanged: mForegroundCall.getState() 這個是前臺呼叫狀態 
  19.  *  mBackgroundCall.getState() 後臺電話 
  20.  *  若 是 DIALING 則是正在撥號,等待創建鏈接,但對方尚未響鈴, 
  21.  *  ALERTING 呼叫成功,即對方正在響鈴, 
  22.  *  如果 ACTIVE 則已經接通 
  23.  *  如果 DISCONNECTED 則本號碼呼叫已經掛斷 
  24.  *  如果 IDLE 則是處於 空閒狀態 
  25.  *   
  26.  */ 
  27. public class ReadLog extends Thread { 
  28.     private Context ctx; 
  29.     private int logCount; 
  30.      
  31.     private static final String TAG = "LogInfo OutGoing Call"
  32.      
  33.     /** 
  34.      *  先後臺電話 
  35.      * @author sdvdxl 
  36.      *   
  37.      */ 
  38.     private static class CallViewState { 
  39.         public static final String FORE_GROUND_CALL_STATE = "mForeground"
  40.     } 
  41.      
  42.     /** 
  43.      * 呼叫狀態 
  44.      * @author sdvdxl 
  45.      * 
  46.      */ 
  47.     private static class CallState { 
  48.         public static final String DIALING = "DIALING"
  49.         public static final String ALERTING = "ALERTING"
  50.         public static final String ACTIVE = "ACTIVE"
  51.         public static final String IDLE = "IDLE"
  52.         public static final String DISCONNECTED = "DISCONNECTED"
  53.     } 
  54.      
  55.     public ReadLog(Context ctx) { 
  56.         this.ctx = ctx; 
  57.     } 
  58.      
  59.     /** 
  60.      * 讀取Log流 
  61.      * 取得呼出狀態的log 
  62.      * 從而獲得轉換狀態 
  63.      */ 
  64.     @Override 
  65.     public void run() { 
  66.         Log.d(TAG, "開始讀取日誌記錄"); 
  67.          
  68.         String[] catchParams = {"logcat""InCallScreen *:s"}; 
  69.         String[] clearParams = {"logcat""-c"}; 
  70.          
  71.         try { 
  72.             Process process=Runtime.getRuntime().exec(catchParams); 
  73.             InputStream is = process.getInputStream(); 
  74.             BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
  75.              
  76.             String line = null
  77.             while ((line=reader.readLine())!=null) { 
  78.                 logCount++; 
  79.                 //輸出全部 
  80.             Log.v(TAG, line); 
  81.                  
  82.                 //日誌超過512條就清理 
  83.                 if (logCount>512) { 
  84.                     //清理日誌 
  85.                     Runtime.getRuntime().exec(clearParams) 
  86.                         .destroy();//銷燬進程,釋放資源 
  87.                     logCount = 0
  88.                     Log.v(TAG, "-----------清理日誌---------------"); 
  89.                 }    
  90.                  
  91.                 /*---------------------------------前臺呼叫-----------------------*/ 
  92.                 //空閒 
  93.                 if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE) 
  94.                         && line.contains(ReadLog.CallState.IDLE)) { 
  95.                     Log.d(TAG, ReadLog.CallState.IDLE); 
  96.                 } 
  97.                  
  98.                 //正在撥號,等待創建鏈接,即已撥號,但對方尚未響鈴, 
  99.                 if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE) 
  100.                         && line.contains(ReadLog.CallState.DIALING)) { 
  101.                     Log.d(TAG, ReadLog.CallState.DIALING); 
  102.                 } 
  103.                  
  104.                 //呼叫對方 正在響鈴 
  105.                 if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE) 
  106.                         && line.contains(ReadLog.CallState.ALERTING)) { 
  107.                     Log.d(TAG, ReadLog.CallState.ALERTING); 
  108.                 } 
  109.                  
  110.                 //已接通,通話創建 
  111.                 if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE) 
  112.                         && line.contains(ReadLog.CallState.ACTIVE)) { 
  113.                     Log.d(TAG, ReadLog.CallState.ACTIVE); 
  114.                 } 
  115.                  
  116.                 //斷開鏈接,即掛機 
  117.                 if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE) 
  118.                         && line.contains(ReadLog.CallState.DISCONNECTED)) { 
  119.                     Log.d(TAG, ReadLog.CallState.DISCONNECTED); 
  120.                 } 
  121.                  
  122.             } //END while 
  123.              
  124.         } catch (IOException e) { 
  125.             e.printStackTrace(); 
  126.         } //END try-catch 
  127.     } //END run 
  128. //END class ReadLog 

         以上代碼中,之因此用線程,是爲了防止讀取日誌過程當中阻滯主方法的其餘方法的執行,影響到程序捕捉對應的電話狀態。
       未完  繼續閱讀 ide

另附 工程源代碼this

相關文章
相關標籤/搜索