//第一步 先加权限 在AndroidManifest.xml里:

//有打电话的权限,读写权限,还有录音权限。

<uses-permission android:name="android.permission.CALL_PHONE" /><uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

//在AndroidManifest.xml里再声明自定义的Service:<service android:name=".TelService"/>

<applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><service android:name=".TelService"/>
</application>

//第二步 自定义TelService类继承Service:

//来电录音或去电录音

//既然来电录音,当然要开启一个后台服务。

//所以先写一个TelService,然后得到TelephonyManager。

public class TelService extends Service {TelListener telListener;TelephonyManager manager;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();Log.e("TAG——TelService", "启动了。。。。。。。。。。。。。。。。。。。。。。。。。。。====------》》》》》》");if (manager == null) {manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);}if (telListener == null) {telListener = TelListener.getInstense(this);}telListener.setRecordState(true);manager.listen(telListener, PhoneStateListener.LISTEN_CALL_STATE);}@Overridepublic void onDestroy() {Log.e("TAG——TelService", "销毁了。。。。。。。。。。。。。。。。。。。。。。。。。。。====------》》》》》》");telListener.setRecordState(false);super.onDestroy();}}

//第三步 写个TelListener类继承PhoneStateListener:

//这个监听是继承PhoneStateListener,里面有个方法onCallStateChanged,这个方法一直在监听电话的状态。

//一般来电是用到三个状态CALL_STATE_IDLE:空闲

//CALL_STATE_RINGING:来电

//CALL_STATE_OFFHOOK:接通,

//一般来电的电话状态的变化是:空闲-》来电-》接通-》空闲,这是其整个过程。

//而去电时是没有CALL_STATE_RINGING: 来电这个状态的。

public class TelListener extends PhoneStateListener {private MediaRecorder mediaRecorder;private String recordPath;static boolean recordState = false;// 是否开启了服务private boolean isRecording = false;// 时候正在录音private boolean isOffhooked = false;// 是否已经接通//    private boolean isRinging = false;// 来电标识private Context context;private String number = "";private String createTime;private static TelListener telListener;private TelListener(Context context) {this.context = context;}public static TelListener getInstense(Context context) {if (telListener == null) {telListener = new TelListener(context);}return telListener;}public void setRecordState(boolean state) {recordState = state;}@Overridepublic void onCallStateChanged(int state, String incomingNumber) {super.onCallStateChanged(state, incomingNumber);if (recordState) {if (!TextUtils.isEmpty(incomingNumber)) {number = incomingNumber;}switch (state) {case TelephonyManager.CALL_STATE_IDLE:// 空闲Log.e("TAG1", "===============CALL_STATE_IDLE空闲==============");// 音频数据上传到服务器if (isRecording) {stopRecord(mediaRecorder);isRecording = false;if (!TextUtils.isEmpty(recordPath) && isOffhooked) {isOffhooked = false;//这里可以写一些录完音之后的一些后学操作//也可以写一个回调}}
//                    isRinging = false;break;case TelephonyManager.CALL_STATE_RINGING:// 来电Log.e("TAG2", "===============CALL_STATE_RINGING来电==============");
//                    isRinging = true;break;case TelephonyManager.CALL_STATE_OFFHOOK:// 接通Log.e("TAG3", "===============CALL_STATE_OFFHOOK接通==============");if (!isRecording) {startRecordAudio(number);number = "";isRecording = true;isOffhooked = true;}break;default:break;}}}/*** 描述:开始录音*/private void startRecordAudio(String number) {mediaRecorder = new MediaRecorder();// 存放的文件路径File soundFile = null;try {soundFile = new File(Environment.getExternalStorageDirectory().getCanonicalPath() + "/song");createTime = MessageFormat.format("{0,date,yyyy-MM-dd-HH-mm-ss}",new Object[]{new Date(System.currentTimeMillis())});//把号码值空if (TextUtils.isEmpty(number)) {number = "";}File file = new File(soundFile, number + "电话录音" + createTime+ ".amr");recordPath = file.getAbsolutePath();// 录音new MediaRecordUtil(context).StartMediaRecord(file, mediaRecorder);Log.e("TAGXX", file.length() + "-------------------" + recordPath.length() + "-----------------" + soundFile.length());} catch (IOException e) {e.printStackTrace();}if (!soundFile.exists()) {try {soundFile.mkdirs();} catch (Exception e) {e.printStackTrace();}}}/*** 停止录音** @param mediaRecorder*/private void stopRecord(MediaRecorder mediaRecorder) {if (mediaRecorder != null) {new MediaRecordUtil(context).StopmediaRecorder(mediaRecorder);}}
}

//第四步 写个MediaRecordUtil类继承Activity:

//接下来这个就是录音类,这里是使用的MediaRecorder,这个录音类在接通状态下执行。

