android实现通话自动录音服务

本文实例为大家分享了android实现通话自动录音服务的具体代码,供大家参考,具体内容如下

需求:

①:通话自动录音;
②:无界面,只是一个service;
③:录音自动压缩上传;
④:当用户清理后台的时候,要求service不可以被杀死;
⑤:稳定性:1、无网络的情况下;2、上传失败;3、服务报错。

解决方案:

①:通话自动录音

启动一个service,监听用户手机通话状态,当检测到用户处于通话状态下,立即开始录音,通话结束后,停止录音,并保存文件。
此功能的前提条件:
1、录音权限、读写存储空间的权限、读取通话状态的权限;
2、Service不可以被停止,否则无法录音。
3、开机启动(不可以让用户每次开机都主动去打开服务)

②:无界面,只是一个service

方案①
普通的service,监听开机广播,当用户开机的时候,启动service。但是,发现service并没有启动。想要启动一个service,必须要有一个activity,即使你不打开这个activity。
在真正做项目的时候,PM会提出各种你不能理解的需求,比如说本系统,PM要求本应用只是一个录音服务,不可以有任何界面,也不可以在手机桌面上出现应用图标。因此,方案①不可行。
方案②
Android手机在设置里面都一个辅助功能(个别手机也叫:无障碍),利用这个我们可以实现一些强大的功能,前提是用户开启我们的辅助功能,抢红包软件就是利用辅助功能实现的。

③:录音自动压缩上传

我们只需要在上传之前对文件进行压缩处理,然后再上传即可。

④:当用户清理后台的时候,要求service不可以被杀死

不会被杀死的服务,或许只有系统服务吧。当然类似于QQ、微信他们做的这种全家桶也可以做到。大公司是可以和厂商合作的,他们的应用可以不那么容易被杀死。当然也不提倡这样做,这样就是垃圾软件,破坏了Android开发的美好环境。
其实,如果可以把服务设置成系统服务,那么只要用户不主动在辅助功能页面关掉服务,后台是清理不掉改服务的。本人在小米手机上测试过,设置成系统级别的服务后,当清理后台的时候,即使服务被杀死,也会非常快的重新启动。(感兴趣的同学可以试一下)

⑤:稳定性:1、无网络的情况下;2、上传失败;3、服务报错

思路:

当无网络的情况下,把录音文件的地址保存下来(保存的方式有很多:Sqlite、Sharedpreferences等等),上传失败也一样,失败的原因可能有很多种:网络断开、接口报错等,当网络恢复的时候,可以重新上传,这样就不会丢失录音文件。
代码很简单,注释很详细:

项目的结构:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 要存储文件或者创建文件夹的话还需要以下两个权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<!--允许读取网络状态-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--允许读取wifi网络状态-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<service
 android:name=".service.RecorderService"
 android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
 <intent-filter>
  <action android:name="android.accessibilityservice.AccessibilityService" />
 </intent-filter>
 <meta-data
  android:name="android.accessibilityservice"
  android:resource="@xml/accessible_service_config" />
</service>
/**
 * 电话自动录音辅助服务(去电、来电自动录音并上传)。
 * Created by wang.ao in 2017/2/24.
 */

public class RecorderService extends AccessibilityService {
 private static final String TAG = "RecorderService";
 private static final String TAG1 = "手机通话状态";
 /**
  * 音频录制
  */
 private MediaRecorder recorder;
 private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 /**
  * 监听拨号广播,以便获取用户拨出的电话号码
  */
 private OutCallReceiver outCallReceiver;
 private IntentFilter intentFilter;
 /**
  * 网络状态改变广播,当网络畅通的状态下,把用户未上传的录音文件都上传掉
  */
 private NetworkConnectChangedReceiver networkConnectChangedReceiver;
 private IntentFilter intentFilter2;
 /**
  * 当前通话对象的电话号码
  */
 private String currentCallNum = "";
 /**
  * 区分来电和去电
  */
 private int previousStats = 0;
 /**
  * 当前正在录制的文件
  */
 private String currentFile = "";
 /**
  * 保存未上传的录音文件
  */
 private SharedPreferences unUploadFile;
 private String dirPath = "";
 private boolean isRecording = false;

