2、介绍完了来电自动录音,下面就来介绍去电自动录音的实现方法。上面说过,相比来电状态的监听,去电的要麻烦些,甚至这种方法不是通用的,这个主要是因为android api 中没有提供去电状态监听的相应类和方法(也许我刚接触,没有找到)。刚开始网上搜索了一通也没有找到对应的解决方法,大多是 来电监听的,也就是上面的方法。不过中途发现一篇博文(后来就搜不到了),记得是查询系统日志的方式,从中找到去电过程中的各个状态的关键词。无奈之中,最终妥协了此方法。

我的(联想A65上的)去电日志内容如下

过滤关键词为 mforeground


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
18. 01-06 16:30:00.399: V/LogInfo OutGoing Call(2492): D/InCallScreen(  251): - onDisconnect: currentlyIdle:true
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
 



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 ,再看看是否包含上面的状态的 单词。既然说的如此,那么看看读取系统日志的代码吧
 

1. package
2.  
3. import
4. import
5. import
6. import
7.  
8. import
9.  
10. import
11. import
12. import
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
28. private
29. private int
30.      
31. private static final String TAG = "LogInfo OutGoing Call"; 
32.      
33. /**
34.      *  前后台电话
35.      * @author sdvdxl
36.      *  
37.      */
38. private static class
39. public static final String FORE_GROUND_CALL_STATE = "mForeground"; 
40.     } 
41.      
42. /**
43.      * 呼叫状态
44.      * @author sdvdxl
45.      *
46.      */
47. private static class
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
56. this.ctx = ctx; 
57.     } 
58.      
59. /**
60.      * 读取Log流
61.      * 取得呼出状态的log
62.      * 从而得到转换状态
63.      */
64. @Override
65. public void
66. "开始读取日志记录"); 
67.          
68. "logcat", "InCallScreen *:s"}; 
69. "logcat", "-c"}; 
70.          
71. try
72.             Process process=Runtime.getRuntime().exec(catchParams); 
73.             InputStream is = process.getInputStream(); 
74. new BufferedReader(new
75.              
76. 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. //销毁进程,释放资源
87. 0; 
88. "-----------清理日志---------------"); 
89.                 }    
90.                  
91. /*---------------------------------前台呼叫-----------------------*/
92. //空闲
93. if
94.                         && line.contains(ReadLog.CallState.IDLE)) { 
95.                     Log.d(TAG, ReadLog.CallState.IDLE); 
96.                 } 
97.                  
98. //正在拨号,等待建立连接,即已拨号,但对方还没有响铃,
99. if
100.                         && line.contains(ReadLog.CallState.DIALING)) { 
101.                     Log.d(TAG, ReadLog.CallState.DIALING); 
102.                 } 
103.                  
104. //呼叫对方 正在响铃
105. if
106.                         && line.contains(ReadLog.CallState.ALERTING)) { 
107.                     Log.d(TAG, ReadLog.CallState.ALERTING); 
108.                 } 
109.                  
110. //已接通,通话建立
111. if
112.                         && line.contains(ReadLog.CallState.ACTIVE)) { 
113.                     Log.d(TAG, ReadLog.CallState.ACTIVE); 
114.                 } 
115.                  
116. //断开连接,即挂机
117. if
118.                         && line.contains(ReadLog.CallState.DISCONNECTED)) { 
119.                     Log.d(TAG, ReadLog.CallState.DISCONNECTED); 
120.                 } 
121.                  
122. //END while
123.              
124. catch
125.             e.printStackTrace(); 
126. //END try-catch
127. //END run
128. } //END class ReadLog

         以上代码中,之所以用线程,是为了防止读取日志过程中阻滞主方法的其他方法的执行,影响到程序捕捉对应的电话状态。
       未完  继续阅读 

另附 工程源代码


转载于:https://blog.51cto.com/sdvdxl/1109862