Android 来去电自动录音 (三)

 好了,捕捉到了去电过程中各个状态的转变,那么,如何通知给程序呢,我采用的方法是捕获后立马给系统发送广播,然后程序进行广播接受,接受后在处理录音事件。要发送广播,就要发送一个唯一的广播,为此,建立如下类,

 

  1. package com.sdvdxl.outgoingcall; 
  2.  
  3. import com.sdvdxl.phonerecorder.ReadLog; 
  4.  
  5. import android.content.Context; 
  6. import android.util.Log; 
  7.  
  8. public class OutgoingCallState { 
  9.     Context ctx; 
  10.     public OutgoingCallState(Context ctx) { 
  11.         this.ctx = ctx; 
  12.     } 
  13.      
  14.     /** 
  15.      * 前台呼叫状态 
  16.      * @author sdvdxl 
  17.      * 
  18.      */ 
  19.     public static final class ForeGroundCallState { 
  20.         public static final String DIALING =  
  21.                 "com.sdvdxl.phonerecorder.FORE_GROUND_DIALING"
  22.         public static final String ALERTING =  
  23.                 "com.sdvdxl.phonerecorder.FORE_GROUND_ALERTING"
  24.         public static final String ACTIVE =  
  25.                 "com.sdvdxl.phonerecorder.FORE_GROUND_ACTIVE"
  26.         public static final String IDLE =  
  27.                 "com.sdvdxl.phonerecorder.FORE_GROUND_IDLE"
  28.         public static final String DISCONNECTED =  
  29.                 "com.sdvdxl.phonerecorder.FORE_GROUND_DISCONNECTED"
  30.     } 
  31.      
  32.     /** 
  33.      * 开始监听呼出状态的转变, 
  34.      * 并在对应状态发送广播 
  35.      */ 
  36.     public void startListen() { 
  37.         new ReadLog(ctx).start(); 
  38.         Log.d("Recorder""开始监听呼出状态的转变,并在对应状态发送广播"); 
  39.     } 
  40.      

程序需要读取系统日志权限

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

然后,在读取日志的类中检测到去电各个状态的地方发送一个广播,那么,读取日志的完整代码如下 
 

  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 mrloong 
  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.                     //发送广播 
  102.                     Intent dialingIntent = new Intent(); 
  103.                     dialingIntent.setAction(OutgoingCallState.ForeGroundCallState.DIALING); 
  104.                     ctx.sendBroadcast(dialingIntent); 
  105.                      
  106.                     Log.d(TAG, ReadLog.CallState.DIALING); 
  107.                 } 
  108.                  
  109.                 //呼叫对方 正在响铃 
  110.                 if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE) 
  111.                         && line.contains(ReadLog.CallState.ALERTING)) { 
  112.                     //发送广播 
  113.                     Intent dialingIntent = new Intent(); 
  114.                     dialingIntent.setAction(OutgoingCallState.ForeGroundCallState.ALERTING); 
  115.                     ctx.sendBroadcast(dialingIntent); 
  116.                      
  117.                     Log.d(TAG, ReadLog.CallState.ALERTING); 
  118.                 } 
  119.                  
  120.                 //已接通,通话建立 
  121.                 if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE) 
  122.                         && line.contains(ReadLog.CallState.ACTIVE)) { 
  123.                     //发送广播 
  124.                     Intent dialingIntent = new Intent(); 
  125.                     dialingIntent.setAction(OutgoingCallState.ForeGroundCallState.ACTIVE); 
  126.                     ctx.sendBroadcast(dialingIntent); 
  127.                      
  128.                     Log.d(TAG, ReadLog.CallState.ACTIVE); 
  129.                 } 
  130.                  
  131.                 //断开连接,即挂机 
  132.                 if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE) 
  133.                         && line.contains(ReadLog.CallState.DISCONNECTED)) { 
  134.                     //发送广播 
  135.                     Intent dialingIntent = new Intent(); 
  136.                     dialingIntent.setAction(OutgoingCallState.ForeGroundCallState.DISCONNECTED); 
  137.                     ctx.sendBroadcast(dialingIntent); 
  138.                      
  139.                     Log.d(TAG, ReadLog.CallState.DISCONNECTED); 
  140.                 } 
  141.                  
  142.             } //END while 
  143.              
  144.         } catch (IOException e) { 
  145.             e.printStackTrace(); 
  146.         } //END try-catch 
  147.     } //END run 
  148. //END class ReadLog 