 @Override
 protected void onServiceConnected() {
  Log.i(TAG, "onServiceConnected");
  Toast.makeText(getApplicationContext(), "自动录音服务已启动", Toast.LENGTH_LONG).show();
 }

 @Override
 public void onAccessibilityEvent(AccessibilityEvent event) {
  // TODO Auto-generated method stub
  Log.i(TAG, "eventType " + event.getEventType());
 }

 @Override
 public void onInterrupt() {
  // TODO Auto-generated method stub
  Log.i(TAG, "onServiceConnected");
 }

 @Override
 public boolean onUnbind(Intent intent) {
  return super.onUnbind(intent);
 }

 @Override
 public void onCreate() {
  super.onCreate();
  TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
  // 监听电话状态
  tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
  outCallReceiver = new OutCallReceiver();
  intentFilter = new IntentFilter();
  //设置拨号广播过滤
  intentFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
  registerReceiver(outCallReceiver, intentFilter);
  //注册拨号广播接收器
  networkConnectChangedReceiver = new NetworkConnectChangedReceiver();
  intentFilter2 = new IntentFilter();
  //设置网络状态改变广播过滤
  intentFilter2.addAction("android.net.conn.CONNECTIVITY_CHANGE");
  intentFilter2.addAction("android.net.wifi.WIFI_STATE_CHANGED");
  intentFilter2.addAction("android.net.wifi.STATE_CHANGE");
  //注册网络状态改变广播接收器
  registerReceiver(networkConnectChangedReceiver, intentFilter2);
  unUploadFile = getSharedPreferences("un_upload_file", 0);
  unUploadFile.edit().putString("description", "未上传的录音文件存放路径").commit();
  dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/com.ct.phonerecorder/";
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  Toast.makeText(getApplicationContext(), "进程被关闭,无法继续录音,请打开录音服务", Toast.LENGTH_LONG).show();
  if (outCallReceiver != null) {
   unregisterReceiver(outCallReceiver);
  }
  if (networkConnectChangedReceiver != null) {
   unregisterReceiver(networkConnectChangedReceiver);
  }
 }

 class MyListener extends PhoneStateListener {
  @Override
  public void onCallStateChanged(int state, String incomingNumber) {
   // TODO Auto-generated method stub
   Log.d(TAG1, "空闲状态" + incomingNumber);
   switch (state) {
    case TelephonyManager.CALL_STATE_IDLE:
     Log.d(TAG1, "空闲");
     if (recorder != null && isRecording) {
      recorder.stop();// 停止录音
      recorder.release();
      recorder = null;
      Log.d("电话", "通话结束,停止录音");
      uploadFile(currentFile);
     }
     isRecording = false;
     break;
    case TelephonyManager.CALL_STATE_RINGING:
     Log.d(TAG1, "来电响铃" + incomingNumber);
     // 进行初始化

     break;
    case TelephonyManager.CALL_STATE_OFFHOOK:
     Log.d(TAG1, "摘机" + (!incomingNumber.equals("") ? incomingNumber : currentCallNum));
     initRecord(!incomingNumber.equals("") ? incomingNumber : currentCallNum);
     // 开始录音
     if (recorder != null) {
      recorder.start();
      isRecording = true;
     }
    default:
     break;
   }
   super.onCallStateChanged(state, incomingNumber);
  }

 }

 /**
  * 当录音结束后,自动上传录音文件。
  * ①网络可用:直接上传;
  * ②网络不可用:保存文件路径,待网络可用的时候再进行上传;
  * ③上传失败的文件,也保存文件路径,或者重新上传。
  */
 public void uploadFile(String file) {
  ZipUtils.zipFile(dirPath + file, dirPath + file + ".zip");
  if (NetWorkUtils.isNetworkConnected(getApplicationContext())) {
   //上传文件
//   OkHttpUtils.postFile()
  } else {
   saveUnUploadFIles(dirPath + file + ".zip");
  }
 }