public class MediaRecordUtil extends Activity {private Context mContext;public MediaRecordUtil(Context context) {mContext = context;}public void StartMediaRecord(File soundFile, MediaRecorder mediaRecorder) {// 先检测下是否含有SDCardif (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {Toast.makeText(mContext, "SD卡不存在,请插入SD卡", Toast.LENGTH_LONG).show();return;}try {// 创建音频输出的文件路径soundFile// 设置录音的来源为麦克风//       华为,酷派可以//----------------------------------重要-------------------------------------------------//VOICE_CALL:语音呼叫,VOICE_COMMUNICATION:语音通信,MIC:麦克风,VOICE_RECOGNITION:语音识别。// VOICE_DOWNLINK:语音下行链路,VOICE_UPLINK:语音上行链路。//经过我的测试发现以下问题,测试手机:红米note4。//小米手机设置MediaRecorder.AudioSource设置调用的时候,// 调用MIC可以正常保存录音,VOICE_COMMUNICATION也可以,VOICE_RECOGNITION也可以,// 但是设置为VOICE_CALL就不行,VOICE_DOWNLINK也不行,VOICE_UPLINK也不行。//如果设置成VOICE_CALL,那么保存后的文件大小会为0b,就是为空。//例如:mediaRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);//------------------------------------------------------------------------------------------if ("xiaomi".equalsIgnoreCase(android.os.Build.BRAND)) {mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);} else {mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);}// 设置录制的声音输出格式mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);// 设置声音的编码格式mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 设置录音的输出文件路径mediaRecorder.setOutputFile(soundFile.getAbsolutePath());// 做预期准备mediaRecorder.prepare();// 开始录音mediaRecorder.start();} catch (Exception e) {e.printStackTrace();}}/*** 停止录音**/public void StopmediaRecorder(MediaRecorder mediaRecorder) {try {if (mediaRecorder != null) {mediaRecorder.stop();// 释放资源mediaRecorder.release();mediaRecorder = null;}} catch (IllegalStateException e) {e.printStackTrace();}}/*** 删除录音文件**/public void DeleteAudio(File soundFile) {if (soundFile.exists()) { // 判断文件是否存在if (soundFile.isFile()) { // 判断是否是文件soundFile.delete(); // delete()方法 你应该知道 是删除的意思;}}}}

//第五步 在Activity里去电(来电时)使用:

//Activity里我写了个Button按钮,点击就打电话,并且开启这个监听的服务。在Button按钮的点击事件里,我注释了一些代码,它可以用来关闭掉这个监听服务。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {private Button btn_recorder;//拨号请求码public static final int REQUEST_CALL_PERMISSION = 10111;//布尔值用来点击按钮开启或者关闭录音boolean isOpening = false;//录音权限初始化private static final int READ_PHONE_STATE = 1;private static String[] CALLS_STATE = {Manifest.permission.READ_PHONE_STATE,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.RECORD_AUDIO,};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();//调用请求6.0录音权限的方法verifyStoragePermissions(this);}private void initView() {btn_recorder = (Button) findViewById(R.id.btn_recorder);btn_recorder.setOnClickListener(this);}//点击事件,点击开始拨打10086,并且启动了录音监听服务@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn_recorder:call("tel:" + "10086");Intent intent = new Intent(MainActivity.this, TelService.class);startService(intent);
//                if (isOpening) {
//                    stopService(intent);
//                    btn_recorder.setText("开启");
//                    isOpening = false;
//                    Toast.makeText(this, "关闭录音功能", Toast.LENGTH_SHORT).show();
//                } else {
//                    startService(intent);
//                    btn_recorder.setText("关闭");
//                    isOpening = true;
//                    Toast.makeText(this, "打开录音功能", Toast.LENGTH_SHORT).show();
//                }break;}}//打电话申请权限,public boolean checkReadPermission(String string_permission, int request_code) {boolean flag = false;
//已有权限if (ContextCompat.checkSelfPermission(this, string_permission) == PackageManager.PERMISSION_GRANTED) {flag = true;} else {
//申请权限ActivityCompat.requestPermissions(this, new String[]{string_permission}, request_code);}return flag;}//逻辑判断,是否允许打电话权限@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {switch (requestCode) {
//拨打电话case REQUEST_CALL_PERMISSION:
//失败,吐司if (permissions.length != 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {Toast.makeText(this, "请允许拨号权限后再试", Toast.LENGTH_SHORT).show();} else {
//成功,直接调用开始拨打方法call("tel:" + "10086");}break;}}//申请到权限后打电话public void call(String telPhone) {if (checkReadPermission(Manifest.permission.CALL_PHONE, REQUEST_CALL_PERMISSION)) {Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(telPhone));startActivity(intent);}}//6.0录音动态权限public static void verifyStoragePermissions(Activity activity) {int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_PHONE_STATE);if (permission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(activity, CALLS_STATE, READ_PHONE_STATE);}}}

//我的Activity布局,就一个Button按钮:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.example.hasee.a926luyin.MainActivity"><Buttonandroid:id="@+id/btn_recorder"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="录音"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></android.support.constraint.ConstraintLayout>

//最后我的这个录音的文件是存到我手机存储里了,因为我手机里SD卡,如果有SD卡那么你就去SD卡的song文件夹里找这个录音文件,如果没有SD卡,那么就去你手机存储里找这个song文件夹。   话说现在的手机应该都不装SD卡了吧!

//----------------------------------------------------------------完-----------------------------------------------------------------------

71.android 简单的电话录音并保存到本地(来电和去电都支持)相关推荐