发送了广播,那么就要有接受者,定义接收者如下
(关于录音机的代码可以先忽略)

  1. package com.sdvdxl.phonerecorder; 
  2.  
  3. import android.content.BroadcastReceiver; 
  4. import android.content.Context; 
  5. import android.content.Intent; 
  6. import android.util.Log; 
  7.  
  8. import com.sdvdxl.outgoingcall.OutgoingCallState; 
  9.  
  10. public class OutgoingCallReciver extends BroadcastReceiver { 
  11.     static final String TAG = "Recorder"
  12.     private MyRecorder recorder; 
  13.      
  14.     public OutgoingCallReciver() { 
  15.         recorder = new MyRecorder(); 
  16.     } 
  17.      
  18.     public  OutgoingCallReciver (MyRecorder recorder) { 
  19.         this.recorder = recorder; 
  20.     } 
  21.      
  22.     @Override 
  23.     public void onReceive(Context ctx, Intent intent) { 
  24.         String phoneState = intent.getAction(); 
  25.          
  26.         if (phoneState.equals(Intent.ACTION_NEW_OUTGOING_CALL)) { 
  27.             String phoneNum = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);//拨出号码 
  28.             recorder.setPhoneNumber(phoneNum); 
  29.             recorder.setIsCommingNumber(false); 
  30.             Log.d(TAG, "设置为去电状态"); 
  31.             Log.d(TAG, "去电状态 呼叫:" + phoneNum); 
  32.         } 
  33.          
  34.         if (phoneState.equals(OutgoingCallState.ForeGroundCallState.DIALING)) { 
  35.             Log.d(TAG, "正在拨号..."); 
  36.         } 
  37.          
  38.         if (phoneState.equals(OutgoingCallState.ForeGroundCallState.ALERTING)) { 
  39.             Log.d(TAG, "正在呼叫..."); 
  40.         } 
  41.          
  42.         if (phoneState.equals(OutgoingCallState.ForeGroundCallState.ACTIVE)) { 
  43.             if (!recorder.isCommingNumber() && !recorder.isStarted()) { 
  44.                 Log.d(TAG, "去电已接通 启动录音机"); 
  45.                 recorder.start(); 
  46.                  
  47.             } 
  48.         } 
  49.          
  50.         if (phoneState.equals(OutgoingCallState.ForeGroundCallState.DISCONNECTED)) { 
  51.             if (!recorder.isCommingNumber() && recorder.isStarted()) { 
  52.                 Log.d(TAG, "已挂断 关闭录音机"); 
  53.                 recorder.stop(); 
  54.             } 
  55.         } 
  56.     } 
  57.  

其中有这么一段代码

  1. String phoneState = intent.getAction();  
  2.           
  3.         if (phoneState.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {  
  4.             String phoneNum = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);//拨出号码  
  5.             recorder.setPhoneNumber(phoneNum);  
  6.             recorder.setIsCommingNumber(false);  
  7.             Log.d(TAG, "设置为去电状态");  
  8.             Log.d(TAG, "去电状态 呼叫:" + phoneNum);  
  9.         }  

这里是接收系统发出的广播,用于接收去电广播。这样,就获得了去电状态。