 /**
  * 保存未上传的录音文件
  *
  * @param file 未上传的录音文件路径
  */
 private void saveUnUploadFIles(String file) {
  String files = unUploadFile.getString("unUploadFile", "");
  if (files.equals("")) {
   files = file;
  } else {
   StringBuilder sb = new StringBuilder(files);
   files = sb.append(";").append(file).toString();
  }
  unUploadFile.edit().putString("unUploadFile", files).commit();
 }

 /**
  * 上传因为网络或者其他原因,暂未上传或者上传失败的文件,重新上传
  */
 public void uploadUnUploadedFiles() {
  //获取当前还未上传的文件,并把这些文件上传
  String files = unUploadFile.getString("unUploadFile", "");
  unUploadFile.edit().putString("unUploadFile", "").commit();
  if (files.equals("")) {
   return;
  }
  String[] fileArry = files.split(";");
  int len = fileArry.length;
  for (String file : fileArry) {
   upload(file);
  }
 }

 /**
  * 文件上传
  *
  * @param file 要上传的文件
  */
 public void upload(final String file) {
  File file1 = new File(file);
  if (file1 == null || !file1.exists()) {
   //文件不存在
   return;
  }
  if (!NetWorkUtils.isNetworkConnected(getApplicationContext())) {
   saveUnUploadFIles(file);
   return;
  }
  Map<String, String> map = new HashMap<String, String>();
  map.put("type", "1");
  final String url = "http://192.168.1.158:8082/uploader";
  OkHttpUtils.post()//
    .addFile("mFile", file1.getName(), file1)//
    .url(url)//
    .params(map).build()//
    .execute(new StringCallback() {

     @Override
     public void onResponse(String response, int id) {
      Log.e(TAG, "成功 response=" + response);
     }

     @Override
     public void onError(Call call, Exception e, int id) {
      Log.e(TAG, "失败 response=" + e.toString());
      saveUnUploadFIles(file);
     }
    });
 }

 /**
  * 初始化录音机,并给录音文件重命名
  *
  * @param incomingNumber 通话号码
  */
 private void initRecord(String incomingNumber) {
  previousStats = TelephonyManager.CALL_STATE_RINGING;
  recorder = new MediaRecorder();
  recorder.setAudioSource(MediaRecorder.AudioSource.MIC);// Microphone
  recorder.setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);// 设置输出3gp格式
  File out = new File(dirPath);
  if (!out.exists()) {
   out.mkdirs();
  }
  recorder.setOutputFile(dirPath
    + getFileName((previousStats == TelephonyManager.CALL_STATE_RINGING ? incomingNumber : currentCallNum))
  );
  recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 设置音频编码格式
  try {
   recorder.prepare();// 做好准备
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

 /**
  * 获取录音文件的名称
  *
  * @param incomingNumber 通话号码
  * @return 获取录音文件的名称
  */
 private String getFileName(String incomingNumber) {
  Date date = new Date(System.currentTimeMillis());
  currentFile = incomingNumber + " " + dateFormat.format(date) + ".mp3";
  return currentFile;
 }

 /**
  * 拨号广播接收器,并获取拨号号码
  */
 public class OutCallReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
   Log.d(TAG1, "当前手机拨打了电话:" + currentCallNum);
   if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
    currentCallNum = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
    Log.d(TAG1, "当前手机拨打了电话:" + currentCallNum);
   } else {
    Log.d(TAG1, "有电话,快接听电话");
   }
  }
 }

 /**
  * 网络状态change广播接收器
  */
 public class NetworkConnectChangedReceiver extends BroadcastReceiver {
  private static final String TAG = "network status";

  @Override
  public void onReceive(Context context, Intent intent) {
   /**
    * 这个监听网络连接的设置,包括wifi和移动数据的打开和关闭。.
    * 最好用的还是这个监听。wifi如果打开,关闭,以及连接上可用的连接都会接到监听。见log
    * 这个广播的最大弊端是比上边两个广播的反应要慢,如果只是要监听wifi,我觉得还是用上边两个配合比较合适
    */
   if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
    ConnectivityManager manager = (ConnectivityManager) context
      .getSystemService(Context.CONNECTIVITY_SERVICE);
    Log.i(TAG, "CONNECTIVITY_ACTION");

    NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
    if (activeNetwork != null) { // connected to the internet
     if (activeNetwork.isConnected()) {
      //当前网络可用
      if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
       // connected to wifi
       Log.e(TAG, "当前WiFi连接可用 ");
      } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
       // connected to the mobile provider's data plan
       Log.e(TAG, "当前移动网络连接可用 ");
      }
      uploadUnUploadedFiles();
     } else {
      Log.e(TAG, "当前没有网络连接,请确保你已经打开网络 ");
     }

    } else { // not connected to the internet
     Log.e(TAG, "当前没有网络连接,请确保你已经打开网络 ");
    }

   }
  }
 }

}
/**
 * 获取网络连接状态工具类
 * Created by wang.ao in 2017/2/24.
 */

