Android實現通話自動錄音
阿新 • • 發佈:2020-10-23
最近需要做一個類似於電話客戶的功能,要求撥打電話能自動錄音。所以寫了一個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; } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。