  1. Android实现长按录音松开保存、播放及根据声贝动画展示

    Android实现长按录音松开保存及根据声贝动画展示 1.准备两张需要动态展示的图片 2.布局文件popup_window.xml 3.popup.xml 文件 4.封装MediaRecorder初始 ...

  2. android view存储为jpg,Android长按imageview把图片保存到本地的实例代码

    工具类 之前用 AsyncTask 现在改用rxJava public class SaveImageUtils { public static void imageSave(final ImageV ...

  3. Android之关于电话录音原理,目前的方法还是只能录MIC

    对于android来讲,没有API直接支持对电话进行双向录音. 虽然MediaRecorder里面可以设置recodeRecorder.setAudioSource(MediaRecorder.Aud ...

  4. android 4.0 电话录音,ANDROID音频系统散记之四:4.0音频系统HAL初探

    昨天(2011-11-15)发布了Android4.0的源码,今天download下来,开始挺进4.0时代.简单看了一下,发现音频系统方面与2.3的有较多地方不同,下面逐一描述. 一.代码模块位置 1 ...

  5. Android FFmpeg视频转码并保存到本地

    本文讲述在Android中, 如何将FFmpeg视频转码为YUV格式并保存到本地. 首先,我们基于上一篇文章 基于Android Studio3.2实现ffmpeg最简单的例子 来进行配置. 配置好之 ...

  6. html5录音怎么保存到本地,详解HTML5 录音遇到的坑

    本文恩主要介绍了详解HTML5 录音的踩坑之旅,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧,希望能帮助到大家. 说实话,一开始都没接触过 HTML5 的 Audio A ...

  7. QML for Android通过ScreenRecorder录制屏幕并保存为本地视频

    前言 最近在学习android截屏相关的知识点,找了很多资料,终于在github上找到一个源码ScreenRecorder,感谢这位哥们的无私奉献,然后又有一篇专门针对这个源码做详细讲解的文章,通过文 ...

  8. 关于android电话录音问题的详细分析

    关于android电话录音问题的详细分析 作者:老猫 一直以来都是在网络上看别人的文章,老老实实的做潜水员,今天一时兴起,写点东西,希望对大家有所帮助,不要再走同样的弯路. 本文是关于Android下 ...

  9. android service 样例(电话录音和获取系统当前时间)

    关于android service 的具体解释请參考: android四大组件--android service具体解释.以下将用两个实例具体呈现Android Service的两种实现. 一个是st ...

最新文章

  1. 挨踢(IT)脱口秀--2014年2015上半年特别“任性”的网络流行语大盘点
  2. Spring Boot - 构建数据访问层
  3. Vue页面加载使用二级属性的时候报错TypeError: Cannot read property ‘name‘ of undefined“
  4. 实现迭代型的echo服务器
  5. 基于easyui开发Web版Activiti流程定制器详解(六)——Draw2d的扩展(一)
  6. 收藏!架构师需要掌握的99条铁律
  7. 14 CO配置-控制-内部订单-维护定单编号范围
  8. 企业类库问题 public key 问题[经过自己测试]
  9. 百倍性能的PL/SQL优化案例(r11笔记第13天)
  10. 搜狗浏览器数据备份/同步工具
  11. 手把手教你在VM虚拟机上安装windows11
  12. 2.1_7 Oracle 执行计划之1_优化器(Optimizer - CBORBO)
  13. hadoop 运行过程中出现Call to localhost/127.0.0.1:9000 failed on connection exception错误。
  14. 华为手机相册怎么镜像翻转_手机相册里的最近删除怎么关
  15. 【历史上的今天】4 月 27 日:Tumblr 上线;施乐推出了 Star 工作站;第一台安德伍德打字机诞生
  16. 挺带劲!这款开源数据库迁移工具超牛逼
  17. 使用 Coinbase 在 Polygon 网络上获取 MATIC
  18. 正则表达式中级应用(java语言版)
  19. 前端 HTML(1)
  20. 程序员的创世传说 第六节 棚户区的怪人

热门文章

  1. 抖音涨粉变现最快的账号的一致性和美观性设计-阿甘电商
  2. 新年寄语丨央视主持人张腾岳为酷雷曼送祝福
  3. css选择器及其权重
  4. 触摸菜单:纸质菜单终结者
  5. Sol和IK分词器得基本使用
  6. 解决 java BufferedReader.readLine()方法按行读取文件内容中文乱码的问题
  7. 人工智能领域计算机应用的研究与探索,人工智能的研究领域与应用领域
  8. 司马懿的6句人生真谛
  9. 自学成才的开发人员可以从JD Salinger学习的6课
  10. NS3 入门环境搭建