public class NetWorkUtils {
 /**
  * 判断是否有网络连接
  * @param context
  * @return
  */
 public static boolean isNetworkConnected(Context context) {
  if (context != null) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
     .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
   if (mNetworkInfo != null) {
    return mNetworkInfo.isAvailable();
   }
  }
  return false;
 }

 /**
  * 判断WIFI网络是否可用
  * @param context
  * @return
  */
 public static boolean isWifiConnected(Context context) {
  if (context != null) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
     .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo mWiFiNetworkInfo = mConnectivityManager
     .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
   if (mWiFiNetworkInfo != null) {
    return mWiFiNetworkInfo.isAvailable();
   }
  }
  return false;
 }

 /**
  * 判断MOBILE网络是否可用
  * @param context
  * @return
  */
 public static boolean isMobileConnected(Context context) {
  if (context != null) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
     .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo mMobileNetworkInfo = mConnectivityManager
     .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
   if (mMobileNetworkInfo != null) {
    return mMobileNetworkInfo.isAvailable();
   }
  }
  return false;
 }

 /**
  * 获取当前网络连接的类型信息
  * @param context
  * @return
  */
 public static int getConnectedType(Context context) {
  if (context != null) {
   ConnectivityManager mConnectivityManager = (ConnectivityManager) context
     .getSystemService(Context.CONNECTIVITY_SERVICE);
   NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
   if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
    return mNetworkInfo.getType();
   }
  }
  return -1;
 }

 /**
  * 获取当前的网络状态 :没有网络0:WIFI网络1:3G网络2:2G网络3
  *
  * @param context
  * @return
  */
 public static int getAPNType(Context context) {
  int netType = 0;
  ConnectivityManager connMgr = (ConnectivityManager) context
    .getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
  if (networkInfo == null) {
   return netType;
  }
  int nType = networkInfo.getType();
  if (nType == ConnectivityManager.TYPE_WIFI) {
   netType = 1;// wifi
  } else if (nType == ConnectivityManager.TYPE_MOBILE) {
   int nSubType = networkInfo.getSubtype();
   TelephonyManager mTelephony = (TelephonyManager) context
     .getSystemService(Context.TELEPHONY_SERVICE);
   if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
     && !mTelephony.isNetworkRoaming()) {
    netType = 2;// 3G
   } else {
    netType = 3;// 2G
   }
  }
  return netType;
 }
}
public class ZipUtils {
 private static final int BUFF_SIZE = 1024;