3、有了以上主要代码,可以说,来去电监听功能算是完成了,下面创建一个service来运行监听
 

  1. package com.sdvdxl.service; 
  2.  
  3. import android.app.Service; 
  4. import android.content.Context; 
  5. import android.content.Intent; 
  6. import android.content.IntentFilter; 
  7. import android.os.IBinder; 
  8. import android.telephony.PhoneStateListener; 
  9. import android.telephony.TelephonyManager; 
  10. import android.util.Log; 
  11. import android.widget.Toast; 
  12.  
  13. import com.sdvdxl.outgoingcall.OutgoingCallState; 
  14. import com.sdvdxl.phonerecorder.MyRecorder; 
  15. import com.sdvdxl.phonerecorder.OutgoingCallReciver; 
  16. import com.sdvdxl.phonerecorder.TelListener; 
  17.  
  18. public class PhoneCallStateService extends Service { 
  19.     private OutgoingCallState outgoingCallState; 
  20.     private OutgoingCallReciver outgoingCallReciver; 
  21.     private MyRecorder recorder; 
  22.      
  23.     @Override 
  24.     public void onCreate() { 
  25.         super.onCreate(); 
  26.          
  27.         //------以下应放在onStartCommand中,但2.3.5以下版本不会因service重新启动而重新调用-------- 
  28.         //监听电话状态,如果是打入且接听 或者 打出 则开始自动录音 
  29.         //通话结束,保存文件到外部存储器上 
  30.         Log.d("Recorder""正在监听中..."); 
  31.         recorder = new MyRecorder(); 
  32.         outgoingCallState = new OutgoingCallState(this); 
  33.         outgoingCallReciver = new OutgoingCallReciver(recorder); 
  34.         outgoingCallState.startListen(); 
  35.         Toast.makeText(this"服务已启动", Toast.LENGTH_LONG).show(); 
  36.          
  37.         //去电 
  38.         IntentFilter outgoingCallFilter = new IntentFilter(); 
  39.         outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.IDLE); 
  40.         outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.DIALING); 
  41.         outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.ALERTING); 
  42.         outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.ACTIVE); 
  43.         outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.DISCONNECTED); 
  44.          
  45.         outgoingCallFilter.addAction("android.intent.action.PHONE_STATE"); 
  46.         outgoingCallFilter.addAction("android.intent.action.NEW_OUTGOING_CALL"); 
  47.          
  48.         //注册接收者 
  49.         registerReceiver(outgoingCallReciver, outgoingCallFilter); 
  50.          
  51.         //来电 
  52.         TelephonyManager telmgr = (TelephonyManager)getSystemService( 
  53.                 Context.TELEPHONY_SERVICE); 
  54.         telmgr.listen(new TelListener(recorder), PhoneStateListener.LISTEN_CALL_STATE); 
  55.          
  56.          
  57.     } 
  58.      
  59.     @Override 
  60.     public IBinder onBind(Intent intent) { 
  61.         // TODO Auto-generated method stub 
  62.         return null
  63.     } 
  64.  
  65.     @Override 
  66.     public void onDestroy() { 
  67.         super.onDestroy(); 
  68.         unregisterReceiver(outgoingCallReciver); 
  69.         Toast.makeText( 
  70.                 this"已关闭电话监听服务", Toast.LENGTH_LONG) 
  71.                 .show(); 
  72.         Log.d("Recorder""已关闭电话监听服务"); 
  73.     } 
  74.  
  75.     @Override 
  76.     public int onStartCommand(Intent intent, int flags, int startId) { 
  77.          
  78.         return START_STICKY; 
  79.     } 
  80.  

注册以下service
 

  1. <service android:name="com.sdvdxl.service.PhoneCallStateService" /> 

