
讯享网
//第一步 先加权限 在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"/>
讯享网<application android: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; @Override public IBinder onBind(Intent intent) { return null; } @Override public 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); } @Override public 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; } @Override public 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) { // 先检测下是否含有SDCard if (!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, }; @Override protected 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,并且启动了录音监听服务 @Override public 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; } //逻辑判断,是否允许打电话权限 @Override public 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"> <Button android: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卡了吧!
//----------------------------------------------------------------完-----------------------------------------------------------------------
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/17995.html