 /**
  * @param zos   压缩流
  * @param parentDirName 父目录
  * @param file   待压缩文件
  * @param buffer  缓冲区
  *
  * @return 只要目录中有一个文件压缩失败,就停止并返回
  */
 private static boolean zipFile(ZipOutputStream zos, String parentDirName, File file, byte[] buffer) {
  String zipFilePath = parentDirName + file.getName();
  if (file.isDirectory()) {
   zipFilePath += File.separator;
   for (File f : file.listFiles()) {
    if (!zipFile(zos, zipFilePath, f, buffer)) {
     return false;
    }
   }
   return true;
  } else {
   try {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    ZipEntry zipEntry = new ZipEntry(zipFilePath);
    zipEntry.setSize(file.length());
    zos.putNextEntry(zipEntry);
    while (bis.read(buffer) != -1) {
     zos.write(buffer);
    }
    bis.close();
    return true;
   } catch (FileNotFoundException ex) {
    ex.printStackTrace();
   } catch (IOException ex) {
    ex.printStackTrace();
   }
   return false;
  }
 }

 /**
  * @param srcPath 待压缩的文件或目录
  * @param dstPath 压缩后的zip文件
  * @return 只要待压缩的文件有一个压缩失败就停止压缩并返回(等价于windows上直接进行压缩)
  */
 public static boolean zipFile(String srcPath, String dstPath) {
  File srcFile = new File(srcPath);
  if (!srcFile.exists()) {
   return false;
  }
  byte[] buffer = new byte[BUFF_SIZE];
  try {
   ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dstPath));
   boolean result = zipFile(zos, "", srcFile, buffer);
   zos.close();
   return result;
  } catch (FileNotFoundException ex) {
   ex.printStackTrace();
  } catch (IOException ex) {
   ex.printStackTrace();
  }
  return false;
 }

 /**
  * @param srcPath 待解压的zip文件
  * @param dstPath zip解压后待存放的目录
  * @return 只要解压过程中发生错误,就立即停止并返回(等价于windows上直接进行解压)
  */
 public static boolean unzipFile(String srcPath, String dstPath) {
  if (TextUtils.isEmpty(srcPath) || TextUtils.isEmpty(dstPath)) {
   return false;
  }
  File srcFile = new File(srcPath);
  if (!srcFile.exists() || !srcFile.getName().toLowerCase(Locale.getDefault()).endsWith("zip")) {
   return false;
  }
  File dstFile = new File(dstPath);
  if (!dstFile.exists() || !dstFile.isDirectory()) {
   dstFile.mkdirs();
  }
  try {
   ZipInputStream zis = new ZipInputStream(new FileInputStream(srcFile));
   BufferedInputStream bis = new BufferedInputStream(zis);
   ZipEntry zipEntry = null;
   byte[] buffer = new byte[BUFF_SIZE];
   if (!dstPath.endsWith(File.separator)) {
    dstPath += File.separator;
   }
   while ((zipEntry = zis.getNextEntry()) != null) {
    String fileName = dstPath + zipEntry.getName();
    File file = new File(fileName);
    File parentDir = file.getParentFile();
    if (!parentDir.exists()) {
     parentDir.mkdirs();
    }
    FileOutputStream fos = new FileOutputStream(file);
    while (bis.read(buffer) != -1) {
     fos.write(buffer);
    }
    fos.close();
   }
   bis.close();
   zis.close();
   return true;
  } catch (FileNotFoundException ex) {
   ex.printStackTrace();
  } catch (IOException ex) {
   ex.printStackTrace();
  }
  return false;
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android App调用MediaRecorder实现录音功能的实例

    MediaRecorder Android的MediaRecorder包含了Audio和video的记录功能,在Android的界面上,Music和Video两个应用程序都是调用MediaRecorder实现的. MediaRecorder在底层是基于OpenCore(PacketVideo)的库实现的,为了构建一个MediaRecorder程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制. 以开源的Android为例MediaRecorder的

  • Android实现录音功能实现实例(MediaRecorder)

    本文介绍了Android实现录音的实例代码(MediaRecorder),分享给大家,具体如下: Android提供了两个API用于录音的实现:MediaRecorder 和 AudioRecord,各有优劣. 1.MediaRecorder 已经集成了录音.编码.压缩等,支持少量的录音音频格式,大概有.aac(API = 16) .amr .3gp 优点:大部分已经集成,直接调用相关接口即可,代码量小 缺点:无法实时处理音频:输出的音频格式不是很多,例如没有输出mp3格式文件 2.AudioR

  • Android简单的利用MediaRecorder进行录音的实例代码

    复制代码 代码如下: package com.ppmeet; import java.io.IOException; import android.app.Activity;  import android.graphics.PixelFormat;  import android.media.MediaRecorder;  import android.os.Bundle;  import android.view.View;  import android.view.View.OnClick

  • Android实现语音播放与录音功能

    本文实例为大家分享了Android实现语音播放与录音的具体代码,供大家参考,具体内容如下 项目用到的技术点和亮点 语音录音 (单个和列表) 语音播放(单个和列表) 语音录音封装 语音播放器封装 语音列表顺序播放 语音列表单个播放 复用问题处理 因为安装原生录音不能录mp3格式文件 而mp3格式是安卓和ios公用的,所以我们需要的是能直接录取mp3文件或者录完的格式转成mp3格式 下面添加这个库 能直接录mp3文件,我觉得是最方便的 compile 'com.czt.mp3recorder:lib

  • Android实现录音方法(仿微信语音、麦克风录音、发送语音、解决5.0以上BUG)

    先给大家展示下效果图,如果大家感觉不错,请参考使用方法, 效果图如下所示: 使用方法: 录音工具类:AudioRecoderUtils.java,代码如下: public class AudioRecoderUtils { //文件路径 private String filePath; //文件夹路径 private String FolderPath; private MediaRecorder mMediaRecorder; private final String TAG = "fan&q

  • Android实现通话自动录音

    最近需要做一个类似于电话客户的功能,要求拨打电话能自动录音.所以写了一个dome,希望能够帮到大家. 主要思路就是监听手机通话状态在监听到接听时开始录音,结束停止录音. AndroidManifest中配置 <!-- 权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android

  • android MediaRecorder实现录屏时带录音功能

    下面说说android的事把 最近是不是也会遇到需求中需要用到录屏录音的功能,最近也是遇到的 现在整理完记录一下 首先呢,录音录屏需要权限 先贴一个动态权限类 public class TalAllow { /** * RECORD_AUDIO 音频权限 * WRITE_EXTERNAL_STORAGE 写入权限 * CAMERA 相机权限 */ public static void requestPermissions(Context context,int allowCode) { Arra

  • Android仿微信语音对讲录音功能

    自微信出现以来取得了很好的成绩,语音对讲的实现更加方便了人与人之间的交流.今天来实践一下微信的语音对讲的录音实现,这个也比较容易实现.在此,我将该按钮封装成为一个控件,并通过策略模式的方式实现录音和界面的解耦合,以方便我们在实际情况中对录音方法的不同需求(例如想要实现wav格式的编码时我们也就不能再使用MediaRecorder,而只能使用AudioRecord进行处理). 效果图: 实现思路: 1.在微信中我们可以看到实现语音对讲的是通过点按按钮来完成的,因此在这里我选择重新自己的控件使其继承

  • Android应用开发:电话监听和录音代码示例

    在oncreate 中执行: 复制代码 代码如下: public void onCreate() {  super.onCreate();  Log.i("TAG", "服务启动了"); // 对电话的来电状态进行监听  TelephonyManager telManager = (TelephonyManager) this    .getSystemService(Context.TELEPHONY_SERVICE);  // 注册一个监听器对电话状态进行监听 

  • Android音频录制MediaRecorder之简易的录音软件实现代码

    使用MediaRecorder的步骤:1.创建MediaRecorder对象2.调用MediRecorder对象的setAudioSource()方法设置声音的来源,一般传入MediaRecorder.MIC3.调用MediaRecorder对象的setOutputFormat()设置所录制的音频文件的格式4.调用MediaRecorder对象的setAudioRncoder().setAudioEncodingBitRate(int bitRate).setAudioSamlingRate(i

随机推荐