最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android實(shí)現(xiàn)通話自動(dòng)錄音

 更新時(shí)間:2020年10月23日 09:07:36   作者:程思陽(yáng)  
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)通話自動(dòng)錄音,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

最近需要做一個(gè)類(lèi)似于電話客戶(hù)的功能,要求撥打電話能自動(dòng)錄音。所以寫(xiě)了一個(gè)dome,希望能夠幫到大家。

主要思路就是監(jiān)聽(tīng)手機(jī)通話狀態(tài)在監(jiān)聽(tīng)到接聽(tīng)時(shí)開(kāi)始錄音,結(jié)束停止錄音。

AndroidManifest中配置

<!-- 權(quán)限 -->
<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" />

當(dāng)然了還要在清單文件中注冊(cè)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;
 }

 //刷新數(shù)據(jù)
 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; 
 } 
  
 /** 
  * 前臺(tái)呼叫狀態(tài) 
  * 
  */ 
 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"; 
 } 
  
 /** 
  * 開(kāi)始監(jiān)聽(tīng)呼出狀態(tài)的轉(zhuǎn)變, 
  * 并在對(duì)應(yīng)狀態(tài)發(fā)送廣播 
  */ 
 public void startListen() { 
  new RBReadPhoneLog(ctx).start(); 
  Log.d("Recorder", "開(kāi)始監(jiān)聽(tīng)呼出狀態(tài)的轉(zhuǎn)變,并在對(duì)應(yīng)狀態(tài)發(fā)送廣播"); 
 } 
  
} 
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: // 空閑狀態(tài),即無(wú)來(lái)電也無(wú)去電  
   Log.i("TelephoneState", "IDLE"); 
   
   //此處添加一系列功能代碼 
   if (recorder != null && !recorder.isCommingNumber() && recorder.isStarted()) {
    
    Log.i("TelephoneState", "STOP RECORDER"); 
    recorder.stop();
   }
   
   break;  
  case TelephonyManager.CALL_STATE_RINGING: // 來(lái)電響鈴  
   Log.i("TelephoneState", "RINGING");  
   //此處添加一系列功能代碼 
   break;  
  case TelephonyManager.CALL_STATE_OFFHOOK: // 摘機(jī),即接通 
   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"; 
  
 /** 
  * 前后臺(tái)電話 
  *  
  */ 
 private static class CallViewState { 
  public static final String FORE_GROUND_CALL_STATE = "mForeground"; 
 } 
  
 /** 
  * 呼叫狀態(tài)  
  * 
  */ 
 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流 
  * 取得呼出狀態(tài)的log 
  * 從而得到轉(zhuǎn)換狀態(tài) 
  */ 
 @Override 
 public void run() { 
  Log.d(TAG, "開(kāi)始讀取日志記錄"); 
   
  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); 
     
    //日志超過(guò)512條就清理 
    if (logCount>512) { 
     //清理日志 
     Runtime.getRuntime().exec(clearParams) 
      .destroy();//銷(xiāo)毀進(jìn)程,釋放資源 
     logCount = 0; 
     Log.v(TAG, "-----------清理日志---------------"); 
    }  
     
    /*---------------------------------前臺(tái)呼叫-----------------------*/ 
    //空閑 
    if (line.contains(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) 
      && line.contains(RBReadPhoneLog.CallState.IDLE)) { 
     Log.d(TAG, RBReadPhoneLog.CallState.IDLE); 
    } 
     
    //正在撥號(hào),等待建立連接,即已撥號(hào),但對(duì)方還沒(méi)有響鈴, 
    if (line.contains(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) 
      && line.contains(RBReadPhoneLog.CallState.DIALING)) { 
     //發(fā)送廣播 
     Intent dialingIntent = new Intent(); 
     dialingIntent.setAction(RBOutPhoneCallState.ForeGroundCallState.DIALING); 
     ctx.sendBroadcast(dialingIntent); 
      
     Log.d(TAG, RBReadPhoneLog.CallState.DIALING); 
    } 
     
    //呼叫對(duì)方 正在響鈴 
    if (line.contains(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) 
      && line.contains(RBReadPhoneLog.CallState.ALERTING)) { 
     //發(fā)送廣播 
     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)) { 
     //發(fā)送廣播 
     Intent dialingIntent = new Intent(); 
     dialingIntent.setAction(RBOutPhoneCallState.ForeGroundCallState.ACTIVE); 
     ctx.sendBroadcast(dialingIntent); 
      
     Log.d(TAG, RBReadPhoneLog.CallState.ACTIVE); 
    } 
     
    //斷開(kāi)連接,即掛機(jī) 
    if (line.contains(RBReadPhoneLog.CallViewState.FORE_GROUND_CALL_STATE) 
      && line.contains(RBReadPhoneLog.CallState.DISCONNECTED)) { 
     //發(fā)送廣播 
     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; // 錄音機(jī)是否啟動(dòng)
 private boolean isCommingNumber = false;// 是否是來(lái)電
 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", "創(chuàng)建文件" + 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, "錄音開(kāi)始");
 }

 public void stop() {
  try {
   if (mrecorder != null) {
    mrecorder.stop();
    // reset
    mrecorder.release();
    mrecorder = null;
   }
   started = false;
  } catch (IllegalStateException e) {
   e.printStackTrace();
  }

  Log.d(TAG, "錄音結(jié)束");
 }

 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;
 }

}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android :okhttp+Springmvc文件解析器實(shí)現(xiàn)android向服務(wù)器上傳照片

    Android :okhttp+Springmvc文件解析器實(shí)現(xiàn)android向服務(wù)器上傳照片

    這篇文章主要介紹了Android :okhttp+Springmvc文件解析器實(shí)現(xiàn)android向服務(wù)器上傳照片,需要的朋友可以參考下
    2020-05-05
  • Android中毛玻璃效果的兩種實(shí)現(xiàn)代碼

    Android中毛玻璃效果的兩種實(shí)現(xiàn)代碼

    這篇文章主要介紹了Android中毛玻璃效果的兩種實(shí)現(xiàn)代碼,第一種是使用JAVA算法FastBlur實(shí)現(xiàn),第二種是使用Android自帶類(lèi)RenderScript 實(shí)現(xiàn),本文通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友參考下吧
    2024-08-08
  • Android入門(mén)之Toast的使用教程

    Android入門(mén)之Toast的使用教程

    Toast是一種很方便的消息提示框,會(huì)在 屏幕中顯示一個(gè)消息提示框,沒(méi)任何按鈕,也不會(huì)獲得焦點(diǎn)一段時(shí)間過(guò)后自動(dòng)消失!非常常用!本文就來(lái)通過(guò)一個(gè)例子把Toast的使用講透
    2022-11-11
  • Android DrawerLayout布局與NavigationView導(dǎo)航菜單應(yīng)用

    Android DrawerLayout布局與NavigationView導(dǎo)航菜單應(yīng)用

    這篇文章主要介紹了Android DrawerLayout抽屜布局與NavigationView導(dǎo)航菜單應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-01-01
  • Android drawable微技巧,你不知道的drawable細(xì)節(jié)

    Android drawable微技巧,你不知道的drawable細(xì)節(jié)

    今天小編就為大家分享一篇關(guān)于Android drawable微技巧,你不知道的drawable細(xì)節(jié),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • android實(shí)現(xiàn)狀態(tài)欄添加圖標(biāo)的函數(shù)實(shí)例

    android實(shí)現(xiàn)狀態(tài)欄添加圖標(biāo)的函數(shù)實(shí)例

    這篇文章主要介紹了android實(shí)現(xiàn)狀態(tài)欄添加圖標(biāo)的函數(shù),較為詳細(xì)的分析了Android狀態(tài)欄添加及刪除圖標(biāo)的具體實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • Android開(kāi)發(fā)重寫(xiě)Animation實(shí)現(xiàn)下拉圖片后彈射回去效果示例

    Android開(kāi)發(fā)重寫(xiě)Animation實(shí)現(xiàn)下拉圖片后彈射回去效果示例

    這篇文章主要介紹了Android開(kāi)發(fā)重寫(xiě)Animation實(shí)現(xiàn)下拉圖片后彈射回去效果,結(jié)合實(shí)例形式分析了Android自定義類(lèi)繼承Animation實(shí)現(xiàn)圖片彈射效果的相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • Android實(shí)現(xiàn)不同apk間共享數(shù)據(jù)的方法(2種方法)

    Android實(shí)現(xiàn)不同apk間共享數(shù)據(jù)的方法(2種方法)

    這篇文章主要介紹了Android實(shí)現(xiàn)不同apk間共享數(shù)據(jù)的方法,介紹了apk自定義借口實(shí)現(xiàn)數(shù)據(jù)共享與基于User id的數(shù)據(jù)共享,并重點(diǎn)介紹了基于User id的數(shù)據(jù)共享實(shí)現(xiàn)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下
    2016-01-01
  • Flutter 包管理器和資源管理使用學(xué)習(xí)

    Flutter 包管理器和資源管理使用學(xué)習(xí)

    這篇文章主要為大家介紹了Flutter 包管理器和資源管理使用學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Android中對(duì)RecyclerView Adapter封裝解析

    Android中對(duì)RecyclerView Adapter封裝解析

    本篇文章主要介紹了Android中對(duì)RecyclerView Adapter封裝解析。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06

最新評(píng)論

抚顺市| 东乡| 全椒县| 凤山市| 奉化市| 石楼县| 正宁县| 莆田市| 明光市| 阿克| 武平县| 左云县| 韶关市| 兰考县| 新民市| 长岛县| 永修县| 阜平县| 察雅县| 中卫市| 新余市| 化州市| 台南市| 广东省| 常熟市| 科尔| 安图县| 常宁市| 乌什县| 威宁| 治县。| 民丰县| 连山| 海阳市| 特克斯县| 云梦县| 叶城县| 永安市| 越西县| 余庆县| 蒲江县|