博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 来去电自动录音 (三)
阅读量:6418 次
发布时间:2019-06-23

本文共 11241 字,大约阅读时间需要 37 分钟。

  hot3.png

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

 

 
package com.sdvdxl.outgoingcall;    import com.sdvdxl.phonerecorder.ReadLog;    import android.content.Context;  import android.util.Log;    public class OutgoingCallState {      Context ctx;      public OutgoingCallState(Context ctx) {          this.ctx = ctx;      }            /**       * 前台呼叫状态       * @author sdvdxl       *       */      public static final class ForeGroundCallState {          public static final String DIALING =                   "com.sdvdxl.phonerecorder.FORE_GROUND_DIALING";          public static final String ALERTING =                   "com.sdvdxl.phonerecorder.FORE_GROUND_ALERTING";          public static final String ACTIVE =                   "com.sdvdxl.phonerecorder.FORE_GROUND_ACTIVE";          public static final String IDLE =                   "com.sdvdxl.phonerecorder.FORE_GROUND_IDLE";          public static final String DISCONNECTED =                   "com.sdvdxl.phonerecorder.FORE_GROUND_DISCONNECTED";      }            /**       * 开始监听呼出状态的转变,       * 并在对应状态发送广播       */      public void startListen() {          new ReadLog(ctx).start();          Log.d("Recorder", "开始监听呼出状态的转变,并在对应状态发送广播");      }        } 

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

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

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

 

 
package com.sdvdxl.phonerecorder;    import java.io.BufferedReader;  import java.io.IOException;  import java.io.InputStream;  import java.io.InputStreamReader;    import com.sdvdxl.outgoingcall.OutgoingCallState;    import android.content.Context;  import android.content.Intent;  import android.util.Log;    /**   *    * @author mrloong   *  找到 日志中的   *  onPhoneStateChanged: mForegroundCall.getState() 这个是前台呼叫状态   *  mBackgroundCall.getState() 后台电话   *  若 是 DIALING 则是正在拨号,等待建立连接,但对方还没有响铃,   *  ALERTING 呼叫成功,即对方正在响铃,   *  若是 ACTIVE 则已经接通   *  若是 DISCONNECTED 则本号码呼叫已经挂断   *  若是 IDLE 则是处于 空闲状态   *     */  public class ReadLog extends Thread {      private Context ctx;      private int logCount;            private static final String TAG = "LogInfo OutGoing Call";            /**       *  前后台电话       * @author sdvdxl       *         */      private static class CallViewState {          public static final String FORE_GROUND_CALL_STATE = "mForeground";      }            /**       * 呼叫状态       * @author sdvdxl       *       */      private static class CallState {          public static final String DIALING = "DIALING";          public static final String ALERTING = "ALERTING";          public static final String ACTIVE = "ACTIVE";          public static final String IDLE = "IDLE";          public static final String DISCONNECTED = "DISCONNECTED";      }            public ReadLog(Context ctx) {          this.ctx = ctx;      }            /**       * 读取Log流       * 取得呼出状态的log       * 从而得到转换状态       */      @Override      public void run() {          Log.d(TAG, "开始读取日志记录");                    String[] catchParams = {
"logcat", "InCallScreen *:s"};          String[] clearParams = {
"logcat", "-c"};                    try {              Process process=Runtime.getRuntime().exec(catchParams);              InputStream is = process.getInputStream();              BufferedReader reader = new BufferedReader(new InputStreamReader(is));                            String line = null;              while ((line=reader.readLine())!=null) {                  logCount++;                  //输出所有              Log.v(TAG, line);                                    //日志超过512条就清理                  if (logCount>512) {                      //清理日志                      Runtime.getRuntime().exec(clearParams)                          .destroy();//销毁进程,释放资源                      logCount = 0;                      Log.v(TAG, "-----------清理日志---------------");                  }                                       /*---------------------------------前台呼叫-----------------------*/                  //空闲                  if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE)                          && line.contains(ReadLog.CallState.IDLE)) {                      Log.d(TAG, ReadLog.CallState.IDLE);                  }                                    //正在拨号,等待建立连接,即已拨号,但对方还没有响铃,                  if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE)                          && line.contains(ReadLog.CallState.DIALING)) {                      //发送广播                      Intent dialingIntent = new Intent();                      dialingIntent.setAction(OutgoingCallState.ForeGroundCallState.DIALING);                      ctx.sendBroadcast(dialingIntent);                                            Log.d(TAG, ReadLog.CallState.DIALING);                  }                                    //呼叫对方 正在响铃                  if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE)                          && line.contains(ReadLog.CallState.ALERTING)) {                      //发送广播                      Intent dialingIntent = new Intent();                      dialingIntent.setAction(OutgoingCallState.ForeGroundCallState.ALERTING);                      ctx.sendBroadcast(dialingIntent);                                            Log.d(TAG, ReadLog.CallState.ALERTING);                  }                                    //已接通,通话建立                  if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE)                          && line.contains(ReadLog.CallState.ACTIVE)) {                      //发送广播                      Intent dialingIntent = new Intent();                      dialingIntent.setAction(OutgoingCallState.ForeGroundCallState.ACTIVE);                      ctx.sendBroadcast(dialingIntent);                                            Log.d(TAG, ReadLog.CallState.ACTIVE);                  }                                    //断开连接,即挂机                  if (line.contains(ReadLog.CallViewState.FORE_GROUND_CALL_STATE)                          && line.contains(ReadLog.CallState.DISCONNECTED)) {                      //发送广播                      Intent dialingIntent = new Intent();                      dialingIntent.setAction(OutgoingCallState.ForeGroundCallState.DISCONNECTED);                      ctx.sendBroadcast(dialingIntent);                                            Log.d(TAG, ReadLog.CallState.DISCONNECTED);                  }                                } //END while                        } catch (IOException e) {              e.printStackTrace();          } //END try-catch      } //END run  } //END class ReadLog 

发送了广播,那么就要有接受者,定义接收者如下

(关于录音机的代码可以先忽略)

 
package com.sdvdxl.phonerecorder;    import android.content.BroadcastReceiver;  import android.content.Context;  import android.content.Intent;  import android.util.Log;    import com.sdvdxl.outgoingcall.OutgoingCallState;    public class OutgoingCallReciver extends BroadcastReceiver {      static final String TAG = "Recorder";      private MyRecorder recorder;            public OutgoingCallReciver() {          recorder = new MyRecorder();      }            public  OutgoingCallReciver (MyRecorder recorder) {          this.recorder = recorder;      }            @Override      public void onReceive(Context ctx, Intent intent) {          String phoneState = intent.getAction();                    if (phoneState.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {              String phoneNum = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);//拨出号码              recorder.setPhoneNumber(phoneNum);              recorder.setIsCommingNumber(false);              Log.d(TAG, "设置为去电状态");              Log.d(TAG, "去电状态 呼叫:" + phoneNum);          }                    if (phoneState.equals(OutgoingCallState.ForeGroundCallState.DIALING)) {              Log.d(TAG, "正在拨号...");          }                    if (phoneState.equals(OutgoingCallState.ForeGroundCallState.ALERTING)) {              Log.d(TAG, "正在呼叫...");          }                    if (phoneState.equals(OutgoingCallState.ForeGroundCallState.ACTIVE)) {              if (!recorder.isCommingNumber() && !recorder.isStarted()) {                  Log.d(TAG, "去电已接通 启动录音机");                  recorder.start();                                }          }                    if (phoneState.equals(OutgoingCallState.ForeGroundCallState.DISCONNECTED)) {              if (!recorder.isCommingNumber() && recorder.isStarted()) {                  Log.d(TAG, "已挂断 关闭录音机");                  recorder.stop();              }          }      }    } 

其中有这么一段代码

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

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

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

 

 
package com.sdvdxl.service;    import android.app.Service;  import android.content.Context;  import android.content.Intent;  import android.content.IntentFilter;  import android.os.IBinder;  import android.telephony.PhoneStateListener;  import android.telephony.TelephonyManager;  import android.util.Log;  import android.widget.Toast;    import com.sdvdxl.outgoingcall.OutgoingCallState;  import com.sdvdxl.phonerecorder.MyRecorder;  import com.sdvdxl.phonerecorder.OutgoingCallReciver;  import com.sdvdxl.phonerecorder.TelListener;    public class PhoneCallStateService extends Service {      private OutgoingCallState outgoingCallState;      private OutgoingCallReciver outgoingCallReciver;      private MyRecorder recorder;            @Override      public void onCreate() {          super.onCreate();                    //------以下应放在onStartCommand中,但2.3.5以下版本不会因service重新启动而重新调用--------          //监听电话状态,如果是打入且接听 或者 打出 则开始自动录音          //通话结束,保存文件到外部存储器上          Log.d("Recorder", "正在监听中...");          recorder = new MyRecorder();          outgoingCallState = new OutgoingCallState(this);          outgoingCallReciver = new OutgoingCallReciver(recorder);          outgoingCallState.startListen();          Toast.makeText(this, "服务已启动", Toast.LENGTH_LONG).show();                    //去电          IntentFilter outgoingCallFilter = new IntentFilter();          outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.IDLE);          outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.DIALING);          outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.ALERTING);          outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.ACTIVE);          outgoingCallFilter.addAction(OutgoingCallState.ForeGroundCallState.DISCONNECTED);                    outgoingCallFilter.addAction("android.intent.action.PHONE_STATE");          outgoingCallFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");                    //注册接收者          registerReceiver(outgoingCallReciver, outgoingCallFilter);                    //来电          TelephonyManager telmgr = (TelephonyManager)getSystemService(                  Context.TELEPHONY_SERVICE);          telmgr.listen(new TelListener(recorder), PhoneStateListener.LISTEN_CALL_STATE);                          }            @Override      public IBinder onBind(Intent intent) {          // TODO Auto-generated method stub          return null;      }        @Override      public void onDestroy() {          super.onDestroy();          unregisterReceiver(outgoingCallReciver);          Toast.makeText(                  this, "已关闭电话监听服务", Toast.LENGTH_LONG)                  .show();          Log.d("Recorder", "已关闭电话监听服务");      }        @Override      public int onStartCommand(Intent intent, int flags, int startId) {                    return START_STICKY;      }    } 

注册以下service

 

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

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

 

 
package com.sdvdxl.phonerecorder;    import java.io.File;  import java.io.IOException;  import java.text.SimpleDateFormat;  import java.util.Date;    import android.media.MediaRecorder;  import android.os.Environment;  import android.util.Log;    public class MyRecorder {      private String phoneNumber;      private MediaRecorder mrecorder;      private boolean started = false; //录音机是否已经启动      private boolean isCommingNumber = false;//是否是来电      private String TAG = "Recorder";                  public MyRecorder(String phoneNumber) {          this.setPhoneNumber(phoneNumber);      }            public MyRecorder() {      }        public void start() {          started = true;          mrecorder = new MediaRecorder();                    File recordPath = new File(                  Environment.getExternalStorageDirectory()                  , "/My record");           if (!recordPath.exists()) {              recordPath.mkdirs();              Log.d("recorder", "创建目录");          }                    String callDir = "呼出";          if (isCommingNumber) {              callDir = "呼入";          }          String fileName = callDir + "-" + phoneNumber + "-"                   + new SimpleDateFormat("yy-MM-dd_HH-mm-ss")                      .format(new Date(System.currentTimeMillis())) + ".mp3";//实际是3gp          File recordName = new File(recordPath, fileName);                    try {              recordName.createNewFile();              Log.d("recorder", "创建文件" + recordName.getName());          } catch (IOException e) {              e.printStackTrace();          }                    mrecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);          mrecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);          mrecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);                    mrecorder.setOutputFile(recordName.getAbsolutePath());                    try {              mrecorder.prepare();          } catch (IllegalStateException e) {              e.printStackTrace();          } catch (IOException e) {              e.printStackTrace();          }          mrecorder.start();          started = true;          Log.d(TAG , "录音开始");      }            public void stop() {          try {              if (mrecorder!=null) {                  mrecorder.stop();                  mrecorder.release();                  mrecorder = null;              }              started = false;          } catch (IllegalStateException e) {              e.printStackTrace();          }                              Log.d(TAG , "录音结束");      }            public void pause() {                }        public String getPhoneNumber() {          return phoneNumber;      }        public void setPhoneNumber(String phoneNumber) {          this.phoneNumber = phoneNumber;      }        public boolean isStarted() {          return started;      }        public void setStarted(boolean hasStarted) {          this.started = hasStarted;      }        public boolean isCommingNumber() {          return isCommingNumber;      }        public void setIsCommingNumber(boolean isCommingNumber) {          this.isCommingNumber = isCommingNumber;      }    } 

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

另附 

本文出自 “” 博客,请务必保留此出处

转载于:https://my.oschina.net/pass/blog/777822

你可能感兴趣的文章
Sublime Text 2 配置python运行环境
查看>>
快速构建Windows 8风格应用36-商店应用发布流程
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
.Net Core IFormFile 始终为空的问题
查看>>
图片自适应
查看>>
【opengl】绘制一个立方体并在表面添加文字(添加文理)
查看>>
Distributed vSwitch分布式交换机
查看>>
用java实现短信发送的实例分享
查看>>
《构建之法》阅读笔记及项目管理软件
查看>>
VC中动态分配的几种写法
查看>>
excel数据比对,查找差异
查看>>
python3 简单登录,注册测试代码
查看>>
MAC VMWare Fusion配置mac和win7虚拟机互相访问
查看>>
awk正则匹配和awk命令统计某程序的CPU总的利用率
查看>>
CentOS7安装grafana
查看>>
bzoj 1823: [JSOI2010]满汉全席
查看>>
实战部署openldap主从架构
查看>>
我的技术路还很长
查看>>
第二阶段团队进展报告(4)
查看>>