最近需要做一个类似于电话客户的功能,要求拨打电话能自动录音。所以写了一个dome,希望能够帮到大家。
主要思路就是监听手机通话状态在监听到接听时开始录音,结束停止录音。
AndroidManifest中配置
<!-- 权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /> <uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.WRITE_CALL_LOG" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
当然了还要在清单文件中注册service
public abstract class CommonAdapter<T> extends BaseAdapter{ protected Context mContext; protected List<T> mList; protected int mLayoutId; public CommonAdapter(Context context, List<T> list, int layoutId) { mContext=context; mList=list; mLayoutId=layoutId; } //刷新数据 public void refresh(List<T> list){ mList=list; notifyDataSetChanged(); } @Override public int getCount() { return mList.size(); } @Override public T getItem(int position) { return mList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.getHolder(mContext, mLayoutId, convertView, parent); convertView(holder,mList.get(position)); return holder.getConvertView(); } public abstract void convertView(ViewHolder holder,T t); }
public class RBOutPhoneCallState { Context ctx; public RBOutPhoneCallState(Context ctx) { this.ctx = ctx; } /** * 前台呼叫状态 * */ 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 RBReadPhoneLog(ctx).start(); Log.d("Recorder", "开始监听呼出状态的转变,并在对应状态发送广播"); } }
public class RBPhoneListener extends PhoneStateListener { public RBRecorder recorder; @Override public void onCallStateChanged(int state, String incomingNumber) { super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: // 空闲状态,即无来电也无去电 Log.i("TelephoneState", "IDLE"); //此处添加一系列功能代码 if (recorder != null && !recorder.isCommingNumber() && recorder.isStarted()) { Log.i("TelephoneState", "STOP RECORDER"); recorder.stop(); } break; case TelephonyManager.CALL_STATE_RINGING: // 来电响铃 Log.i("TelephoneState", "RINGING"); //此处添加一系列功能代码 break; case TelephonyManager.CALL_STATE_OFFHOOK: // 摘机,即接通 Log.i("TelephoneState", "OFFHOOK"); //此处添加一系列功能代码 if (recorder == null) { recorder = new RBRecorder(); } if (!recorder.isStarted()) { Log.i("TelephoneState", "START RECORDER"); if (incomingNumber != null && incomingNumber.length() >= 8) { //CALLID recorder.setPhoneNumber(String.valueOf(incomingNumber)); } if (!recorder.isCommingNumber() && !recorder.isStarted()) { recorder.start(); } } break; } Log.i("TelephoneState", String.valueOf(incomingNumber)); } }
public class RBReadPhoneLog extends Thread { private Context ctx; private int logCount; private static final String TAG = "LogInfo OutGoing Call"; /** * 前后台电话 * */ private static class CallViewState { public static final String FORE_GROUND_CALL_STATE = "mForeground"; } /** * 呼叫状态 * */ 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 RBReadPhoneLog(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(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) && line.contains(RBReadPhoneLog.CallState.IDLE)) { Log.d(TAG, RBReadPhoneLog.CallState.IDLE); } //正在拨号,等待建立连接,即已拨号,但对方还没有响铃, if (line.contains(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) && line.contains(RBReadPhoneLog.CallState.DIALING)) { //发送广播 Intent dialingIntent = new Intent(); dialingIntent.setAction(RBOutPhoneCallState.ForeGroundCallState.DIALING); ctx.sendBroadcast(dialingIntent); Log.d(TAG, RBReadPhoneLog.CallState.DIALING); } //呼叫对方 正在响铃 if (line.contains(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) && line.contains(RBReadPhoneLog.CallState.ALERTING)) { //发送广播 Intent dialingIntent = new Intent(); dialingIntent.setAction(RBOutPhoneCallState.ForeGroundCallState.ALERTING); ctx.sendBroadcast(dialingIntent); Log.d(TAG, RBReadPhoneLog.CallState.ALERTING); } //已接通,通话建立 if (line.contains(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) && line.contains(RBReadPhoneLog.CallState.ACTIVE)) { //发送广播 Intent dialingIntent = new Intent(); dialingIntent.setAction(RBOutPhoneCallState.ForeGroundCallState.ACTIVE); ctx.sendBroadcast(dialingIntent); Log.d(TAG, RBReadPhoneLog.CallState.ACTIVE); } //断开连接,即挂机 if (line.contains(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) && line.contains(RBReadPhoneLog.CallState.DISCONNECTED)) { //发送广播 Intent dialingIntent = new Intent(); dialingIntent.setAction(RBOutPhoneCallState.ForeGroundCallState.DISCONNECTED); ctx.sendBroadcast(dialingIntent); Log.d(TAG, RBReadPhoneLog.CallState.DISCONNECTED); } } } catch (IOException e) { e.printStackTrace(); } }
public class RBRecorder { private String phoneNumber; private MediaRecorder mrecorder; private boolean started = false; // 录音机是否启动 private boolean isCommingNumber = false;// 是否是来电 private String TAG = "Recorder"; public RBRecorder(String phoneNumber) { this.setPhoneNumber(phoneNumber); } public RBRecorder() { } public void start() { started = true; mrecorder = new MediaRecorder(); String fileName = new SimpleDateFormat("yy-MM-dd_HH-mm-ss") .format(new Date(System.currentTimeMillis())) + ".mp3"; String fileSavePath = getFilePath(fileName); File recordName = new File(fileSavePath); 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(); // reset 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; } private String getFilePath(String fileName) { File sdcardDir = null; boolean sdcardExist = Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); if (sdcardExist) { sdcardDir = Environment.getExternalStorageDirectory(); } String filePath = sdcardDir.toString() + "/Recorder/Recorder"; File file = new File(filePath); if (!file.exists()) { file.mkdirs(); } return filePath + "/" + fileName; } }
大家有什么问题可以在下方留言,欢迎指出。