Android监听来去电通话录音真正可实行方案,可获取电话接通时状态

最近 经过一段时间研究了Android来去电并且录音的研究,特此作为记录

首先监听来去电并且可以录音得有以下权限:

//录音权限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
<!-- 要存储文件或者创建文件夹的话还需要以下两个权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
//读取系统日志
<uses-permission android:name="android.permission.READ_LOGS" />

前置条件,如果有录制双向声音的需求,必须手机获取root权限,且应用作为系统应用才可,因为CAPTURE_AUDIO_OUTPUT,READ_LOGS必须是系统级应用才可以。网上很多方案说配置文件加sharedid什么的然后用系统签名apk文件,各位看官这都是扯蛋。实现难度太大,去哪整每个系统的签名?如果已经获取了root权限 完全可以代码内判断/system/priv-app文件夹下是否存在自己应用文件夹是否存在,不存在移动整个文件夹到/system/priv-app,然后代码执行重启手机命令后您的应用就是系统级应用了。此处就不进行代码叙述,重点讲述来去电监听。

流程:首先建立service开启监听来去电服务,用TelephonyManager提供的PhoneStateListener监听来电接通状态跟电话挂断状态。用广播监听去电开始(未接通)的状态。当开始去电时,开启线程读取系统日志,当获取到去电接通的日志(不同机型日志不同)时返回去电接通状态。以上是我来去电状态获取的流程。在来去电接通时开启录音,电话挂断监听处停止录音即可。

一、建立service开启监听

private TelephonyManager mTelephonyManager;
private CallListener mCallListener = new CallListener(new CallListener.OnIncomingListener() {
    @Override
    public void incomingOn(String number) {
        //来电接通,开启录音
       startRecord(number)
    }
}, new TelListener.OnCallOffStateListener() {
    @Override
    public void off() {
        //电话挂断,不分来去电,停止录音
       stopRecord()
    }
});

@Override
public void onCreate() {
    super.onCreate();
    mTelephonyManager = (TelephonyManager) this.getSystemService(
            Context.TELEPHONY_SERVICE);
    mTelephonyManager.listen(mCallListener, PhoneStateListener.LISTEN_CALL_STATE);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if ("outgoingAction".equals(intent.getAction())) {
        String number = intent.getStringExtra("outgoingNumber");
//开启读取日志,获取去电状态
        if (mOutGoingLogThread == null) {
            mOutGoingLogThread = new OutGoingLogThread(CallService.this, new OutGoingLogThread.OutGoingListener() {
                @Override
                public void outGoingOn() {
//去电接通了 开启录音
                    startRecord(number)
                }
            });
        }
        mOutGoingLogThread.start();
    }
    return START_REDELIVER_INTENT;
}

二、来电监听:

public class CallListener extends PhoneStateListener {
//上个电话状态,当上个状态为响铃,当前状态为OFFHOOK时即为来电接通
    private int mLastState = TelephonyManager.CALL_STATE_IDLE;
    private OnIncomingListener mOnIncomingListener;
    private OnCallOffListener mOnCallOffListener;
//来电号码
    private String mIncomingNumber;

    public TelListener(OnIncomingListener listener, OnCallOffListener callOffistener) {
        this.mOnIncomingListener = listener;
        this.mOnCallOffListener = callOffListener;
    }


    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch (state) {
            case TelephonyManager.CALL_STATE_IDLE: // 空闲状态,即无来电也无去电
                if (mLastState == TelephonyManager.CALL_STATE_OFFHOOK&&mOnCallOffListener!=null) {
                    mOnCallOffListener.off();
                }
                break;
            case TelephonyManager.CALL_STATE_RINGING: // 来电响铃
                mIncomingNumber = String.valueOf(incomingNumber);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK: // 摘机,即接通
                //此处添加一系列功能代码
                if (mLastState == TelephonyManager.CALL_STATE_RINGING && mOnIncomingListener != null) {
                    mOnIncomingListener.incomingOn(mIncomingNumber);
                }
                break;
        }
        mLastState = state;
        super.onCallStateChanged(state, incomingNumber);
    }
//来电接通 public interface OnIncomingListener { void incomingOn(String number); } //电话挂断监听,不分来去电 public interface OnCallOffListener { void Off(); }
}  

三、去电监听:

开启广播:

public class OutGoingReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //只获取去电广播
        if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
            String number = intent.getExtras().getString(Intent.EXTRA_PHONE_NUMBER);
            Intent intent1 = new Intent();
            intent1.putExtra("outgoingNumber", number);
            intent1.setAction("outgoingAction");
            intent1.setClass(context, CallService.class);
            context.startService(intent1);
        }
    }
}

去电日志获取线程:

 //系统通话信息的TAG,不同机型TAG不同,自己获取

    public final static String LOG_TAG="your phone system phone call tag";

//日志里接通的信息,不同机型信息不同,自己研究获取

    public final static String OUTGOING_ON="call_state = 5";



@Override
public void run() {
mIsRunning = true;
Process process = null;
BufferedReader bufferReader=null;
try {
//此处尤为注意!!!读取日志前如果不清理日志,会获取缓存区域的日志,导致不是最新实时日志,影响本次判断
//网上很多清理日志时没调用waitFor(),经测试根本无法及时清理日志,所以必须调用
Runtime.getRuntime().exec("logcat -c").waitFor();
//获取系统指定TAG日志
String cmd = "logcat -b system -s "+LOG_TAG;
process = Runtime.getRuntime().exec(cmd);
bufferReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while (mIsRunning && (line = bufferReader.readLine()) != null) {
if (line.contains(OUTGOING_ON)) {
if (mOutGoingListener != null) {
mOutGoingListener.outGoingOn();
}
mIsRunning = false;
Log.d(TAG, "去电接通");
}
}
} catch (IOException e) {
} catch (InterruptedException e) {
} finally {
try {
if (bufferReader != null) {
bufferReader.close();
}
if (process != null) {
process.destroy();
}
} catch (IOException e) {
}

}
}

四:总结

以上就是本次来去电状态获取的部分代码,其中注释部分尤为注意,就是我掉进去的坑。其中没叙述录音的实现,网上借助mediarecoder很多录音方法,此处不在叙述

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值