到此为止,来去电状态的监听功能算是完成了,剩下一个录音机,附上录音机代码如下
 

  1. package com.sdvdxl.phonerecorder; 
  2.  
  3. import java.io.File; 
  4. import java.io.IOException; 
  5. import java.text.SimpleDateFormat; 
  6. import java.util.Date; 
  7.  
  8. import android.media.MediaRecorder; 
  9. import android.os.Environment; 
  10. import android.util.Log; 
  11.  
  12. public class MyRecorder { 
  13.     private String phoneNumber; 
  14.     private MediaRecorder mrecorder; 
  15.     private boolean started = false//录音机是否已经启动 
  16.     private boolean isCommingNumber = false;//是否是来电 
  17.     private String TAG = "Recorder"
  18.      
  19.      
  20.     public MyRecorder(String phoneNumber) { 
  21.         this.setPhoneNumber(phoneNumber); 
  22.     } 
  23.      
  24.     public MyRecorder() { 
  25.     } 
  26.  
  27.     public void start() { 
  28.         started = true
  29.         mrecorder = new MediaRecorder(); 
  30.          
  31.         File recordPath = new File( 
  32.                 Environment.getExternalStorageDirectory() 
  33.                 , "/My record");  
  34.         if (!recordPath.exists()) { 
  35.             recordPath.mkdirs(); 
  36.             Log.d("recorder""创建目录"); 
  37.         } 
  38.          
  39.         String callDir = "呼出"
  40.         if (isCommingNumber) { 
  41.             callDir = "呼入"
  42.         } 
  43.         String fileName = callDir + "-" + phoneNumber + "-"  
  44.                 + new SimpleDateFormat("yy-MM-dd_HH-mm-ss"
  45.                     .format(new Date(System.currentTimeMillis())) + ".mp3";//实际是3gp 
  46.         File recordName = new File(recordPath, fileName); 
  47.          
  48.         try { 
  49.             recordName.createNewFile(); 
  50.             Log.d("recorder""创建文件" + recordName.getName()); 
  51.         } catch (IOException e) { 
  52.             e.printStackTrace(); 
  53.         } 
  54.          
  55.         mrecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); 
  56.         mrecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); 
  57.         mrecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); 
  58.          
  59.         mrecorder.setOutputFile(recordName.getAbsolutePath()); 
  60.          
  61.         try { 
  62.             mrecorder.prepare(); 
  63.         } catch (IllegalStateException e) { 
  64.             e.printStackTrace(); 
  65.         } catch (IOException e) { 
  66.             e.printStackTrace(); 
  67.         } 
  68.         mrecorder.start(); 
  69.         started = true
  70.         Log.d(TAG , "录音开始"); 
  71.     } 
  72.      
  73.     public void stop() { 
  74.         try { 
  75.             if (mrecorder!=null) { 
  76.                 mrecorder.stop(); 
  77.                 mrecorder.release(); 
  78.                 mrecorder = null
  79.             } 
  80.             started = false
  81.         } catch (IllegalStateException e) { 
  82.             e.printStackTrace(); 
  83.         } 
  84.          
  85.          
  86.         Log.d(TAG , "录音结束"); 
  87.     } 
  88.      
  89.     public void pause() { 
  90.          
  91.     } 
  92.  
  93.     public String getPhoneNumber() { 
  94.         return phoneNumber; 
  95.     } 
  96.  
  97.     public void setPhoneNumber(String phoneNumber) { 
  98.         this.phoneNumber = phoneNumber; 
  99.     } 
  100.  
  101.     public boolean isStarted() { 
  102.         return started; 
  103.     } 
  104.  
  105.     public void setStarted(boolean hasStarted) { 
  106.         this.started = hasStarted; 
  107.     } 
  108.  
  109.     public boolean isCommingNumber() { 
  110.         return isCommingNumber; 
  111.     } 
  112.  
  113.     public void setIsCommingNumber(boolean isCommingNumber) { 
  114.         this.isCommingNumber = isCommingNumber; 
  115.     } 
  116.  

写到这儿,算是完成了来去电自动录音的所有功能,如有不懂,或者更好的建议欢迎评论。

另附 工程源代码 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章