//第一步 先加权限 在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://www.bmabk.com/index.php/post/118323.html